クライアント起点バックチャネル認証 (CIBA) 機能を使用するには、Enterprise Plan または適切なアドオンが必要です。詳しくは、Auth0 Pricing を参照してください。
CIBA でモバイルプッシュ通知を使用すると、ユーザーは登録済みのモバイルデバイスでリクエストを認証または認可するためのプッシュ通知を受け取ります。CIBA でモバイルプッシュ通知を送信するには、Auth0 Guardian アプリ、または Auth0 Guardian SDK と統合されたカスタムアプリを使用できます。
モバイルプッシュ通知を使用する CIBA フローでは、ブラウザーを使わずに、ユーザーのモバイルデバイス上で認証と認可を行います。利用側デバイスではアクティブなブラウザーセッションが不要なため、CIBA リクエストがトリガーされる前にユーザーがログインしている必要はありません。また、これにより、CIBA フローがユーザーの既存のセッションに影響を与えないことも保証されます。
次の図は、モバイルプッシュ通知を使用した CIBA のエンドツーエンドのフローを示しています。
以下のセクションでは、モバイルプッシュ通知を使用した CIBA でユーザー認証がどのように機能するかを、手順に沿って説明します。
Auth0 を使用して CIBA のプッシュリクエストを開始するには、次の前提条件を満たす必要があります。
ステップ 1: クライアントアプリケーションが CIBA リクエストを開始する
User Search APIs を使用して、CIBA リクエストを開始する対象の認可ユーザーを検索し、そのユーザー ID を取得します。
認可ユーザーのユーザー ID を取得したら、Authentication API または SDKs を使用して、/bc-authorize エンドポイントに CIBA リクエストを送信します。
curl --location 'https://{YOUR_DOMAIN}.auth0.com/bc-authorize' \
--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 'scope={SCOPES}' \
--data-urlencode 'binding_message={BINDING_MESSAGE}'
var response = await authenticationApiClient . ClientInitiatedBackchannelAuthorization (
new ClientInitiatedBackchannelAuthorizationRequest ()
{
ClientId = "{YOUR_CLIENT_ID}" ,
Scope = "openid" ,
ClientSecret = "{YOUR_CLIENT_SECRET}" ,
BindingMessage = "{BINDING_MESSAGE}" ,
LoginHint = new LoginHint ()
{
Format = "iss_sub" ,
Issuer = "https://{YOUR_DOMAIN}.auth0.com/" ,
Subject = "{USER_ID}"
}
}
);
resp , err := authAPI . CIBA . Initiate ( context . Background (), ciba . Request {
ClientID : mgmtClientID ,
ClientSecret : mgmtClientSecret ,
Scope : "openid" ,
LoginHint : map [ string ] string {
"format" : "iss_sub" ,
"iss" : "https://{YOUR_DOMAIN}.auth0.com/" ,
"sub" : "{USER_ID}" ,
},
BindingMessage : "{BINDING_MESSAGE}" ,
})
//AuthClient インスタンスを作成
AuthAPI auth = AuthAPI . newBuilder (domain, clientId, clientSecret). build ();
//認可
Map < String , Object > loginHint = new HashMap <>();
loginHint . put ( "format" , "iss_sub" );
loginHint . put ( "iss" , "https://{YOUR_DOMAIN}.auth0.com/" );
loginHint . put ( "sub" , "{USER_ID}" );
Request < BackChannelAuthorizeResponse > request = auth . authorizeBackChannel ( "openid" , "{BINDING_MESSAGE}" , loginHint);
BackChannelAuthorizeResponse resp = request . execute (). getBody ();
パラメーター 説明 tenantテナント名。カスタムドメインを指定することもできます。iss_sub 形式を使用する場合、テナント名は iss クレーム内で渡されます。 client_idクライアントアプリケーションの識別子です。 client_secretクライアントシークレット、Private Key JWT、mTLS Authentication など、CIBA でのユーザー認証に使用されるクライアント認証方式です。Private Key JWT または mTLS を使用する場合は、クライアントシークレットを含める必要はありません。 scopeopenid を含める必要があります。 必要に応じて、リフレッシュトークンを要求するために offline_access を含めることもできます。ただし、CIBA フローでトランザクションを 1 回限り認可する場合、リフレッシュトークンは不要であり、このコンテキストでは意味を持ちません。user_idlogin_hint 構造内で渡される、認可を行うユーザーのユーザー ID です。iss_sub 形式を使用する場合、ユーザー ID は sub クレーム内で渡されます。 ユーザー ID の形式は、外部プロバイダーによって異なる場合があります。requested_expiryCIBA セッションの最大有効期間 (秒) です。CIBA フローの requested_expiry は 1 ~ 259200 秒 (72 時間) の範囲で、デフォルトは 300 秒です。CIBA フローのカスタム有効期限を設定するには、requested_expiry パラメーターを含めます。requested_expiry パラメーターは、CIBA が使用する通知チャネルを決定する際に役立ちます:requested_expiry を 300 秒以下に設定すると、有効になっている場合は、CIBA はモバイルのプッシュ通知チャネルを使用します。テナントに MFA が設定されていない場合、CIBA リクエストは失敗します。requested_expiry を 301 ~ 259200 秒 (72 時間) に設定すると、有効になっている場合は、CIBA はメール通知チャネルを使用します。 binding_message認証デバイスと consumption device の間で CIBA フローを関連付けるために使用される、人が読んで理解できるメッセージです。binding_message は必須で、最大 64 文字です。使用できるのは英数字と +-_.,:# のみです。
認可を行うユーザーごとにレート制限があり、1 分あたり 5 件を超えるリクエストは送信されません。
ステップ 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 または SDKs を使用して、urn:openid:params:grant-type:ciba グラントタイプと /bc-authorize エンドポイントから受け取った auth_req_id を指定し、/token エンドポイントを呼び出します。
curl --location 'https://$tenant.auth0.com/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'client_secret=<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 = "<CLIENT_ID>" ,
ClientSecret = "<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 エンドポイントをポーリングしてください。
ステップ 4: モバイルアプリケーションでプッシュ通知を受信する
Auth0 は、Auth0 Guardian アプリ、または Auth0 Guardian SDK と統合したカスタムアプリを通じて、ユーザーが登録したモバイルアプリまたはデバイスにプッシュ通知を送信します。
カスタムアプリを使用している場合、Auth0 Guardian SDK には、プッシュ通知で受信したデータを解析し、そのまま使用できる Notification インスタンスを返すメソッドが用意されています。Notification インスタンスには、トランザクション関連付け ID (txlinkid) が含まれており、モバイルアプリケーションはこれを使用して Auth0 から同意の詳細を取得します。
以下のコードサンプルは、Guardian SDK を使用した iOS および Android のモバイル向けプッシュ通知実装例です。
//UNUserNotificationCenterDelegate を実装
func userNotificationCenter ( _ center : UNUserNotificationCenter, willPresent notification : UNNotification, withCompletionHandler completionHandler : (UNNotificationPresentationOptions) -> Void ) {
let userInfo = notification. request . content . userInfo
if let notification = Guardian. notification ( from : userInfo) {
// この関数を実装して、プロンプトを表示し、ユーザーの同意/拒否を処理します。
handleGuardianNotification ( notification : notification)
}
}
// FCM リスナーで RemoteMessage を受信します
@Override
public void onMessageReceived (RemoteMessage message) {
Notification notification = Guardian. parseNotification (message. getData ());
if (notification != null ) {
// Guardian 通知を受信したので、処理します
handleGuardianNotification (notification);
return ;
}
/* 使用中の他のプッシュ通知を処理します ... */
}
ステップ 5: モバイルアプリケーションが同意の詳細を取得します
Auth0 Guardian SDK と統合された Auth0 Guardian アプリまたはカスタムアプリは、Auth0 Consent API から同意の詳細、つまり binding_message の内容を取得します。
カスタムアプリを使用している場合、次のコードサンプルは Auth0 Consent API からデータを取得する iOS および Android の実装例です。
let device: AuthenticationDevice = // Guardian SDK の初回登録プロセスで取得し、ローカルに保存したオブジェクト
if let consentId = notification.transactionLinkingId {
Guardian
. consent ( forDomain : {yourTenantDomain}, device : device)
. fetch ( consentId : consentId, notificationToken : notification. transactionToken )
. start {result in
switch result {
case . success ( let payload) :
// 同意の詳細をユーザーに表示する
case . failure ( let cause) :
// エラーが発生した
}
}
}
Enrollment enrollment = // Guardian SDK の初回登録プロセスで取得し、ローカルに保存したオブジェクト
if (notification. getTransactionLinkingId () != null ) {
guardian
. fetchConsent (notification, enrollment)
. start (new Callback < Enrollment > {
@Override
void onSuccess (RichConsent consentDetails) {
// 同意の詳細をユーザーに表示する
}
@Override
void onFailure (Throwable exception) {
// エラーが発生した
}
});
}
ステップ 6: モバイルアプリケーションが同意の詳細をユーザーに表示する
Auth0 Consent API は、binding_message、scope、audience を含む同意の詳細を、Auth0 Guardian アプリまたは Auth0 Guardian SDK と連携したカスタムアプリに返します。モバイルアプリケーションに返されるスコープは、RBAC ポリシーに基づいてフィルタリングされます。詳しくは、ロールベースアクセス制御 を参照してください。
モバイルアプリケーションは、認証リクエストおよび/または同意の詳細をユーザーに表示します。
次のコードサンプルは、Auth0 Consent API からのレスポンスの例です。
{
"id" : "cns_abc123" ,
"requested_details" : {
"audience" : "https://$tenant.auth0.com/userinfo" ,
"scope" : [ "openid" ],
"binding_message" : "21-49-38"
},
"created_at" : 1746693720
"expires_at" : 1746693750
}
この時点で、ユーザーは認証リクエストを承諾または拒否できます。
ステップ 7: モバイルアプリケーションがユーザーの応答を Auth0 に返送する
Auth0 Guardian アプリまたはカスタムアプリが、ユーザーの応答を Auth0 に返送します。
Auth0 Guardian SDK と統合されたカスタムアプリを使用している場合、以下のコードサンプルは、ユーザーの応答を処理する iOS および Android の実装例を示しています。
Guardian
. authentication ( forDomain : "{yourTenantDomain}" , device : device)
. allow ( notification : notification)
// または reject(notification: notification, withReason: "hacked")
. start { result in
switch result {
case . success :
// 認証リクエストは正常に拒否されました
case . failure ( let cause) :
// 失敗しました。cause を確認して原因を特定してください
}
}
guardian
. allow (notification, enrollment)
. execute (); // または start(new Callback<> ...)
Guardian
. authentication ( forDomain : "{yourTenantDomain}" , device : device)
. reject ( notification : notification)
// または reject(notification: notification, withReason: "hacked")
. start { result in
switch result {
case . success :
// 認証リクエストは正常に拒否されました
case . failure ( let cause) :
// エラーが発生しました。原因を確認して問題を特定してください
}
}
guardian
. reject (notification, enrollment) // または reject(notification, enrollment, reason)
. execute (); // または start(new Callback<> ...)
ステップ8: フロー完了後、Auth0 はユーザーの応答を受け取る
クライアントアプリケーションは、/token エンドポイントからの応答を受信すると、ポーリングを終了します。CIBA フローでは常に、認可を行うユーザーから承認または拒否の応答が必要であり、既存のグラントは確認されません。
ステップ 9: Auth0 がクライアントアプリケーションにアクセストークンを返す
ユーザーがプッシュリクエストを拒否した場合、Auth0 は次のようなエラーレスポンスをクライアントアプリケーションに返します。
{
"error" : "access_denied" ,
"error_description" : "エンドユーザーが認証リクエストを拒否したか、有効期限が切れました"
}
ユーザーがプッシュリクエストを承認すると、Auth0 は次のような アクセストークン をクライアントアプリケーションに返します:
{
"access_token" : "eyJh..." ,
"id_token" : "eyJh..." ,
"expires_in" : 86400 ,
"scope" : "openid" ,
"token_type" : "Bearer"
}
refresh_token は、最初の /bc-authorize リクエストに offline_access スコープが含まれている場合にのみ返されます。