Contents
Keycloakでカスタムクレームを設定する意義
KeycloakではOpenID Connect(OIDC)を通じて、認証情報にカスタムクレームを追加することで、アプリケーション側でのセキュリティポリシーの柔軟な制御が可能になります。企業の独自属性やロール情報をトークンに含めることで、認可ルールの細分化やデータアクセス制限が実現できます。たとえば、custom_roleという属性をトークンに埋め込むことで、特定のユーザーのみ許可するAPIエンドポイントを構築できるのです。この設定は、アプリケーションとIAM(統合アクセス管理)の連携強化において不可欠です。
Realm属性追加の手順
Realmレベルでカスタム属性を定義することで、後続のクレームマッピングに必要なデータ源を作成できます。Keycloak Admin Consoleでの設定が最も直感的ですが、API経由でも可能です。
Keycloak Admin Consoleでの設定
- Admin Consoleにログインし、対象のRealmを選択します。
- 「**Settings(設定)」タブへ移動し、「Custom Attributes(カスタム属性)」セクションを開きます。
- 任意の名前(例:
custom_role)を入力し、値(例:admin,user)を定義します。 - 「Save(保存)」ボタンで変更を反映させます。
注意点: ロール属性は後続のクレームマッピングで参照されるため、一貫した命名規則が重要です。たとえば、「department」や「contractor_type」のような用途に応じた名前を設定すると良いでしょう。
API経由のオプション
KeycloakのAdmin APIを使用してRealm属性を追加するには、以下のようにPOST /admin/realms/{realm}/attributesエンドポイントにリクエストを送信します。これはスクリプト化や自動設定向けに有効です。
|
1 2 3 4 5 |
curl -X POST "http://localhost:8080/auth/admin/realms/my-realm/attributes" \ -H "Authorization: Bearer <ACCESS_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"custom_role": "developer"}' |
クレームマッピング構成
ユーザー属性やカスタムRealm属性をOpenID Connectのトークンに含めるには、Mapperコンフィグを使用します。この設定により、アプリケーションが認証時に取得するIDトークンにカスタム情報が含まれます。
User Attributeタイプのマッパー作成
- Client(クライアント)設定画面で、「Mappers(マッパラー)」タブを開きます。
- 「Create Mapper(マッパラーを作成)」ボタンをクリックし、以下の情報を入力します:
- Name:
custom_role_mapper(任意の名前) - Mapper Type:
User Attribute -
User Attribute: 事前に定義したRealm属性(例:
custom_role) -
「Save」ボタンで保存します。これにより、ユーザーが認証するたびに指定された属性がトークンに含まれるようになります。
注意: マッパラーが動作するのは、IDトークンとアクセストークンの両方です。ただし、アプリケーション側でどちらを検証対象とするか明確にしておくことが重要です。この区別は、セキュリティポリシーによって異なる場合があります。
Scriptベースの動的処理
複雑なロジックが必要な場合は、スクリプト型マッパラーを使用します。たとえば、ユーザー属性から動的に値を生成する場合や、セキュリティチェックを行う際に役立ちます。
スクリプト例(JavaScript):
|
1 2 3 4 5 6 7 8 9 |
function mapper(user, session, context) { const role = user.getAttribute("custom_role"); return { name: "dynamic_claim", value: role === "admin" ? "superuser" : role, type: "string" }; } |
このスクリプトを「Mapper Type」でScriptを選択し、コードを入力することで動的なクレームが生成されます。
User Federationとの連携方法
Keycloakは外部の認証プロバイダー(例: LDAP/AD)と連携する際も、カスタムクレームの同期を可能にしています。この設定により、フェデレーションユーザーもアプリケーション側でセキュリティ制御が可能です。
LDAP/ADとの属性マッピング
- User Federation(ユーザーフェデレーション)設定画面を開きます。
- 「LDAP」や「Active Directory」プロバイダーを選択し、以下の情報を入力します:
-
Attribute Mapping: フェデレーションユーザーの属性(例:
memberOf)をKeycloakのカスタム属性にマップします。 -
保存後、フェデレーションユーザーの認証時に自動で属性が同期されます。
重要な確認点
- フェデレーションプロバイダー側の属性名とKeycloakのカスタム属性名は一致させましょう。
- タイミングについては、「Synchronization(同期)」設定で定期更新を有効化します。
フェデレーションプロバイダー設定
フェデレーションプロバイダーの設定ファイル(例: config.json)には、以下の内容が含まれます:
|
1 2 3 4 5 6 7 8 9 10 |
{ "provider": "ldap", "importConfig": { "attributeMappings": [ {"externalAttribute": "memberOf", "internalAttribute": "custom_role"}, {"externalAttribute": "department", "internalAttribute": "team"} ] } } |
この設定により、フェデレーションユーザーの属性がKeycloakのカスタムクレームに自動的に反映されます。
注意事項:
- JSONフォーマットでのエスケープ処理が必要な場合(例:
"や\を含む値)、適切にエスケープしてください。 - カスタム属性名は、Keycloak側で一意かつ識別可能な形式を使用してください。
トークン発行時のカスタムクレーム確認手順
実環境での検証フローを理解するために、PostmanでIDトークンを取得し、ペイロードを解析する方法を説明します。
PostmanによるIDトークン取得
- KeycloakのClients(クライアント)設定画面で、認証対象のクライアントを選択します。
- 「Client ID」や「Redirect URI」を確認し、Postmanを使用してOAuth 2.0認証を実施します:
- URL:
http://localhost:8080/auth/realms/my-realm/protocol/openid-connect/auth -
パラメータ:
plaintext
client_id=your_client_id
response_type=code
redirect_uri=http://localhost:3000/callback
scope=openid -
認証に成功すると、リダイレクトURIにコードが返されます。これを使用してアクセストークンとIDトークンを取得します。
JWTペイロードの解析方法
IDトークンはBase64 URLエンコードされたJSON形式です。以下の手順でペイロードを確認できます:
- IDトークンをコピーし、ブラウザやJWTデコーダー(例: jwt.io)に貼り付けます。
- 「Decode(デコード)」ボタンをクリックすると、
payloadセクションでカスタムクレームが表示されます。
ペイロード例:
|
1 2 3 4 5 6 |
{ "sub": "1234567890", "name": "John Doe", "custom_role": "admin" } |
このように、custom_roleが正しくトークンに含まれているかを確認できます。
アプリケーション側でのJWT検証例
アプリケーションで取得したIDトークンは、Nimbus JOSE + JWTライブラリを使用して検証します。以下にJavaの実装サンプルを示します。
JavaにおけるNimbusライブラリ活用
まずはMavenプロジェクトのpom.xmlに依存関係を追加します:
|
1 2 3 4 5 6 |
<dependency> <groupId>com.nimbusds</groupId> <artifactId>nimbus-jose-jwt</artifactId> <version>9.43.1</version> </dependency> |
注意事項:
- バージョン指定(例:
9.43.1)は、将来のバージョンアップに伴う不兼容性リスクを含みます。リリースノートを確認し、必要に応じて範囲指定(例:[8, 10))を使用してください。
検証コード例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import com.nimbusds.jwt.JWTClaimsSet; import java.util.Set; public class JwtValidator { public static boolean validate(String jwt, String issuer) throws Exception { // タイムスタンプの検証(1分以内) JWTClaimsSet claims = JWTClaimsSet.parse(jwt); long now = System.currentTimeMillis() / 1000; if (claims.getIssuedAtTimeSeconds() < now - 60 || claims.getExpirationTimeSeconds() < now) { return false; } // 発行元の検証 if (!issuer.equals(claims.getIssuer())) { return false; } // カスタムクレームの検証(例: custom_roleが"admin"か) Set<String> roles = (Set<String>) claims.getClaim("custom_role"); return roles.contains("admin"); } } |
このコードにより、トークンが有効期限内であり、発行元が正しく、カスタムクレームにadminという値があるかを検証できます。
まとめ
- Realm属性の追加は、カスタムクレーム設定の基盤になります。
- Mapperコンフィグでユーザー属性やフェデレーションユーザーの情報をトークンに反映します。
- PostmanでのIDトークン取得と解析により、実際のトークン内容を確認できます。
- Nimbusライブラリを使用することで、アプリケーション側でもJWT検証が可能です。
設定後はPostmanでIDトークンを検証し、実際のAPI連携テストを行ってください。