Loading
ただいま大変多くのお問い合わせをいただいており、ご連絡までにお時間を頂戴しております続きを読む
ユーザーの識別およびアクセス権の管理
サーバー間インテグレーション用の OAuth 2.0 JWT ベアラーフロー

サーバー間インテグレーション用の OAuth 2.0 JWT ベアラーフロー

サーバーが情報交換するたびに対話形式のログインをしなくてもデータにアクセスすることを承認したい場合があります。このような場合は、OAuth 2.0 JSON Web トークン (JWT) ベアラーフローを使用できます。このフローは、証明書を使用して JWT 要求に署名し、明示的なユーザー操作を必要としません。ただし、このフローには、クライアントアプリケーションの事前承認が必要です。

必要なエディション

使用可能なインターフェース: Salesforce Classic および Lightning Experience の両方
使用可能なエディション: すべてのエディション

OAuth 2.0 JWT ベアラートークンフローを使用した場合、クライアントは Salesforce OAuth トークンエンドポイントに JWT を POST します。Salesforce が処理する JWT にはデジタル署名が含まれ、アプリケーションの前の承認に基づいてアクセストークンが発行されます。

次の例は、フローで実行される手順を示しています。

  1. レポートサービスが、夜間のバッチレポートを開始します。
  2. 接続アプリケーションは、Salesforce トークンエンドポイントに JWT を送信します。JWT は、ID とセキュリティ情報をセキュリティドメインで共有できるようにします。
  3. Salesforce が、以前に設定された証明書と追加のパラメーターを使用して、署名を基に JWT を検証します。
  4. JWT が有効で、接続アプリケーションに事前承認があるものとして、Salesforce がアクセストークンを発行します。事前承認は、次のいずれかの方法で行われます。
    • 接続アプリケーションポリシーが [管理者が承認したユーザーは事前承認済み] に設定されている場合、プロファイルと権限セットを使用できます。
    • 接続アプリケーションポリシーが [すべてのユーザーは自己承認可能] に設定されている場合、エンドユーザー承認および更新トークンの発行を使用できます。ただし、クライアントは現在の更新トークンまたは保存された更新トークンを必要としません。また、クライアントはクライアントの秘密をトークンエンドポイントに渡す必要もありません。
    メモ
    メモ どちらの場合も、Salesforce は元のアクセストークンに少なくとも 1 つ refresh_token 範囲以外の標準の範囲が含まれている場合のみ新しいアクセストークンを発行します。
  5. 接続アプリケーションがアクセストークンを使用して、Salesforce サーバー上の保護されているデータにアクセスします。
  6. レポートサービスが、承認されたデータを夜間のレポートに取り込みます。
メモ
メモ このフローでは、更新トークンが発行されることはありません。

この認証フローの各ステップを見ていきましょう。

JWT の作成

Salesforce では、署名の秘密としてアップロードされた証明書を使用する RSA SHA256 を使用して JWT が署名されている必要があります。この認証フローを使用する前に、必ず次の手順を実行します。

  • X509 証明書を Java キーストア (JKS) にアップロードする。証明書サイズは 4 KB を超えることはできません。超える場合、DER エンコードファイルを使用して、サイズを削減してください。
  • 接続アプリケーションの X509 証明書を登録する。この証明書はアプリケーションの非公開鍵に対応しています。接続アプリケーションを保存すると、client_idclient_secretが生成され、アプリケーションに割り当てられます。
  • JWT を生成するアプリケーションを作成する。JWT は X509 証明書の非公開鍵を使用して署名されます。関連付けられた接続アプリケーションは証明書を使用して署名を検証します。JWT は https://tools.ietf.org/html/rfc7519 で規定されている一般的な形式のルールに準拠する必要がある。
    メモ
    メモ Salesforce は JWT ベアラートークン内の JWT ID (JTI) 要求を必要としません。ただし、JWT ベアラートークン内で JTI 要求を渡した場合、Salesforce は、JTI 要求が以前に送信されていないことを検証します。この検証により、JWT リプレイ攻撃が回避されます。

有効な JWT を作成する手順は、次のとおりです。

  1. JWT ヘッダーを次の形式で作成します。{"alg":"RS256"}
  2. http://tools.ietf.org/html/rfc4648#page-7 の定義に従って JWT ヘッダーを Base64url エンコードします。結果は eyJhbGciOiJSUzI1NiJ9 と類似しています。
  3. 次のパラメーターを使用して、JWT の JSON 要求セットを作成します。
    パラメーター説明
    iss 発行者には、証明書を登録した接続アプリケーションの OAuth client_idが含まれている必要があります。
    aud

    利用者は認証サーバーを対象利用者として識別します。認証サーバーは、これがトークンの対象利用者であることを確認する必要があります。

    利用者の値には認証サーバーの URL https://login.salesforce.comhttps://test.salesforce.com、または https://site.force.com/customers (Experience Cloud サイトに実装する場合) を使用します。

    sub

    このフローを Experience Cloud サイトに実装している場合、対象ユーザーにはユーザーのユーザー名が含まれている必要があります。

    後方互換性のために、ユーザーは件名 (prn) の代わりに主要 (sub) を使用することもできます。両方が指定されている場合、prn が使用されます。

    exp トークンが期限切れになる日時 (UTC で測定された 1970-01-01T0:0:0Z からの秒数として表記)。Salesforce ではクロックスキューに 3 分間のバッファが許容されます。たとえば、有効期限が 1,735,743,600 秒または 2025 年 1 月 1 日 15:00:00 UTC に設定されている場合、トークンはこの日付の 15:03:00 UTC まで有効です。
    JWT の JSON 要求セットの例を次に示します。
    {"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ
    ukXnVjzRgSuQqGn75NL7yfkQcyy7", 
    "sub": "my@email.com", 
    "aud": "https://login.salesforce.com", 
    "exp": "1333685628"}
  4. JWT 要求セットを改行なしで Base64url エンコードします。次に例を示します。
    eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
    Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
    Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
    Njg1NjI4In0=
  5. エンコードされた JWT ヘッダーおよびエンコードされた JWT 要求セットの文字列を次の形式で作成します。
    encoded_JWT_Header + "." + encoded_JWT_Claims_Set
    次の例では、エンコードされた JWT ヘッダーが強調表示されています。
    eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
    Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
    Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
    Njg1NjI4In0=
  6. JKS から X509 証明書をダウンロードします。
  7. 結果の文字列に RSA SHA256 を使用して署名します。
  8. 次の形式で、このステップの文字列を作成します。
    existing_string + "." + base64_encoded_signature
    次の例では、base64 でエンコードされた署名が強調表示されています。
    eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
    Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
    Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
    Njg1NjI4In0=.iYCthqWCQucwi35yFs-nWNgpF5NA_a46fXDTNIY8ACko6BaEtQ9E6h4Hn1l_pcwcK​
    I_GlmfUO2dJDg1A610t09TeoPagJsZDm_H83bsoZUoI8LpAA1s-2aj_Wbysqb1j4uDToz​
    480WtEbkwIv09sIeS_-QuWak2RXOl1Krnf72mpVGS4WWSULodgNzlKHHyjAMAHiBHIDNt​
    36y2L2Bh7M8TNWiKa_BNM6s1FNKDAwHEWQrNtAeReXgRy0MZgQY2rZtqT2FcDyjY3JVQb​
    En_CSjH2WV7ZlUwsKHqGfI7hzeEvVdfOjH9NuaJozxvhPF489IgW6cntPuT2V647JWi7ng

次の Java コードは JWT ベアラートークンの簡単な作成例です。

import org.apache.commons.codec.binary.Base64;
import java.io.*; 
import java.security.*; 
import java.text.MessageFormat;  

public class JWTExample {

  public static void main(String[] args) {

    String header = "{\"alg\":\"RS256\"}";
    String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\", \"jti\": \"{4}\"'}'";

    try {
      StringBuffer token = new StringBuffer();

      //Encode the JWT Header and add it to our string to sign
      token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8")));

      //Separate with a period
      token.append(".");

      //Create the JWT Claims Object
      String[] claimArray = new String[5];
      claimArray[0] = "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQukXnVjzRgSuQqGn75NL7yfkQcyy7";
      claimArray[1] = "my@email.com";
      claimArray[2] = "https://login.salesforce.com";
      claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
      claimArray[4]=<JTI>
      MessageFormat claims;
      claims = new MessageFormat(claimTemplate);
      String payload = claims.format(claimArray);

      //Add the encoded claims object
      token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8")));

      //Load the private key from a keystore
      KeyStore keystore = KeyStore.getInstance("JKS");
      keystore.load(new FileInputStream("./path/to/keystore.jks"), "keystorepassword".toCharArray());
      PrivateKey privateKey = (PrivateKey) keystore.getKey("certalias", "privatekeypassword".toCharArray());

      //Sign the JWT Header + "." + JWT Claims Object
      Signature signature = Signature.getInstance("SHA256withRSA");
      signature.initSign(privateKey);
      signature.update(token.toString().getBytes("UTF-8"));
      String signedPayload = Base64.encodeBase64URLSafeString(signature.sign());

      //Separate with a period
      token.append(".");

      //Add the encoded signature
      token.append(signedPayload);

      System.out.println(token.toString());

    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

アクセストークンの要求

アクセストークンを要求するために、接続アプリケーションはトークン要求を Salesforce インスタンスのトークンエンドポイントに POST します。POST には JWT が含まれます。

次の例は、トークン要求のサンプルを示しています。

POST /services/oauth2/token HTTP/1.1
Host: login.example.com
Content-Type: application/x-www-form-urlencoded

grant_type= urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=eyJpc3MiOiAiM01WRz...[omitted for brevity]...ZT
重要
重要 OAuth インテグレーションを開発するときは、常に機密情報を POST 要求の本文または要求ヘッダーで渡します。機密情報を渡すために URL クエリ文字列で GET パラメーターを使用しないでください。機密情報には、ユーザー名、パスワード、OAuth トークン、クライアントの秘密、個人識別情報が含まれますが、これらに限定されません。セキュリティのベストプラクティスについての詳細は、『Secure Coding Guide (セキュアコーディングガイド)』の「Storing Sensitive Data (機密データの保存)」を参照してください。

POST に次のパラメーターを含めます。

パラメーター 説明
grant_type 付与種別に次の値を使用します。urn:ietf:params:oauth:grant-type:jwt-bearer
assertion アサーションは JWT の値全体です。
format

(省略可能) 予測される戻り形式を指定するために使用します。このパラメーターは、要求のヘッダーを上書きします。次の形式がサポートされます。

  • urlencoded
  • json (デフォルト)
  • xml

範囲パラメーター

JWT ベアラートークンフローで範囲を指定することはできません。範囲は、接続アプリケーションの [許可されているユーザー] ポリシーまたは組織の [API アクセスコントロール] 設定に従って発行されます (次の表を参照)。

設定 結果
[許可されているユーザー] ポリシー: すべてのユーザーは自己承認可能 認証が成功すると、アクセストークンと共に返される範囲が前の承認の範囲から取得されます。
[許可されているユーザー] ポリシー: 管理者が承認したユーザーは事前承認済み 接続アプリケーションに割り当てられた標準範囲とカスタム範囲がアクセストークンと共に返されます。
API アクセスコントロール: 組織の接続アプリケーションを許可リストに登録する

接続アプリケーションに割り当てられた標準範囲とカスタム範囲がアクセストークンと共に返されます。組織の接続アプリケーションを許可リストに登録していても、予期される範囲を受信しない場合は、次の手順を実行します。

  • [設定] から、[クイック検索] ボックスに「OAuth」と入力し、[接続アプリケーションの OAuth の利用状況] を選択します。
  • 許可リストに登録された接続アプリケーションで、[ブロック] をクリックします。
  • 許可リストに登録された接続アプリケーションで、[ブロック解除] をクリックします。

Salesforce によるアクセストークンの付与

OAuth 2.0 JWT ベアラーおよび SAML アサーションベアラーフロー要求は、更新トークンを含むユーザーの以前のすべての承認を確認します。一致する承認が見つかった場合、Salesforce は承認された範囲の値を組み合わせます。次に、Salesforce はアクセストークンを発行します。更新トークンまたは承認された使用可能な範囲を含んでいた以前の承認が見つからない場合、要求は未認証として失敗します。

確認が成功すると、Salesforce インスタンスは接続アプリケーションに応答を送信します。OAuth 2.0 JWT ベアラートークンフローのトークン応答は、認証コードフローと同じ形式に従っていますが、更新トークンが発行されることはありません。

次の例は、Salesforce からの応答を示しています。

{"access_token":"00Dxx0000001gPL!AR8AQJXg5oj8jXSgxJfA0lBog.
39AsX.LVpxezPwuX5VAIrrbbHMuol7GQxnMeYMN7cj8EoWr78nt1u44zU31
IbYNNJguseu",
"scope":"web openid api id","instance_url":"
https://yourInstance.salesforce.com","id":"
https://yourInstance.salesforce.com
/id/00Dxx0000001gPLEAY/005xx000001SwiUAAS","token_type":"Bearer"}

次のパラメーターはレスポンスボディ内にあります。

パラメーター説明
access_token 接続アプリケーションがクライアントアプリケーションの代わりに保護されたリソースへのアクセスを要求するために使用する OAuth トークン。範囲の形式の追加権限にはアクセストークンが付随することがあります。
token_type Bearer トークン種別。アクセストークンを含むすべての応答で使用します。
scope 範囲は、接続アプリケーションの [許可されているユーザー] ポリシーまたは組織の [API アクセスコントロール] 設定に従って発行されます。「範囲パラメーター」を参照してください。
instance_url ユーザーの組織のインスタンスを示す URL。例: https://yourInstance.salesforce.com/
id ユーザーを識別し、ユーザーの詳細を照会するために使用できる ID URL。「ID URL」を参照してください。
sfdc_site_url ユーザーが Experience Cloud サイトのメンバーである場合、サイトの URL が提供されます。
sfdc_site_id ユーザーが Experience Cloud サイトのメンバーである場合、ユーザーのサイト ID が提供されます。Experience Cloud サイトの場合、このフローにはトークンエンドポイントの "sfdc_site_id" 値が含まれます。このサイト ID は、Connect REST API 要求で必要になる場合があります。

保護されたデータへのアクセス

接続アプリケーションは access_token を受信したら、認証ヘッダー要求でベアラートークンとして渡すことができます。次の例は、Experience Cloud サイトへの REST API コールを示しています。


          https://site.force.com/customers/services/data/v32.0/ -H 
"Authorization: Bearer 00D50000000IehZ\!AQcAQH0dMHZfz972Szmpkb58urFRkgeBGsxL_QJWwYMfAbUeeG7c1E6 LYUfiDUkWe6H34r1AAwOR8B8fLEz6n04NPGRrq0FM"
        
 
読み込み中
Salesforce Help | Article