クライアント起点バックチャネル認証 (CIBA) 機能を使用するには、エンタープライズプランまたは適切なアドオンが必要です。詳しくは、Auth0 Pricing を参照してください。
クライアント起点バックチャネル認証 (CIBA) は、開始元のアプリケーションでユーザーによる直接操作を必要とせずに、クライアントアプリケーションが認証および/または 認可フロー を開始できるようにする OAuth 2.0 の仕様です。Rich Authorization Requests (RAR) は OAuth 2.0 の拡張機能で、クライアントアプリケーションが認可リクエストで標準的な OAuth 2.0 スコープを超える、より複雑な権限を要求できるようにします。
CIBA と RAR を組み合わせると、バックチャネルリクエストで きめ細かな認可 データを 認可サーバー に渡せます。authorization_details パラメーターには、ユーザーに表示する同意プロンプトでカスタマイズできるリクエストの詳細が含まれます。
CIBA では、次の通知チャネルを使用してユーザーを認可できます。
Auth0 Guardian アプリと、Auth0 Guardian SDK を統合したカスタムアプリを使用する モバイルプッシュ通知 。
カスタマイズした同意プロンプトの設定が必要な メール通知 。
リソースへのアクセスをよりきめ細かく制御する必要があるユースケースでは、RAR を CIBA フローと組み合わせて使用します。一般的なユースケースには、次のようなものがあります。
支払いアプリが、送金を確認するようユーザーに求めます。authorization_details は、トランザクションの詳細を表示するようにカスタマイズできます。
AI エージェントが、変更後の診察予約の詳細をユーザーに提示します。authorization_details は、新しい日時を表示するようにカスタマイズできます。
CIBA を使用したユーザー認可フローは、CIBA を使用したユーザー認証フローと似ており、RAR のサポートにより、クライアントは /bc-authorize エンドポイントを介して authorization_details を認可サーバーに渡すことができます。
次のシーケンス図は、CIBA を使用したユーザー認可フローのエンドツーエンドの流れを示しています。
以下のセクションでは、CIBA でのユーザー認可の仕組みを手順ごとに説明します。
Auth0 を使用して CIBA リクエストを開始するには、次の設定が必要です。
ステップ 1: クライアントアプリケーションが CIBA リクエストを開始する
User Search APIs を使用して、CIBA リクエストを開始する対象の認可を行うユーザーを特定し、そのユーザー ID を取得します。
認可を行うユーザーのユーザー ID を取得したら、Authentication API を使用して、authorization_details を含む CIBA リクエストを /bc-authorize エンドポイントに送信します。
curl --location 'https://{YOUR_DOMAIN}.auth0.com/bc-authorize' \
--request POST \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={YOUR_CLIENT_ID}' \
--data-urlencode 'client_secret={YOUR_CLIENT_SECRET}' \
--data-urlencode 'login_hint={ "format": "iss_sub", "iss": "https://{YOUR_DOMAIN}.auth0.com/", "sub":"{USER_ID}"}' \
--data-urlencode 'audience=https://api.example.com' \
--data-urlencode 'binding_message=Confirm payment of 2500' \
--data-urlencode 'authorization_details=[{
"type": "money_transfer",
"instructedAmount": {
"amount": 2500,
"currency": "USD"
},
"sourceAccount": "xxxxxxxxxxx1234",
"destinationAccount": "xxxxxxxxxxx9876",
"beneficiary": "Hanna Herwitz",
"subject": "A Lannister Always Pays His Debts"
}]'
パラメーター 説明 tenantlogin_hint 構造内で渡されるテナント名です。カスタムドメインを指定することもできます。iss_sub 形式を使用する場合、テナント名は iss クレーム内で渡されます。例 : login_hint={"format": "iss_sub", "iss": "https://{YOUR_DOMAIN}.auth0.com/", "sub":"{USER_ID"}client_idクライアントアプリケーションの識別子です。 client_secretCIBA でユーザーを認証する際に使用するクライアント認証方式です。たとえば、クライアントシークレット、Private Key JWT、mTLS Authentication などがあります。Private Key JWT または mTLS を使用している場合は、client secret を含める必要はありません。 scopeopenid を含める必要があります。 必要に応じて、リフレッシュトークンをリクエストするために offline_access をスコープに含めることもできます。ただし、CIBA フローでトランザクションを 1 回限り認可する場合、リフレッシュトークンは不要であり、このコンテキストでは意味を持ちません。user_idlogin_hint 構造内で渡される、認可を行うユーザーのユーザー ID です。iss_sub 形式を使用する場合、ユーザー ID は sub クレーム内で渡されます。例 : login_hint={"format": "iss_sub", "iss": "https://{YOUR_DOMAIN}.auth0.com/", "sub":"{USER_ID}"} ユーザー ID の形式は、外部プロバイダーによって異なる場合があります。requested_expiryCIBA フローの要求有効期限は 1~259200 秒 (72 時間) で、デフォルトは 300 秒です。CIBA フローのカスタム有効期限を設定するには、requested_expiry パラメーターを指定します。requested_expiry パラメーターは、CIBA が使用する通知チャネルの判定にも使われます:requested_expiry を 300 秒以下に設定した場合、有効になっていれば CIBA はモバイルのプッシュ通知チャネルを使用します。テナントで MFA が設定されていない場合、CIBA リクエストは失敗します。requested_expiry を 301~259200 秒に設定した場合、有効になっていれば CIBA はメール通知チャネルを使用します。 binding_message認証デバイスと利用デバイスの間で CIBA フローを関連付けるために使用される、人が読んで理解できるメッセージです。binding message は必須で、最大 64 文字です。使用できるのは英数字と +-_.,:# のみです audience発行されるトークンのオーディエンスを一意に識別する値です。 authorization_details認可する permissions を記述する、省略可能な JSON オブジェクト配列です。各オブジェクトの type 値は、リソースサーバーの authorization_details パラメーターを使用してリソースサーバーに登録する必要があります。詳しくは、Configure Rich Authorization Requests を参照してください。
ステップ 2: Auth0 テナントが CIBA リクエストの受領を確認する
Auth0 テナントが POST リクエストを正常に受信すると、リクエストを参照する auth-req-id を含むレスポンスを受け取ります。
{
"auth_req_id" : "eyJh..." ,
"expires_in" : 300 ,
"interval" : 5
}
auth_req_id の値は、CIBA フローの完了をポーリングするために /token エンドポイントに渡されます。
ステップ 3: クライアントアプリケーションが応答をポーリングする
Authentication API を使用して、urn:openid:params:grant-type:ciba グラントタイプと /bc-authorize エンドポイントから受け取った auth_req_id を指定し、/token エンドポイントを呼び出します。
curl --location 'https://{YOUR_DOMAIN}.auth0.com/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id={YOUR_CLIENT_ID}' \
--data-urlencode 'client_secret={YOUR_CLIENT_SECRET}' \
--data-urlencode 'auth_req_id={AUTH_REQ_ID}' \
--data-urlencode 'grant_type=urn:openid:params:grant-type:ciba'
var token = await authenticationApiClient . GetTokenAsync (
new ClientInitiatedBackchannelAuthorizationTokenRequest ()
{
AuthRequestId = response . AuthRequestId ,
ClientId = "your-client-id" ,
ClientSecret = "your-client-secret"
}
);
token , err := authAPI . OAuth . LoginWithGrant ( context . Background (),
"urn:openid:params:grant-type:ciba" ,
url . Values {
"auth_req_id" : [] string { resp . AuthReqID },
"client_id" : [] string { clientID },
"client_secret" : [] string { clientSecret },
},
oauth . IDTokenValidationOptions {})
Request < BackChannelTokenResponse > tokenRequest = auth . getBackChannelLoginStatus (authReqId, "grant-type" );
BackChannelTokenResponse tokenResponse = tokenRequest . execute (). getBody ();
ユーザーがトランザクションを承認するまで、次のレスポンスが返されます。
{
"error" : "authorization_pending" ,
"error_description" : "エンドユーザーの認証が保留中です"
}
ポーリングの間隔は約 5 秒です。頻繁にポーリングしすぎると、次のレスポンスが返されます。description の内容は、バックオフ間隔に応じて異なります。
{
"error" : "slow_down" ,
"error_description" : "You are polling faster than allowed. Try again in 10 seconds."
"interval" : 10
}
エラーを解消するには、次のポーリング間隔 (秒) まで待ってから、/token エンドポイントをポーリングしてください。
通知チャネルに応じて、Auth0 は認証デバイスに通知を送信します。
モバイルプッシュ通知 : Auth0 は Auth0 Guardian アプリ、または Auth0 Guardian SDK を統合したカスタムモバイルアプリに送信します。
メール通知 : Auth0 はユーザーの確認済みメールアドレスに送信します。
認証デバイスは、Auth0 Consent API から同意の詳細、つまり binding_message の内容を取得します。
モバイルプッシュ通知 : Auth0 Guardian アプリ、または Auth0 Guardian SDK を統合したカスタムアプリが Auth0 Consent API を呼び出し、同意の詳細を取得します。
メール通知 : ユーザーが確認用リンクをクリックするとブラウザーにリダイレクトされ、そのブラウザーが Auth0 Consent API から同意の詳細を取得します。
ステップ 6: 認証デバイスがユーザーに同意の詳細を表示する
Auth0 Consent API は、binding_message、scope、audience、および設定されている場合は authorization_details を含む同意の詳細を認証デバイスに返します。モバイルアプリケーションに返されるスコープは、RBAC ポリシーに従ってフィルタリングされます。詳しくは、ロールベースアクセス制御 を参照してください。
次のコードサンプルは、Auth0 Consent API からのレスポンス例です。
{
"id" : "cns_2309dsfsd098" ,
"requested_details" : {
"audience" : "https://api.example.com" ,
"scope" : [ "read:profile" , "write:profile" ],
"binding_message" : "abc123" ,
"authorization_details" : [
{
"type" : "money_transfer" ,
"instructedAmount" : {
"amount" : 2500 ,
"currency" : "USD"
},
"sourceAccount" : "xxxxxxxxxxx1234" ,
"destinationAccount" : "xxxxxxxxxxx9876" ,
"beneficiary" : "Hanna Herwitz" ,
"subject" : "A Lannister Always Pays His Debts"
}
]
},
"created_at" : 1632739200 ,
"expires_at" : 1632739200
}
認証デバイスは、authorization_details を含む同意の詳細をユーザーに表示します。
モバイルプッシュ通知 : Auth0 Guardian アプリは、プッシュ通知を使用して、同意画面に authorization_details をレンダリングします。
メール通知 : ブラウザーは、カスタム同意画面に authorization_details をレンダリングします。同意画面をカスタマイズする方法については、カスタマイズされた同意プロンプトを設定する を参照してください。
この時点で、ユーザーは認可リクエストを承諾または拒否できます。
ステップ 7: 認証デバイスがユーザーの応答を Auth0 に返す
ユーザーが認可リクエストを承認または拒否すると、認証デバイスはその応答を Auth0 に返します。
モバイルプッシュ通知 : Auth0 Guardian アプリ、または Auth0 Guardian SDK と統合されたカスタムアプリが、ユーザーの応答を Auth0 に返します。
メール通知 : ブラウザーがユーザーの応答を Auth0 に返します。
ステップ 8: フローの完了後、Auth0 がユーザーの応答を受信する
クライアントアプリケーションは、/token エンドポイントから応答を受信すると、ポーリングを終了します。CIBA フローでは、認可を行うユーザーからの承認または拒否の応答が常に必要であり、既存のグラントは確認されません。つまり、Auth0 はすべての CIBA リクエストを、認可を行うユーザーによる新たな認可として扱います。
ステップ9: Auth0 がクライアントアプリケーションにアクセストークンを返す
ユーザーがプッシュリクエストを拒否すると、Auth0 は次のようなエラーレスポンスをクライアントアプリケーションに返します。
{
"error" : "access_denied" ,
"error_description" : "エンドユーザーが認証リクエストを拒否したか、有効期限が切れました"
}
ユーザーがプッシュリクエストを承認すると、Auth0 は次のような authorization_details を含むアクセストークン をクライアントアプリケーションに返します。
{
"id_token" : "..." ,
"access_token" : "..." ,
"expires_in" : "..." ,
"scope" : "{SCOPES}" ,
"authorization_details" : [{
"type" : "money_transfer" ,
"instructedAmount" : {
"amount" : 2500 ,
"currency" : "USD"
},
"sourceAccount" : "xxxxxxxxxxx1234" ,
"destinationAccount" : "xxxxxxxxxxx9876" ,
"beneficiary" : "Hanna Herwitz" ,
"subject" : "A Lannister Always Pays His Debts"
}]
}
refresh_token は、最初の /bc-authorize リクエストに offline_access スコープが含まれていた場合にのみ返されます。
authorization_details を照会する
コンパイル時には、JSON を動的にクエリする場合と同様に、同意の詳細から authorization_details の型とオブジェクトを型安全に照会できます。
let requestedDetails: ConsentRequestedDetails = payload. requestedDetails
let myAuthorizationDetailsTypes = requestedDetails. authorizationDetails [ 0 ]. objectValue ! ;
let type = myAuthorizationDetailsTypes[ "type" ] ? . stringValue // 事前登録済みの type 値
let stringProperty = myAuthorizationDetailsTypes[ "string_property" ] ? . stringValue
let boolProperty = myAuthorizationDetailsTypes[ "bool_property" ] ? . boolValue
let numericProperty = myAuthorizationDetailsTypes[ "numeric_property" ] ? . doubleValue
let nestedObjectProperty = myAuthorizationDetailsTypes[ "nested_property" ] ? . objectValue
let nestedArrayProperty = myAuthorizationDetailsTypes[ "nested_array_property" ] ? . arrayValue
RichConsentRequestedDetails requestedDetails = consentDetails. getRequestedDetails ();
Map < String, Object > authorizationDetails = requestedDetails. getAuthorizationDetails (). get ( 0 );
String type = (String) myAuthorizationDetailsTypes. get ( "type" );
String stringProperty = (String) myAuthorizationDetailsTypes. get ( "string_property" );
boolean booleanProperty = (boolean) myAuthorizationDetailsTypes. get ( "boolean_property" );
int numericProperty = (int) myAuthorizationDetailsTypes. get ( "numeric_property" );
Object nestedObjectProperty = myAuthorizationDetailsTypes. get ( "nested_property" );
List < Object > nestedArrayProperty = (List < Object > ) myAuthorizationDetailsTypes. get ( "nested_array_property" );
オブジェクトを表すカスタム型を定義している場合は、filterAuthorizationDetailsByType() 関数を使用して、目的の型に一致するすべての authorization_details オブジェクトを返すことができます。
次のコードサンプルでは、payment 型の authorization_details を照会します。
// AuthorizationDetailsType を実装する必要があります
struct Payment : AuthorizationDetailsType {
static let type = "payment" ;
let amount: Double ;
let currency: String ;
}
...
let requestedDetails: ConsentRequestedDetails = payload. requestedDetails
let payments = requestedDetails. filterAuthorizationDetailsByType (Payment. self )
let firstPayment = payments. first !
let type: String = firstPayment. type // "payment"
let amount: Double = firstPayment. amount
let currency: String = firstPayment. currency
@AuthorizatioDetailsType ( "payment" )
class Payment {
private String type;
private int amount;
private String currency;
public Payment (String type, int amount, String currency) {
this .type = type;
this .amount = amount;
this .currency = currency;
}
public String getType () {
return type;
}
public int getAmount () {
return amount;
}
public String getCurrency () {
return currency;
}
}
.. .
RichConsentRequestedDetails requestedDetails = consentDetails. getRequestedDetails ();
List < Payment > payments = requestedDetails. filterAuthorizationDetailsByType (Payment.class);
Payment firstPayment = payments. get ( 0 );
String type = firstPayment. getType ();
int amount = firstPayment. getAmount ();
String currency = firstPayment. getCurrency ();
See all 33 lines
filterAuthorizationDetailsByType() は、指定した authorization_details 型に一致するオブジェクトのみを返します。そのため、リクエストの内容をユーザーが完全に理解できるようにするには、型に関係なく、モバイルアプリケーションですべての関連する authorization_details を同意のためにユーザーに提示する必要があります。
AI エージェントまたはアプリケーションがレスポンスを取得するために /oauth/token エンドポイントをポーリングするときにも、authorization_details を照会できます。
curl --request POST \
--url "https://{YOUR_DOMAIN}.auth0.com/oauth/token" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=urn:openid:params:grant-type:ciba" \
--data-urlencode "client_id={YOUR_CLIENT_ID}" \
--data-urlencode "client_secret={YOUR_CLIENT_SECRET}" \
--data-urlencode "auth_req_id={AUTH_REQ_ID}"
パラメーター 説明 grant_typeCIBA グラントタイプ urn:openid:params:grant-type:ciba を設定します。 client_idアプリケーションのクライアントIDを設定します。 client_secretアプリケーションのクライアントシークレットを設定します。 auth_req_idAuth0 テナントが CIBA リクエストを受領した際に返されます。CIBA リクエストを参照する ID です。
認可を行うユーザーがリクエストを承認すると、Auth0 はユーザーの応答を受信し、CIBA フローが完了して、アクセストークンと authorization_details 配列が返されます。
{
"access_token" : "ey...ZQ" ,
"expires_in" : 86400 ,
"authorization_details" : [{
"type" : "money_transfer" ,
"instructedAmount" : {
"amount" : 2500 ,
"currency" : "USD"
},
"sourceAccount" : "xxxxxxxxxxx1234" ,
"destinationAccount" : "xxxxxxxxxxx9876" ,
"beneficiary" : "Hanna Herwitz" ,
"subject" : "A Lannister Always Pays His Debts"
}],
"token_type" : "Bearer"
}
Auth0 は以下をサポートしていません。
CIBA フローの Actions で RAR を変更すること。
クライアントが検出できるように RAR タイプを公開すること。つまり、クライアントが送信可能な authorization_details タイプを事前に登録しておく必要があります。
API で許可されているタイプに一致する type プロパティを持っているかどうかの確認を超える、RAR オブジェクトの検証。authorization_details 内の内容の詳細な検証は、リソースサーバー側で行う必要があります。詳しくは、Configure RAR を参照してください。