メインコンテンツまでスキップ

デバイスクレデンシャル管理

概要

デバイスクレデンシャルは、モバイルアプリがIdPサーバーと安全に通信するための認証情報です。

利用パターン

デバイスシークレットには2つの利用パターンがあります:

パターン説明ユーザー操作
CIBAフローデバイスエンドポイント認証 + FIDO-UAF本人確認必要(生体認証)
JWT Bearer Grantアクセストークンを直接取得(RFC 7523)不要

CIBAフロー(推奨)

Webアプリからの操作承認リクエストをモバイルアプリで受信・認証する際、以下の2段階認証を実現します:

  1. デバイス認証: デバイスシークレット(JWT)で「正規のデバイス」であることを証明
  2. 本人認証: FIDO-UAF(生体認証)で「正規のユーザー」であることを証明
┌─────────────────────────────────────────────────────────────────────┐
│ モバイルアプリの初回セットアップ │
│ │
│ FIDO-UAF登録 → デバイスシークレット自動発行 │
│ (issue_device_secret: true) │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│ CIBAフロー(Webからの操作承認) │
│ │
│ 1. Webアプリ → IdP: 承認リクエスト │
│ 2. IdP → モバイルアプリ: Push通知 │
│ 3. モバイルアプリ → IdP: デバイスシークレットJWTで認証 │
│ 4. モバイルアプリ → IdP: FIDO-UAF(生体認証)で本人確認 │
│ 5. Webアプリ: トークン取得 │
└─────────────────────────────────────────────────────────────────────┘

Step 1: デバイス登録(FIDO-UAF + シークレット自動発行)

モバイルアプリの初回セットアップで、FIDO-UAF登録と同時にデバイスシークレットを発行します。

テナントポリシー設定

identity_policy_config.authentication_device_rule で設定します。

{
"identity_policy_config": {
"authentication_device_rule": {
"max_devices": 5,
"required_identity_verification": false,
"authentication_type": "device_secret_jwt",
"issue_device_secret": true,
"device_secret_algorithm": "HS256",
"device_secret_expires_in_seconds": 31536000
}
}
}
パラメータ説明デフォルト
authentication_typedevice_secret_jwt: デバイスエンドポイントアクセスにJWT認証を要求
none: 認証不要
none
issue_device_secretFIDO-UAF登録時にシークレットを自動発行false
device_secret_algorithm署名アルゴリズム(HS256/HS384/HS512)HS256
device_secret_expires_in_seconds有効期限(秒)、null=無期限null

登録シーケンス

登録レスポンス

{
"status": "success",
"device_id": "device_abc123",
"device_secret": "base64url-encoded-random-secret",
"device_secret_algorithm": "HS256",
"device_secret_jwt_issuer": "device:device_abc123"
}
フィールド説明
device_idデバイス識別子
device_secret署名用シークレット(Secure Storageに保存)
device_secret_algorithmJWT署名アルゴリズム
device_secret_jwt_issuerJWT生成時のissクレームに使用

Step 2: CIBAフローでの認証

Webアプリからの操作承認リクエストをモバイルアプリで処理します。

認証シーケンス

デバイス認証用JWT

デバイスエンドポイントにアクセスする際、device_secretで署名したJWTを送信します。

{
"iss": "device:device_abc123",
"sub": "user_123",
"aud": "https://idp.example.com",
"jti": "unique-request-id",
"iat": 1704067200,
"exp": 1704067500
}
クレーム説明
iss登録時に返却されたdevice_secret_jwt_issuerの値
subユーザーID
audIdPのissuer URL
jtiリクエストごとにユニークなID(リプレイ攻撃防止)
exp有効期限(5分以内を推奨)

デバイスエンドポイントの認証要否

authentication_type: "device_secret_jwt"の場合:

# JWTなし → 401エラー
GET /v1/authentication-devices/{deviceId}/authentications

HTTP/1.1 401 Unauthorized
{"error": "unauthorized", "error_description": "Device authentication required"}
# JWTあり → 成功
GET /v1/authentication-devices/{deviceId}/authentications
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

HTTP/1.1 200 OK
{"list": [{"id": "auth_123", "flow": "ciba", "binding_message": "承認コード: 1234"}]}

(参考)JWT Bearer Grantによるトークン取得

CIBAフローとは別に、デバイスシークレットを使ってアクセストークンを直接取得することも可能です(RFC 7523)。

詳細: JWT認可グラント(JWT Bearer Grant)を参照してください。クライアント設定、Subject Claim Mapping、外部IdP連携などの詳細が記載されています。

リクエスト例

POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
&assertion=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
&scope=openid profile

Note: このパターンはCIBAフローのデバイスエンドポイント認証とは異なり、ユーザー操作なしでアクセストークンを取得します。セキュリティ要件に応じて使い分けてください。


認証トランザクションのレスポンス制御

デバイスエンドポイントから取得する認証トランザクションのレスポンス内容は、デバイス認証の有無によって制御されます。

レスポンス内容の違い

認証設定contextフィールド説明
authentication_type: "none"含まれない認証なしでアクセス可能。機密情報は除外
authentication_type: "access_token"含まれるアクセストークン認証成功後のみ詳細情報を返却
authentication_type: "device_secret_jwt"含まれる対称鍵JWT(HMAC)認証成功後のみ詳細情報を返却
authentication_type: "private_key_jwt"含まれる非対称鍵JWT(RSA/EC)認証成功後のみ詳細情報を返却

contextに含まれる情報

contextフィールドには、認証リクエストの詳細情報が含まれます:

フィールド説明
scopes要求されたスコープ
acr_values要求された認証コンテキストクラス
binding_messageCIBAバインディングメッセージ
authorization_detailsRich Authorization Requests(RAR)の詳細

レスポンス例

デバイス認証あり(authentication_type: "device_secret_jwt"):

{
"list": [
{
"id": "auth_123",
"flow": "ciba",
"tenant_id": "tenant_abc",
"client_id": "client_xyz",
"context": {
"scopes": "openid profile payment",
"binding_message": "送金承認: ¥10,000",
"acr_values": "urn:example:acr:mfa"
},
"created_at": "2024-01-01T00:00:00",
"expires_at": "2024-01-01T00:05:00"
}
],
"total_count": 1
}

デバイス認証なし(authentication_type: "none"):

{
"list": [
{
"id": "auth_123",
"flow": "ciba",
"tenant_id": "tenant_abc",
"client_id": "client_xyz",
"created_at": "2024-01-01T00:00:00",
"expires_at": "2024-01-01T00:05:00"
}
],
"total_count": 1
}

セキュリティ: contextフィールドには、スコープやバインディングメッセージなど、認証リクエストの詳細情報が含まれます。デバイス認証なしでこれらの情報が漏洩すると、リクエストの内容を推測される可能性があるため、認証されたデバイスにのみ返却します。


ユースケース

シナリオ説明
モバイルバンキング別デバイスからの送金をスマホアプリで承認(CIBAフロー)
2要素承認Webでの重要操作をモバイルアプリで承認(CIBAフロー)
バックグラウンド処理アプリがバックグラウンドでAPIアクセス(JWT Bearer Grant)
IoTデバイス連携スマートデバイスの操作承認

セキュリティ考慮事項

シークレット保存

プラットフォーム推奨保存先
iOSKeychain Services
AndroidAndroid Keystore

JWT生成

  • 有効期限: 5分以内を推奨
  • jti: リクエストごとにユニークな値を生成(リプレイ攻撃防止)

シークレット管理

項目推奨
有効期限1年以内を推奨
ローテーションデバイス再登録でシークレットを更新
漏洩時対応デバイス削除 + 再登録で即座に無効化

関連ドキュメント

参考仕様