> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDKを使用しないJWT

export const Link = ({href, children, className, ...props}) => {
  const localizedHref = localizeLink(href);
  return <a href={localizedHref} className={className} {...props}>
      {children}
    </a>;
};

export const MultiRelatedLinks = ({sections = []}) => {
  if (!sections || sections.length === 0) {
    return null;
  }
  return <div className="space-y-8">
      {sections.map((section, index) => <RelatedLinks key={index} title={section.title} items={section.items} />)}
    </div>;
};

export const RelatedLinks = ({title, items = []}) => {
  const getBadgeClass = badge => {
    if (!badge) return "badge-default";
    const badgeType = badge.toLowerCase().replace(/\s+/g, "-");
    return `badge-${badge === "ガイド" ? "guide" : badgeType}`;
  };
  if (!items || items.length === 0) {
    return null;
  }
  return <div className="my-8">
      {}
      <h3 className="text-sm font-bold uppercase tracking-wider mb-4">{title}</h3>

      {}
      <div className="flex flex-col gap-3">
        {items.map((item, index) => <a key={index} href={item.href} className="py-2 px-3 rounded related_link hover:bg-[#f2f2f2] dark:hover:bg-[#111827] flex items-center gap-3 group no-underline hover:no-underline border-b-0">
            {}
            <span className={`px-2 py-1 rounded-full text-xs font-semibold uppercase tracking-wide flex-shrink-0 ${getBadgeClass(item.badge)}`}>
              {item.badge}
            </span>

            {}
            <span className="text-base">{item.label}</span>
          </a>)}
      </div>
    </div>;
};

<RelatedLinks
  title="必須のガイド"
  items={[
{ label: translate("Select Auth Method"), href: "/guides/authentication/select", badge: "GUIDE" },
{ label: translate("Setup with OAuth 2.0"), href: "/guides/authentication/oauth2/oauth2-setup", badge: "GUIDE" }
]}
/>

このガイドでは、Box SDKを使用しないJWT認証について説明します。JWTはエンドユーザーによる操作を必要とせず、Box APIで直接認証するよう設計されています。

このトークンの使用方法を確認するには、<Link href="/guides/api-calls">APIコールの実行</Link>に関するガイドを参照してください。

<Note>
  デフォルトでは、JWTを使用して取得したアクセストークンは、アプリケーションのサービスアカウントに関連付けられています。このトークンを使用して実行されるAPIコールはすべて、このアプリケーションから実行されます。アプリケーションのサービスアカウントがコラボレータとして追加されるまで、このアカウントでは、既存のファイルやフォルダにアクセスできません。

  `as-user`ヘッダーを使用するか<Link href="/guides/authentication/jwt/user-access-tokens">ユーザーアクセストークン</Link>をリクエストして、<Link href="/guides/authentication/oauth2/as-user">別のユーザーとして処理を実行</Link>できます。
</Note>

## キーペアの使用

公開キーと秘密キーのペアを使用してアプリケーションのIDを確認する場合は、以下の手順に従います。

### 前提条件

* [開発者コンソール][devconsole]でJWT認証を使用するPlatformアプリケーション
* `config.json`という名前の秘密キー構成ファイル ([開発者コンソール][devconsole]の \[構成] タブからダウンロード可能)
* Box管理コンソールでアプリケーションが<Link href="/guides/authorization">承認</Link>されていること

### 1. JSON構成を読み取る

`config.json`ファイルには、アプリケーションの秘密キーと、認証に必要なその他の詳細が含まれています。このファイルの例を以下に示します。

```json config.json theme={null}
{
  "boxAppSettings": {
    "clientID": "abc...123",
    "clientSecret": "def...234",
    "appAuth": {
      "publicKeyID": "abcd1234",
      "privateKey": "-----BEGIN ENCRYPTED PRIVATE KEY-----\n....\n-----END ENCRYPTED PRIVATE KEY-----\n",
      "passphrase": "ghi...345"
    }
  },
  "enterpriseID": "1234567"
}
```

このオブジェクトをアプリケーションで使用するには、ファイルから読み取る必要があります。

<CodeGroup>
  ```csharp .Net theme={null}
  using System;
  using System.IO;
  using Newtonsoft.Json;

  class Config
  {
      public class BoxAppSettings {
          public class AppAuth {
              public string privateKey { get; set; }
              public string passphrase { get; set; }
              public string publicKeyID { get; set; }
          }
          public string clientID { get; set; }
          public string clientSecret { get; set; }
          public AppAuth appAuth { get; set; }

      }
      public string enterpriseID { get; set; }
      public BoxAppSettings boxAppSettings { get; set; }
  }

  var reader = new StreamReader("config.json");
  var json = reader.ReadToEnd();

  var config = JsonConvert.DeserializeObject<Config>(json);
  ```

  ```java Java theme={null}
  import java.io.FileReader;

  import com.google.gson.Gson;
  import com.google.gson.GsonBuilder;

  class Config {
      class BoxAppSettings {
          class AppAuth {
              String privateKey;
              String passphrase;
              String publicKeyID;
          }

          String clientID;
          String clientSecret;
          AppAuth appAuth;
      }

      BoxAppSettings boxAppSettings;
      String enterpriseID;
  }

  FileReader reader = new FileReader("config.json");

  Gson gson = new GsonBuilder().create();
  Config config = (Config) gson.fromJson(reader, Config.class);
  ```

  ```python Python 3 theme={null}
  import json
  import os

  config = json.load(open('config.json'))
  ```

  ```js Node  theme={null}
  const fs = require("fs");

  const config = JSON.parse(fs.readFileSync("config.json"));
  ```

  ```ruby Ruby theme={null}
  require 'json'

  config = JSON.parse(
    File.read('config.json')
  )
  ```

  ```php PHP theme={null}
  $json = file_get_contents('config.json');
  $config = json_decode($json);
  ```
</CodeGroup>

<Info>
  **JSONの解析**

  プログラミング言語によっては、ファイルからJSONを読み取って解析する方法が複数ある場合があります。エラー処理など、さらに詳細な説明については、使用するプログラミング言語のガイドを参照してください。
</Info>

### 2. 秘密キーを復号化する

JWTアサーションを作成するために、アプリケーションでは構成オブジェクトにある秘密キーが必要になります。この秘密キーは暗号化されており、ロックを解除するにはパスコードが必要です。暗号化されたキーとパスコードは両方とも、構成オブジェクトで指定されています。

<CodeGroup>
  ```csharp .Net theme={null}
  using System.Security.Cryptography;
  using Org.BouncyCastle.OpenSsl;
  using Org.BouncyCastle.Crypto.Parameters;
  using Org.BouncyCastle.Math;

  // https://www.bouncycastle.org/csharp/index.html
  class PasswordFinder : IPasswordFinder
  {
      private string password;
      public PasswordFinder(string _password) { password = _password; }
      public char[] GetPassword() { return password.ToCharArray(); }
  }

  var appAuth = config.boxAppSettings.appAuth;
  var stringReader = new StringReader(appAuth.privateKey);
  var passwordFinder = new PasswordFinder(appAuth.passphrase);
  var pemReader = new PemReader(stringReader, passwordFinder);
  var keyParams = (RsaPrivateCrtKeyParameters) pemReader.ReadObject();

  public RSA CreateRSAProvider(RSAParameters rp)
  {
      var rsaCsp = RSA.Create();
      rsaCsp.ImportParameters(rp);
      return rsaCsp;
  }

  public RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
  {
      RSAParameters rp = new RSAParameters();
      rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
      rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
      rp.P = privKey.P.ToByteArrayUnsigned();
      rp.Q = privKey.Q.ToByteArrayUnsigned();
      rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
      rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
      rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
      rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
      return rp;
  }

  public byte[] ConvertRSAParametersField(BigInteger n, int size)
  {
      byte[] bs = n.ToByteArrayUnsigned();
      if (bs.Length == size)
          return bs;
      if (bs.Length > size)
          throw new ArgumentException("Specified size too small", "size");
      byte[] padded = new byte[size];
      Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
      return padded;
  }

  var key = CreateRSAProvider(ToRSAParameters(keyParams));
  ```

  ```java Java theme={null}
  import java.io.StringReader;
  import java.security.PrivateKey;
  import java.security.Security;

  import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
  import org.bouncycastle.jce.provider.BouncyCastleProvider;
  import org.bouncycastle.openssl.PEMParser;
  import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
  import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
  import org.bouncycastle.operator.InputDecryptorProvider;
  import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;

  // https://www.bouncycastle.org/java.html
  Security.addProvider(new BouncyCastleProvider());

  PEMParser pemParser = new PEMParser(
      new StringReader(config.boxAppSettings.appAuth.privateKey)
  );
  Object keyPair = pemParser.readObject();
  pemParser.close();

  char[] passphrase = config.boxAppSettings.appAuth.passphrase.toCharArray();
  JceOpenSSLPKCS8DecryptorProviderBuilder decryptBuilder =
      new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider("BC");
  InputDecryptorProvider decryptProvider
      = decryptBuilder.build(passphrase);
  PrivateKeyInfo keyInfo
      = ((PKCS8EncryptedPrivateKeyInfo) keyPair).decryptPrivateKeyInfo(decryptProvider);

  PrivateKey key = (new JcaPEMKeyConverter()).getPrivateKey(keyInfo);
  ```

  ```python Python 3 theme={null}
  from cryptography.hazmat.backends import default_backend
  from cryptography.hazmat.primitives.serialization import load_pem_private_key

  appAuth = config["boxAppSettings"]["appAuth"]
  privateKey = appAuth["privateKey"]
  passphrase = appAuth["passphrase"]

  # https://cryptography.io/en/latest/
  key = load_pem_private_key(
      data=privateKey.encode('utf8'),
      password=passphrase.encode('utf8'),
      backend=default_backend(),
  )
  ```

  ```js Node  theme={null}
  let key = {
      key: config.boxAppSettings.appAuth.privateKey,
      passphrase: config.boxAppSettings.appAuth.passphrase,
  };
  ```

  ```ruby Ruby theme={null}
  require "openssl"

  appAuth = config['boxAppSettings']['appAuth']
  key = OpenSSL::PKey::RSA.new(
    appAuth['privateKey'],
    appAuth['passphrase']
  )
  ```

  ```php PHP theme={null}
  $private_key = $config->boxAppSettings->appAuth->privateKey;
  $passphrase = $config->boxAppSettings->appAuth->passphrase;
  $key = openssl_pkey_get_private($private_key, $passphrase);
  ```
</CodeGroup>

<Info>
  **ファイルから秘密キーを読み込むための代替方法**

  アプリケーションでは、秘密キーとパスワードの両方をディスクに保存しておきたくない場合があります。代替方法として、パスワードを環境変数として渡し、秘密キーを、秘密キーのロックを解除するためのトークンと分けておくこともできます。
</Info>

### 3. JWTアサーションを作成する

Box APIで認証するために、アプリケーションは、アクセストークンと交換できる署名済みのJWTアサーションを作成する必要があります。

JWTアサーションは、暗号化されたJSONオブジェクトで、`header`、`claims`、および`signature`で構成されます。最初に`claims`を作成します。これは、`payload`とも呼ばれる場合もあります。

<CodeGroup>
  ```csharp .Net theme={null}
  using System.IdentityModel.Tokens.Jwt;
  using System.Security.Claims;
  using System.Collections.Generic;

  byte[] randomNumber = new byte[64];
  RandomNumberGenerator.Create().GetBytes(randomNumber);
  var jti = Convert.ToBase64String(randomNumber);

  DateTime expirationTime = DateTime.UtcNow.AddSeconds(45);

  var claims = new List<Claim>{
      new Claim("sub", config.enterpriseID),
      new Claim("box_sub_type", "enterprise"),
      new Claim("jti", jti),
  };
  ```

  ```java Java theme={null}
  import org.jose4j.jwt.JwtClaims;

  String authenticationUrl = "https://api.box.com/oauth2/token";

  JwtClaims claims = new JwtClaims();
  claims.setIssuer(config.boxAppSettings.clientID);
  claims.setAudience(authenticationUrl);
  claims.setSubject(config.enterpriseID);
  claims.setClaim("box_sub_type", "enterprise");
  claims.setGeneratedJwtId(64);
  claims.setExpirationTimeMinutesInTheFuture(0.75f);
  ```

  ```python Python 3 theme={null}
  import time
  import secrets

  authentication_url = 'https://api.box.com/oauth2/token'

  claims = {
      'iss': config['boxAppSettings']['clientID'],
      'sub': config['enterpriseID'],
      'box_sub_type': 'enterprise',
      'aud': authentication_url,
      'jti': secrets.token_hex(64),
      'exp': round(time.time()) + 45
  }
  ```

  ```js Node  theme={null}
  const crypto = require("crypto");

  const authenticationUrl = "https://api.box.com/oauth2/token";

  let claims = {
      iss: config.boxAppSettings.clientID,
      sub: config.enterpriseID,
      box_sub_type: "enterprise",
      aud: authenticationUrl,
      jti: crypto.randomBytes(64).toString("hex"),
      exp: Math.floor(Date.now() / 1000) + 45,
  };
  ```

  ```ruby Ruby theme={null}
  require 'securerandom'

  authentication_url = 'https://api.box.com/oauth2/token'

  claims = {
    iss: config['boxAppSettings']['clientID'],
    sub: config['enterpriseID'],
    box_sub_type: 'enterprise',
    aud: authentication_url,
    jti: SecureRandom.hex(64),
    exp: Time.now.to_i + 45
  }
  ```

  ```php PHP theme={null}
  $authenticationUrl = 'https://api.box.com/oauth2/token';

  $claims = [
    'iss' => $config->boxAppSettings->clientID,
    'sub' => $config->enterpriseID,
    'box_sub_type' => 'enterprise',
    'aud' => $authenticationUrl,
    'jti' => base64_encode(random_bytes(64)),
    'exp' => time() + 45,
    'kid' => $config->boxAppSettings->appAuth->publicKeyID
  ];
  ```
</CodeGroup>

| パラメータ               | 型       | 説明                                                                                         |
| ------------------- | ------- | ------------------------------------------------------------------------------------------ |
| `iss` (必須)          | String  | BoxアプリケーションのOAuthクライアントID                                                                  |
| `sub` (必須)          | String  | Box Enterprise ID (このアプリがそのアプリケーションのサービスアカウントの代わりになる場合) またはユーザーID (このアプリが別のユーザーの代わりになる場合)。 |
| `box_sub_type` (必須) | String  | `enterprise`または`user` (`sub`クレームでリクエストされているトークンの種類に応じて決定)                                  |
| `aud` (必須)          | String  | 常に`https://api.box.com/oauth2/token`                                                       |
| `jti` (必須)          | String  | このJWTに対してアプリケーションで指定されたUUID (Universally Unique Identifier)。16文字以上128文字以下の一意の文字列です。        |
| `exp` (必須)          | Integer | このJWTが期限切れとなるUnix時間。設定できる最大値は、発行時刻から60秒後です。許容される最大値よりも小さい値を設定することをお勧めします。                  |
| `iat` (省略可)         | Integer | 発行時刻。トークンは、この時刻より前に使用することはできません。                                                           |
| `nbf` (省略可)         | Integer | 開始時刻。トークンの有効期間の開始時刻を指定します。                                                                 |

次に、秘密キーを使用してこれらのクレームに署名する必要があります。使用する言語とライブラリに応じて、クレームの署名に使用する暗号化アルゴリズムと公開キーのIDを定義することで、JWTの`header`が構成されます。

<CodeGroup>
  ```csharp .Net theme={null}
  using Microsoft.IdentityModel.Tokens;

  String authenticationUrl = "https://api.box.com/oauth2/token";

  var payload = new JwtPayload(
      config.boxAppSettings.clientID,
      authenticationUrl,
      claims,
      null,
      expirationTime
  );

  var credentials = new SigningCredentials(
      new RsaSecurityKey(key),
      SecurityAlgorithms.RsaSha512
  );
  var header = new JwtHeader(signingCredentials: credentials);

  var jst = new JwtSecurityToken(header, payload);
  var tokenHandler = new JwtSecurityTokenHandler();
  string assertion = tokenHandler.WriteToken(jst);
  ```

  ```java Java theme={null}
  import org.jose4j.jws.AlgorithmIdentifiers;
  import org.jose4j.jws.JsonWebSignature;

  JsonWebSignature jws = new JsonWebSignature();
  jws.setPayload(claims.toJson());
  jws.setKey(key);

  jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA512);
  jws.setHeader("typ", "JWT");
  jws.setHeader("kid", config.boxAppSettings.appAuth.publicKeyID);
  String assertion = jws.getCompactSerialization();
  ```

  ```python Python 3 theme={null}
  import jwt

  keyId = config['boxAppSettings']['appAuth']['publicKeyID']

  assertion = jwt.encode(
      claims,
      key,
      algorithm='RS512',
      headers={
          'kid': keyId
      }
  )
  ```

  ```js Node  theme={null}
  const jwt = require("jsonwebtoken");

  let keyId = config.boxAppSettings.appAuth.publicKeyID;

  let headers = {
      algorithm: "RS512",
      keyid: keyId,
  };

  let assertion = jwt.sign(claims, key, headers);
  ```

  ```ruby Ruby theme={null}
  require 'jwt'
  keyId = appAuth['publicKeyID']
  assertion = JWT.encode(claims, key, 'RS512', { kid: keyId })
  ```

  ```php PHP theme={null}
  use \Firebase\JWT\JWT;
  $assertion = JWT::encode($claims, $key, 'RS512');
  ```
</CodeGroup>

ヘッダーでは、以下のパラメータがサポートされます。

| パラメータ            | 型      | 説明                                                               |
| ---------------- | ------ | ---------------------------------------------------------------- |
| `algorithm` (必須) | String | JWTクレームへの署名に使用する暗号化アルゴリズム。RS256、RS384、RS512のいずれかを指定できます。         |
| `keyid` (必須)     | String | JWTへの署名に使用する公開キーのID。必須ではありませんが、アプリケーションに対して複数のキーペアが定義される場合は必須です。 |

<Info>
  JWTライブラリの使用

  独自のJWTへの署名は、複雑で手間のかかる処理になる可能性があります。そのようなことがないよう、事前にこの処理を済ませたライブラリがほぼすべての言語で用意されています。概要については、<Link href="https://jwt.io/">JWT.io</Link>をご覧ください。
</Info>

### 4. アクセストークンをリクエストする

最後の手順として、有効期間の短いJWTアサーションを、より有効期間の長いアクセストークンと交換します。これには、アサーションをパラメータに指定してトークンエンドポイントを呼び出します。

<CodeGroup>
  ```csharp .Net theme={null}
  using System.Net;
  using System.Net.Http;

  var content = new FormUrlEncodedContent(new[]
  {
      new KeyValuePair<string, string>(
          "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
      new KeyValuePair<string, string>(
          "assertion", assertion),
      new KeyValuePair<string, string>(
          "client_id", config.boxAppSettings.clientID),
      new KeyValuePair<string, string>(
          "client_secret", config.boxAppSettings.clientSecret)
  });

  var client = new HttpClient();
  var response = client.PostAsync(authenticationUrl, content).Result;

  class Token
  {
      public string access_token { get; set; }
  }

  var data = response.Content.ReadAsStringAsync().Result;
  var token = JsonConvert.DeserializeObject<Token>(data);
  var accessToken = token.access_token;
  ```

  ```java Java theme={null}
  import java.util.ArrayList;
  import java.util.List;

  import org.apache.http.HttpEntity;
  import org.apache.http.NameValuePair;
  import org.apache.http.client.entity.UrlEncodedFormEntity;
  import org.apache.http.client.methods.CloseableHttpResponse;
  import org.apache.http.client.methods.HttpPost;
  import org.apache.http.impl.client.CloseableHttpClient;
  import org.apache.http.impl.client.HttpClientBuilder;
  import org.apache.http.message.BasicNameValuePair;
  import org.apache.http.util.EntityUtils;

  List<NameValuePair> params = new ArrayList<NameValuePair>();

  params.add(new BasicNameValuePair(
      "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"));
  params.add(new BasicNameValuePair(
      "assertion", assertion));
  params.add(new BasicNameValuePair(
      "client_id", config.boxAppSettings.clientID));
  params.add(new BasicNameValuePair(
      "client_secret", config.boxAppSettings.clientSecret));

  CloseableHttpClient httpClient =
      HttpClientBuilder.create().disableCookieManagement().build();
  HttpPost request = new HttpPost(authenticationUrl);
  request.setEntity(new UrlEncodedFormEntity(params));
  CloseableHttpResponse httpResponse = httpClient.execute(request);
  HttpEntity entity = httpResponse.getEntity();
  String response = EntityUtils.toString(entity);
  httpClient.close();

  class Token {
      String access_token;
  }

  Token token = (Token) gson.fromJson(response, Token.class);
  String accessToken = token.access_token;
  ```

  ```python Python 3 theme={null}
  import json
  import requests

  params = {
      'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      'assertion': assertion,
      'client_id': config['boxAppSettings']['clientID'],
      'client_secret': config['boxAppSettings']['clientSecret']
  }
  response = requests.post(authentication_url, params)
  access_token = response.json()['access_token']
  ```

  ```js Node  theme={null}
  const axios = require("axios");
  const querystring = require("querystring");

  let accessToken = await axios
      .post(
          authenticationUrl,
          querystring.stringify({
              grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
              assertion: assertion,
              client_id: config.boxAppSettings.clientID,
              client_secret: config.boxAppSettings.clientSecret,
          })
      )
      .then((response) => response.data.access_token);
  ```

  ```ruby Ruby theme={null}
  require 'json'
  require 'uri'
  require 'net/https'

  params = URI.encode_www_form({
    grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    assertion: assertion,
    client_id: config['boxAppSettings']['clientID'],
    client_secret: config['boxAppSettings']['clientSecret']
  })

  uri = URI.parse(authentication_url)
  http = Net::HTTP.start(uri.host, uri.port, use_ssl: true)
  request = Net::HTTP::Post.new(uri.request_uri)
  request.body = params
  response = http.request(request)

  access_token = JSON.parse(response.body)['access_token']
  ```

  ```php PHP theme={null}
  use GuzzleHttp\Client;

  $params = [
    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    'assertion' => $assertion,
    'client_id' => $config->boxAppSettings->clientID,
    'client_secret' => $config->boxAppSettings->clientSecret
  ];

  $client = new Client();
  $response = $client->request('POST', $authenticationUrl, [
    'form_params' => $params
  ]);

  $data = $response->getBody()->getContents();
  $access_token = json_decode($data)->access_token;
  ```
</CodeGroup>

## コードサンプル

このガイドに記載されているコードは、[GitHub][samples]で入手できます。

[samples]: https://github.com/box-community/samples-docs-authenticate-with-jwt-api

[devconsole]: https://app.box.com/developers/console

[configfile]: /guides/authentication/jwt/jwt-setup/#jwt-keypair

[ccg]: /guides/authentication/jwt/without-sdk/#client-credentials-grant

<RelatedLinks
  title="関連するAPI"
  items={[
{ label: translate("Authorize user"), href: "/reference/get-authorize", badge: "GET" }
]}
/>

<RelatedLinks
  title="関連するガイド"
  items={[
{ label: translate("Platform App"), href: "/guides/applications/platform-apps/index", badge: "GUIDE" },
{ label: translate("Select Auth Method"), href: "/guides/authentication/select", badge: "GUIDE" },
{ label: translate("Setup with OAuth 2.0"), href: "/guides/authentication/oauth2/oauth2-setup", badge: "GUIDE" }
]}
/>
