Keycloak 認可クライアント

Keycloak authz クライアントを使用して、権限の管理と確認を行う

要件に応じて、リソースサーバーはリソースをリモートで管理したり、プログラムで権限を確認したりできる必要があります。Java を使用している場合は、Authorization Client API を使用して Keycloak Authorization Services にアクセスできます。

これは、トークンエンドポイント、リソース、および権限管理エンドポイントなど、サーバーによって提供されるさまざまなエンドポイントにアクセスしたいリソースサーバーを対象としています。

Maven の依存関係

<dependencies>
    <dependency>
        <groupId>org.keycloak</groupId>
        <artifactId>keycloak-authz-client</artifactId>
        <version>26.0.4</version>
    </dependency>
</dependencies>

設定

クライアント設定は、以下のように keycloak.json ファイルで定義されます。

{
  "realm": "hello-world-authz",
  "auth-server-url" : "https://#:8080",
  "resource" : "hello-world-authz-service",
  "credentials": {
    "secret": "secret"
  }
}
  • realm (必須)

    realm の名前。

  • auth-server-url (必須)

    Keycloak サーバーのベース URL。他のすべての Keycloak ページと REST サービスエンドポイントはこれから派生します。通常、https://host:port の形式です。

  • resource (必須)

    アプリケーションの client-id。各アプリケーションには、アプリケーションを識別するために使用される client-id があります。

  • credentials (必須)

    アプリケーションの認証情報を指定します。これはオブジェクト表記であり、キーは認証情報のタイプ、値は認証情報のタイプの値です。詳細については、専用セクションを参照してください。

設定ファイルは通常、アプリケーションのクラスパスに配置されます。これは、クライアントが keycloak.json ファイルを見つけようとするデフォルトの場所です。

認可クライアントの作成

クラスパスに keycloak.json ファイルがあることを前提として、次のように新しい AuthzClient インスタンスを作成できます。

// create a new instance based on the configuration defined in a keycloak.json located in your classpath
AuthzClient authzClient = AuthzClient.create();

ユーザーエンタイトルメントの取得

ユーザーエンタイトルメントの取得方法を示す例を次に示します。

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();

// send the entitlement request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();

System.out.println("You got an RPT: " + rpt);

// now you can use the RPT to access protected resources on the resource server

1 つ以上のリソースのセットに対するユーザーエンタイトルメントの取得方法を示す例を次に示します。

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create an authorization request
AuthorizationRequest request = new AuthorizationRequest();

// add permissions to the request based on the resources and scopes you want to check access
request.addPermission("Default Resource");

// send the entitlement request to the server in order to
// obtain an RPT with permissions for a single resource
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize(request);
String rpt = response.getToken();

System.out.println("You got an RPT: " + rpt);

// now you can use the RPT to access protected resources on the resource server

Protection API を使用したリソースの作成

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// create a new resource representation with the information we want
ResourceRepresentation newResource = new ResourceRepresentation();

newResource.setName("New Resource");
newResource.setType("urn:hello-world-authz:resources:example");

newResource.addScope(new ScopeRepresentation("urn:hello-world-authz:scopes:view"));

ProtectedResource resourceClient = authzClient.protection().resource();
ResourceRepresentation existingResource = resourceClient.findByName(newResource.getName());

if (existingResource != null) {
    resourceClient.delete(existingResource.getId());
}

// create the resource on the server
ResourceRepresentation response = resourceClient.create(newResource);
String resourceId = response.getId();

// query the resource using its newly generated id
ResourceRepresentation resource = resourceClient.findById(resourceId);

System.out.println(resource);

RPT のイントロスペクション

// create a new instance based on the configuration defined in keycloak.json
AuthzClient authzClient = AuthzClient.create();

// send the authorization request to the server in order to
// obtain an RPT with all permissions granted to the user
AuthorizationResponse response = authzClient.authorization("alice", "alice").authorize();
String rpt = response.getToken();

// introspect the token
TokenIntrospectionResponse requestingPartyToken = authzClient.protection().introspectRequestingPartyToken(rpt);

System.out.println("Token status is: " + requestingPartyToken.getActive());
System.out.println("Permissions granted by the server: ");

for (Permission granted : requestingPartyToken.getPermissions()) {
    System.out.println(granted);
}

クライアント認証

認可クライアントがバックチャネルリクエストを送信する必要がある場合、Keycloak サーバーに対して認証する必要があります。デフォルトでは、クライアントを認証する方法は 3 つあります。クライアント ID とクライアントシークレット、署名付き JWT によるクライアント認証、またはクライアントシークレットを使用した署名付き JWT によるクライアント認証です。

クライアント ID とクライアントシークレット

これは、OAuth2 仕様で説明されている従来の方法です。クライアントはシークレットを持っており、クライアントと Keycloak サーバーの両方が知っている必要があります。Keycloak 管理コンソールで特定のクライアントのシークレットを生成し、そのシークレットをアプリケーション側の keycloak.json ファイルに貼り付けることができます。

"credentials": {
    "secret": "19666a4f-32dd-4049-b082-684c74115f28"
}

署名付き JWT によるクライアント認証

これは、RFC7523 仕様に基づいています。仕組みは次のとおりです。

  • クライアントは、秘密鍵と証明書を持っている必要があります。認可クライアントの場合、これは従来の keystore ファイルを通じて利用できます。これは、クライアントアプリケーションのクラスパス上またはファイルシステムのどこかにあります。

  • 認証中、クライアントは JWT トークンを生成し、秘密鍵で署名して、特定の要求で client_assertion パラメーターで Keycloak に送信します。

  • Keycloak は、JWT の署名を検証できるように、クライアントの公開鍵または証明書を持っている必要があります。Keycloak では、クライアントのクライアント認証情報を構成します。まず、管理コンソールの Credentials タブで、クライアントを認証する方法として Signed JWT を選択します。次に、Keys タブで次のいずれかの方法を選択できます。

    • Keycloak がクライアントの公開鍵をダウンロードできる JWKS URL を構成します。クライアントはいつでもキーをローテーションでき、Keycloak は構成を変更せずに必要に応じて常に新しいキーをダウンロードするため、このオプションが最も柔軟性があります。言い換えれば、Keycloak は不明な kid (キー ID) で署名されたトークンを検出すると、新しいキーをダウンロードします。ただし、公開鍵を JWKS 形式でどこかに公開して、サーバーで使用できるようにする必要があります。

    • クライアントの公開鍵または証明書を、PEM 形式、JWK 形式、またはキーストアからアップロードします。このオプションでは、公開鍵はハードコードされており、クライアントが新しいキーペアを生成するたびに変更する必要があります。独自のキーストアがない場合は、Keycloak 管理コンソールから独自のキーストアを生成することもできます。このオプションは、認可クライアントを使用する場合に最も簡単です。

この方法を設定するには、keycloak.json ファイルに次のようなコードを記述する必要があります。

"credentials": {
  "jwt": {
    "client-keystore-file": "classpath:keystore-client.jks",
    "client-keystore-type": "JKS",
    "client-keystore-password": "storepass",
    "client-key-password": "keypass",
    "client-key-alias": "clientkey",
    "token-expiration": 10
  }
}

この構成では、キーストアファイル keystore-client.jks は、認可クライアントを使用するアプリケーションのクラスパスで使用可能である必要があります。プレフィックス classpath: を使用しない場合は、クライアントアプリケーションが実行されているファイルシステム上の任意のファイルを指定できます。

クライアントシークレットを使用した署名付き JWT によるクライアント認証

これは、秘密鍵と証明書の代わりにクライアントシークレットを使用する点を除いて、署名付き JWT によるクライアント認証と同じです。

クライアントはシークレットを持っており、認可クライアントを使用するアプリケーションと Keycloak サーバーの両方が知っている必要があります。管理コンソールの Credentials タブで、クライアントを認証する方法として Signed JWT with Client Secret を選択し、そのシークレットをアプリケーション側の keycloak.json ファイルに貼り付けます。

"credentials": {
  "secret-jwt": {
    "secret": "19666a4f-32dd-4049-b082-684c74115f28",
    "algorithm": "HS512"
  }
}

"algorithm" フィールドは、クライアントシークレットを使用した署名付き JWT のアルゴリズムを指定します。これは、HS256、HS384、HS512 のいずれかの値である必要があります。詳細については、JSON Web Algorithms (JWA) を参照してください。

この "algorithm" フィールドはオプションです。"algorithm" フィールドが keycloak.json ファイルに存在しない場合は、HS256 が自動的に適用されます。

独自のクライアント認証方法の追加

独自のクライアント認証方法を追加することもできます。クライアント側とサーバー側の両方のプロバイダーを実装する必要があります。詳細については、Server Developer GuideAuthentication SPI セクションを参照してください。

このページの内容