認可サービス概要

Keycloakは、きめ細かい認可ポリシーをサポートし、次のようなさまざまなアクセス制御メカニズムを組み合わせることができます

  • 属性ベースのアクセス制御 (ABAC)

  • ロールベースのアクセス制御 (RBAC)

  • ユーザーベースのアクセス制御 (UBAC)

  • コンテキストベースのアクセス制御 (CBAC)

  • ルールベースのアクセス制御

    • JavaScriptの使用

  • 時間ベースのアクセス制御

  • サービスプロバイダーインターフェース(SPI)を介したカスタムアクセス制御メカニズム(ACM)のサポート

Keycloakは、管理UIとRESTful APIのセットに基づいており、保護されたリソースとスコープのパーミッションを作成し、それらのパーミッションを認可ポリシーに関連付け、アプリケーションとサービスで認可の決定を強制するために必要な手段を提供します。

リソースサーバー(保護されたリソースを提供するアプリケーションまたはサービス)は通常、保護されたリソースへのアクセスを許可する必要があるかどうかを決定するために、何らかの情報に依存しています。RESTfulベースのリソースサーバーの場合、その情報は通常、セキュリティトークンから取得され、通常はサーバーへのすべてのリクエストでベアラートークンとして送信されます。ユーザーを認証するためにセッションに依存するWebアプリケーションの場合、その情報は通常、ユーザーのセッションに保存され、各リクエストごとにそこから取得されます。

多くの場合、リソースサーバーは、ロールベースのアクセス制御(RBAC)に基づいてのみ認可の決定を実行します。ここでは、保護されたリソースにアクセスしようとしているユーザーに付与されたロールが、これらの同じリソースにマッピングされたロールと照合されます。ロールは非常に便利でアプリケーションで使用されていますが、いくつかの制限もあります

  • リソースとロールは密接に結合されており、ロールの変更(アクセスコンテキストの追加、削除、または変更など)は複数のリソースに影響を与える可能性があります

  • セキュリティ要件の変更は、これらの変更を反映するためにアプリケーションコードを大幅に変更することを意味する場合があります

  • アプリケーションのサイズによっては、ロール管理が困難になり、エラーが発生しやすくなる可能性があります

  • 最も柔軟なアクセス制御メカニズムではありません。ロールはあなたが誰であるかを表しておらず、コンテキスト情報がありません。ロールが付与されている場合、少なくとも何らかのアクセス権があります。

今日、ユーザーが異なる地域に分散し、異なるローカルポリシーを持ち、異なるデバイスを使用し、情報共有の要求が高い異種環境を考慮する必要があることを考えると、Keycloak認可サービスは、以下を提供することにより、アプリケーションとサービスの認可機能を向上させるのに役立ちます

  • きめ細かい認可ポリシーとさまざまなアクセス制御メカニズムを使用したリソース保護

  • 集中型リソース、パーミッション、およびポリシー管理

  • 集中型ポリシー決定ポイント

  • RESTベースの認可サービスセットに基づくRESTセキュリティ

  • 認可ワークフローとユーザー管理アクセス

  • プロジェクト間のコードの重複(および再デプロイ)を回避し、セキュリティ要件の変更に迅速に適応するのに役立つインフラストラクチャ。

アーキテクチャ

Keycloak AuthZ architecture overview

設計の観点から、認可サービスは、これらの機能を提供する明確に定義された認可パターンに基づいています

  • ポリシー管理ポイント (PAP)

    リソースサーバー、リソース、スコープ、パーミッション、およびポリシーを管理するためのKeycloak管理コンソールに基づくUIのセットを提供します。これの一部は、Protection APIの使用を通じてリモートでも実現されます。

  • ポリシー決定ポイント (PDP)

    認可リクエストが送信され、リクエストされたパーミッションに従ってポリシーが評価される分散可能なポリシー決定ポイントを提供します。詳細については、パーミッションの取得を参照してください。

  • ポリシー施行ポイント (PEP)

    リソースサーバー側で実際に認可の決定を施行するためのさまざまな環境向けの実装を提供します。Keycloakは、いくつかの組み込みポリシーエンフォーサーを提供しています。

  • ポリシー情報ポイント (PIP)

    Keycloak認証サーバーに基づいているため、認可ポリシーの評価中にIDとランタイム環境から属性を取得できます。

認可プロセス

3つの主要なプロセスが、Keycloakを使用してアプリケーションへのきめ細かい認可を有効にする方法を理解するために必要なステップを定義します

  • リソース管理

  • パーミッションとポリシー管理

  • ポリシー施行

リソース管理

リソース管理には、保護されているものを定義するために必要なすべてのステップが含まれます。

Resource management overview

まず、保護しようとしているものをKeycloakに指定する必要があります。これは通常、Webアプリケーションまたは1つ以上のサービスのセットを表します。リソースサーバーの詳細については、用語を参照してください。

リソースサーバーは、Keycloak管理コンソールを使用して管理されます。そこで、登録されたクライアントアプリケーションをリソースサーバーとして有効にし、保護するリソースとスコープの管理を開始できます。

Resource Server overview

リソースは、Webページ、RESTFulリソース、ファイルシステムのファイル、EJBなどです。これらは、リソースのグループ(Javaのクラスのように)を表すことも、単一の特定のリソースを表すこともできます。

たとえば、すべての銀行口座を表す銀行口座リソースを持ち、それを使用してすべての銀行口座に共通する認可ポリシーを定義する場合があります。ただし、アリス口座(顧客に属するリソースインスタンス)に固有のポリシーを定義したい場合があります。ここでは、所有者のみが一部の情報にアクセスしたり、操作を実行したりできます。

リソースは、Keycloak管理コンソールまたはProtection APIを使用して管理できます。後者の場合、リソースサーバーはリソースをリモートで管理できます。

スコープは通常、リソースで実行できるアクションを表しますが、それらに限定されません。スコープを使用して、リソース内の1つ以上の属性を表すこともできます。

パーミッションとポリシー管理

リソースサーバーと保護するすべてのリソースを定義したら、パーミッションとポリシーを設定する必要があります。

このプロセスには、リソースを管理するセキュリティとアクセス要件を実際に定義するために必要なすべてのステップが含まれます。

Permission and policy management overview

ポリシーは、何か(リソースまたはスコープ)へのアクセスまたは操作の実行を満たす必要のある条件を定義しますが、保護するものには結び付けられていません。これらは一般的であり、パーミッションまたはさらに複雑なポリシーを構築するために再利用できます。

たとえば、「ユーザープレミアム」ロールが付与されたユーザーのみがリソースのグループにアクセスできるようにするには、RBAC(ロールベースのアクセス制御)を使用できます。

Keycloakは、最も一般的なアクセス制御メカニズムをカバーするいくつかの組み込みポリシータイプ(およびそれぞれのポリシープロバイダー)を提供します。JavaScriptを使用して記述されたルールに基づいてポリシーを作成することもできます。

ポリシーを定義したら、パーミッションの定義を開始できます。パーミッションは、保護しているリソースと結合されています。ここでは、保護するもの(リソースまたはスコープ)と、パーミッションを許可または拒否するために満たす必要のあるポリシーを指定します。

ポリシー施行

ポリシー施行には、リソースサーバーへの認可の決定を実際に施行するために必要なステップが含まれます。これは、リソースサーバーでポリシー施行ポイントまたはPEPを有効にすることで実現されます。これは、認可サーバーと通信し、認可データを要求し、サーバーから返された決定とパーミッションに基づいて保護されたリソースへのアクセスを制御できます。

PEP overview

Keycloakは、実行しているプラットフォームに応じてアプリケーションを保護するために使用できる、いくつかの組み込みポリシーエンフォーサー実装を提供します。

認可サービス

認可サービスは、次のRESTFulエンドポイントで構成されています

  • トークンエンドポイント

  • リソース管理エンドポイント

  • パーミッション管理エンドポイント

これらの各サービスは、認可プロセスに関与するさまざまなステップをカバーする特定のAPIを提供します。

トークンエンドポイント

OAuth2クライアント(フロントエンドアプリケーションなど)は、トークンエンドポイントを使用してサーバーからアクセストークンを取得し、これらの同じトークンを使用して、リソースサーバー(バックエンドサービスなど)によって保護されたリソースにアクセスできます。同様に、Keycloak認可サービスは、リクエストされているリソースまたはスコープに関連付けられたすべてのポリシーの処理に基づいてアクセストークンを発行できるように、OAuth2への拡張機能を提供します。これは、リソースサーバーが、サーバーによって許可され、アクセストークンによって保持されているパーミッションに基づいて、保護されたリソースへのアクセスを強制できることを意味します。Keycloak認可サービスでは、パーミッションを持つアクセストークンは、リクエスターパーティートークンまたは略してRPTと呼ばれます。

追加リソース
Protection API

Protection APIは、リソースサーバーがリソース、スコープ、パーミッション、およびそれらに関連付けられたポリシーの管理を支援するためのUMA準拠エンドポイント提供操作のセットです。リソースサーバーのみがこのAPIにアクセスでき、uma_protectionスコープも必要です。

Protection APIによって提供される操作は、主に2つのグループに編成できます

  • リソース管理

    • リソースの作成

    • リソースの削除

    • IDで検索

    • クエリ

  • パーミッション管理

    • パーミッションチケットの発行

デフォルトでは、リモートリソース管理が有効になっています。Keycloak管理コンソールを使用してこれを変更し、コンソールを介したリソース管理のみを許可できます。

UMAプロトコルを使用する場合、Protection APIによるパーミッションチケットの発行は、認可プロセス全体で重要な部分です。後続のセクションで説明するように、これらはクライアントによってリクエストされているパーミッションを表し、リクエストされたリソースとスコープに関連付けられたパーミッションとポリシーの評価中に許可されたすべてのパーミッションを含む最終トークンを取得するためにサーバーに送信されます。

追加リソース

用語

さらに進む前に、Keycloak認可サービスによって導入されたこれらの用語と概念を理解することが重要です。

リソースサーバー

OAuth2用語に従い、リソースサーバーは、保護されたリソースをホストし、保護されたリソースリクエストを受け入れて応答できるサーバーです。

リソースサーバーは通常、保護されたリソースへのアクセスを許可する必要があるかどうかを決定するために、何らかの情報に依存しています。RESTfulベースのリソースサーバーの場合、その情報は通常、セキュリティトークンに含まれており、通常はサーバーへのすべてのリクエストとともにベアラートークンとして送信されます。ユーザーを認証するためにセッションに依存するWebアプリケーションは、通常、その情報をユーザーのセッションに保存し、各リクエストごとにそこから取得します。

Keycloakでは、すべてのコンフィデンシャルクライアントアプリケーションはリソースサーバーとして機能できます。このクライアントのリソースとそれぞれのスコープは、一連の認可ポリシーによって保護および管理されます。

リソース

リソースは、アプリケーションと組織の資産の一部です。これは、1つまたは複数のエンドポイントのセット、HTMLページなどの従来のWebリソースなどです。認可ポリシ

すべてのリソースは、単一のリソースまたはリソースのセットを表すことができる一意の識別子を持ちます。たとえば、すべての銀行口座に対する認可ポリシーのセットを表し、定義する銀行口座リソースを管理できます。しかし、単一の顧客が所有する単一のリソースを表し、独自の認可ポリシーのセットを持つことができる、アリスの銀行口座という別のリソースを持つこともできます。

スコープ

リソースのスコープとは、リソース上で実行可能なアクセス範囲の制限された広がりです。認可ポリシーの用語では、スコープとは、リソースに論理的に適用できる可能性のある多くの動詞の1つです。

通常、特定のリソースで何ができるかを示します。スコープの例としては、表示、編集、削除などがあります。ただし、スコープはリソースによって提供される特定の情報に関連付けることもできます。この場合、プロジェクトリソースとコストスコープを持つことができ、コストスコープは、ユーザーがプロジェクトのコストにアクセスするための特定のポリシーと許可を定義するために使用されます。

パーミッション

このシンプルで非常に一般的なパーミッションについて考えてみましょう。

パーミッションは、保護されているオブジェクトと、アクセスが許可されるかどうかを判断するために評価する必要があるポリシーを関連付けます。

  • X はリソース Z に対して Y を実行できる

    • ここで、…

      • X は、1人以上のユーザー、ロール、またはグループ、あるいはそれらの組み合わせを表します。ここではクレームとコンテキストを使用することもできます。

      • Y は、実行されるアクションを表します。たとえば、書き込み、表示などです。

      • Z は、保護されたリソースを表します。たとえば、"/accounts" などです。

Keycloakは、単純なものから非常に複雑なもの、ルールベースの動的パーミッションまで、幅広いパーミッション戦略を構築するための豊富なプラットフォームを提供します。柔軟性を提供し、以下を支援します。

  • コードのリファクタリングとパーミッション管理のコストを削減

  • より柔軟なセキュリティモデルをサポートし、セキュリティ要件の変更に容易に対応できるように支援

  • ランタイム時に変更を加える。アプリケーションは、保護されているリソースとスコープ、およびそれらがどのように保護されているかについてのみ関心があります。

ポリシー

ポリシーは、オブジェクトへのアクセスを許可するために満たす必要のある条件を定義します。パーミッションとは異なり、保護されているオブジェクトを指定するのではなく、特定オブジェクト(リソース、スコープ、またはその両方など)へのアクセスに対して満たす必要のある条件を指定します。ポリシーは、リソースを保護するために使用できるさまざまなアクセス制御メカニズム(ACM)と強く関連しています。ポリシーを使用すると、属性ベースのアクセス制御(ABAC)、ロールベースのアクセス制御(RBAC)、コンテキストベースのアクセス制御、またはこれらの任意の組み合わせの戦略を実装できます。

Keycloakは、集約ポリシーの概念を提供することにより、ポリシーの概念とポリシーの定義方法を活用しています。ここでは、「ポリシーのポリシー」を構築し、評価の動作を制御できます。特定のリソースへのアクセスに対して満たす必要のあるすべての条件を含む1つの大きなポリシーを作成する代わりに、Keycloak Authorization Servicesのポリシー実装は分割統治法に従います。つまり、個々のポリシーを作成し、それらを異なるパーミッションで再利用し、個々のポリシーを組み合わせることでより複雑なポリシーを構築できます。

ポリシープロバイダー

ポリシープロバイダーは、特定のポリシータイプの実装です。Keycloakは、対応するポリシープロバイダーによってバックアップされた組み込みポリシーを提供し、特定の要件をサポートするために独自のポリシータイプを作成できます。

Keycloakは、独自のポリシープロバイダー実装をプラグインするために使用できるSPI(サービスプロバイダーインターフェース)を提供します。

パーミッションチケット

パーミッションチケットは、User-Managed Access(UMA)仕様で定義された特別なタイプのトークンであり、その形式が認可サーバーによって決定される不透明な構造を提供します。この構造は、クライアントによって要求されているリソースやスコープ、アクセスコンテキスト、および認可データ(リクエスト当事者トークン[RPT])のリクエストに適用する必要があるポリシーを表します。

UMAでは、パーミッションチケットは、個人間の共有および組織間の共有をサポートするために不可欠です。認可ワークフローにパーミッションチケットを使用すると、リソース所有者とリソースサーバーが、これらのリソースへのアクセスを管理するきめ細かいポリシーに基づいて、リソースを完全に制御できる、単純なものから複雑なものまで、さまざまなシナリオが可能になります。

UMAワークフローでは、パーミッションチケットは認可サーバーによってリソースサーバーに発行され、リソースサーバーは保護されたリソースにアクセスしようとしているクライアントにパーミッションチケットを返します。クライアントがチケットを受信すると、チケットを認可サーバーに送り返すことにより、RPT(認可データを保持する最終トークン)のリクエストを行うことができます。

パーミッションチケットの詳細については、User-Managed Access および UMA 仕様を参照してください。

はじめに

特定のアプリケーションについては、Keycloak Authorization Servicesをすぐに開始するために、以下のリソースを参照できます。

リソースサーバーの管理

OAuth2仕様によると、リソースサーバーとは、保護されたリソースをホストし、保護されたリソースリクエストを受け入れて応答できるサーバーです。

Keycloakでは、リソースサーバーには、保護されたリソースに対するきめ細かい認可を有効にするための豊富なプラットフォームが提供されており、認可の決定はさまざまなアクセス制御メカニズムに基づいて行うことができます。

クライアントアプリケーションは、きめ細かいパーミッションをサポートするように構成できます。そうすることで、概念的にはクライアントアプリケーションをリソースサーバーに変えています。

クライアントアプリケーションの作成

Keycloak Authorization Servicesを有効にするための最初のステップは、リソースサーバーにしたいクライアントアプリケーションを作成することです。

手順
  1. Clientsをクリックします。

    クライアント

    Clients

  2. このページで、クライアントを作成をクリックします。

    クライアントを追加

    Add Client

  3. クライアントのクライアントIDを入力します。たとえば、my-resource-serverなどです。

  4. 次へをクリックします。

  5. クライアント認証をONに切り替えます。

  6. 保存をクリックします。

  7. アプリケーションのルートURLを入力します。例:

    http://${host}:${port}/my-resource-server
  8. 保存をクリックします。クライアントが作成され、クライアント設定ページが開きます。次のようなページが表示されます。

    クライアント設定

    Client Settings

認可サービスの有効化

OIDCクライアントをリソースサーバーに変えて、きめ細かい認可を有効にできます。

手順
  1. クライアント設定ページで、Capability Configセクションまでスクロールダウンします。

  2. Authorization EnabledOnに切り替えます。

  3. 保存をクリックします。

    認可サービスの有効化

    Enabling authorization services

    このクライアントの新しいAuthorizationタブが表示されます。Authorizationタブをクリックすると、次のようなページが表示されます。

    リソースサーバー設定

    Resource server settings

Authorizationタブには、アプリケーションのリソースを実際に保護するために従う必要のあるさまざまな手順をカバーする追加のサブタブが含まれています。各タブは、このドキュメントの特定のトピックで個別に説明されています。ただし、各タブの簡単な説明を以下に示します。

  • 設定

    リソースサーバーの一般的な設定。このページの詳細については、リソースサーバー設定セクションを参照してください。

  • リソース

    このページから、アプリケーションのリソースを管理できます。

  • 認可スコープ

    このページから、スコープを管理できます。

  • ポリシー

    このページから、認可ポリシーを管理し、パーミッションを付与するために満たす必要のある条件を定義できます。

  • パーミッション

    このページから、作成したポリシーとリンクすることにより、保護されたリソースとスコープのパーミッションを管理できます。

  • 評価

    このページから、認可リクエストをシミュレートし、定義したパーミッションと認可ポリシーの評価結果を表示できます。

  • 設定のエクスポート

    このページから、認可設定をJSONファイルにエクスポートできます。

リソースサーバー設定

リソースサーバー設定ページでは、ポリシー適用モードを設定し、リモートリソース管理を許可し、認可構成設定をエクスポートできます。

  • ポリシー適用モード

    サーバーに送信された認可リクエストを処理するときに、ポリシーがどのように適用されるかを指定します。

    • 強制

      (デフォルトモード)特定のリソースに関連付けられたポリシーがない場合でも、リクエストはデフォルトで拒否されます。

    • 許可的

      特定のリソースに関連付けられたポリシーがない場合でも、リクエストは許可されます。

    • 無効

      すべてのポリシーの評価を無効にし、すべてのリソースへのアクセスを許可します。

  • 決定戦略

    この構成は、ポリシー評価エンジンが、評価されたすべてのパーミッションの結果に基づいて、リソースまたはスコープを許可するかどうかをどのように決定するかを変更します。肯定とは、リソースとそのスコープへのアクセスを許可するために、少なくとも1つのパーミッションが肯定的な決定として評価される必要があることを意味します。全会一致とは、最終的な決定も肯定的であるためには、すべてのパーミッションが肯定的な決定として評価される必要があることを意味します。例として、同じリソースまたはスコープに対する2つのパーミッションが競合している場合(一方のパーミッションがアクセスを許可し、もう一方のパーミッションがアクセスを拒否している場合)、選択された戦略が肯定であれば、リソースまたはスコープへのパーミッションが付与されます。それ以外の場合、いずれかのパーミッションからの単一の拒否も、リソースまたはスコープへのアクセスを拒否します。

  • リモートリソース管理

    リソースをリソースサーバーによってリモートで管理できるかどうかを指定します。falseの場合、リソースは管理コンソールからのみ管理できます。

デフォルト設定

リソースサーバーを作成すると、Keycloakは新しく作成されたリソースサーバーのデフォルト設定を作成します。

デフォルト設定は以下で構成されています。

  • アプリケーション内のすべてのリソースを表すデフォルトの保護されたリソース。

  • このポリシーによって保護されたリソースへのアクセスを常に許可するポリシー。

  • デフォルトポリシーに基づいてすべてのリソースへのアクセスを管理するパーミッション。

デフォルトの保護されたリソースは、デフォルトリソースと呼ばれ、リソースタブに移動すると表示できます。

デフォルトリソース

Default resource

このリソースは、Type、つまりurn:my-resource-server:resources:defaultURI /*を定義します。ここで、URIフィールドは、このリソースがアプリケーション内のすべてのパスを表すことをKeycloakに示すワイルドカードパターンを定義します。言い換えれば、アプリケーションのポリシー適用を有効にすると、アクセスを許可する前に、リソースに関連付けられたすべてのパーミッションが調べられます。

前述のTypeは、デフォルトリソースまたは同じタイプを使用して作成する他のリソースに適用する必要がある型付きリソースパーミッションを作成するために使用できる値を定義します。

デフォルトポリシーは、レルムポリシーのみと呼ばれ、ポリシータブに移動すると表示できます。

デフォルトポリシー

Default policy

このポリシーは、このポリシーによって保護されたリソースへのアクセスを常に許可する条件を定義するJavaScriptベースのポリシーです。このポリシーをクリックすると、次のルールが定義されていることがわかります。

// by default, grants any permission associated with this policy
$evaluation.grant();

最後に、デフォルトパーミッションはデフォルトパーミッションと呼ばれ、パーミッションタブに移動すると表示できます。

デフォルトパーミッション

Default Permission

このパーミッションは、リソースベースのパーミッションであり、特定のタイプを持つすべてのリソースに適用される1つ以上のポリシーのセットを定義します。

デフォルト設定の変更

デフォルト設定は、デフォルトのリソース、ポリシー、またはパーミッション定義を削除し、独自の定義を作成することで変更できます。

デフォルトリソースは、/* パターンを使用してアプリケーション内の任意のリソースまたはパスにマッピングするURIで作成されます。独自のリソース、パーミッション、ポリシーを作成する前に、デフォルト設定が独自の設定と競合しないことを確認してください。

デフォルト設定は、アプリケーション内のすべてのパスにマッピングするリソースを定義します。独自のリソースへのパーミッションを記述しようとしている場合は、デフォルトリソースを削除するか、アプリケーション内のより具体的なパスにURISフィールドを変更してください。そうしないと、デフォルトリソースに関連付けられたポリシー(デフォルトでは常にアクセスを許可する)により、Keycloakは保護された任意のリソースへのアクセスを許可します。

認可構成のエクスポートとインポート

リソースサーバー(またはクライアント)の設定をエクスポートしてダウンロードできます。また、リソースサーバーの既存の設定ファイルをインポートすることもできます。設定ファイルのインポートとエクスポートは、リソースサーバーの初期設定を作成したり、既存の設定を更新したりする場合に役立ちます。設定ファイルには、以下の定義が含まれています。

  • 保護されたリソースとスコープ

  • ポリシー

  • パーミッション

設定ファイルのエクスポート

手順
  1. メニューのクライアントをクリックします。

  2. リソースサーバーとして作成したクライアントをクリックします。

  3. エクスポートタブをクリックします。

    設定のエクスポート

    Export Settings

設定ファイルはJSON形式でエクスポートされ、テキストエリアに表示されます。そこからコピー&ペーストできます。また、ダウンロードをクリックして設定ファイルをダウンロードして保存することもできます。

設定ファイルのインポート

リソースサーバーの設定ファイルをインポートできます。

手順
  1. リソースサーバー設定ページに移動します。

    設定のインポート

    Import Settings

  2. インポートをクリックし、インポートする設定を含むファイルを選択します。

リソースとスコープの管理

リソース管理は簡単で汎用的です。リソースサーバーを作成したら、保護したいリソースとスコープの作成を開始できます。リソースとスコープは、それぞれリソースタブとオーソリゼーションスコープタブに移動して管理できます。

リソースの表示

リソースページには、リソースサーバーに関連付けられたリソースのリストが表示されます。

リソース

Resources

リソースリストには、保護されたリソースに関する次の情報が提供されます。

  • タイプ

  • URI

  • オーナー

  • 関連付けられたスコープ(ある場合)

  • 関連付けられたパーミッション

このリストから、パーミッションを作成したいリソースのパーミッションを作成をクリックして、パーミッションを直接作成することもできます。

リソースのパーミッションを作成する前に、パーミッションに関連付けるポリシーを定義済みであることを確認してください。

リソースの作成

リソースの作成は簡単で汎用的です。主な関心事は、作成するリソースの粒度です。言い換えれば、リソースは1つまたは複数のリソースのセットを表すように作成でき、それらの定義方法はパーミッションの管理に非常に重要です。

新しいリソースを作成するには、リソースを作成をクリックします。

リソースの追加

Add resource

Keycloakでは、リソースは、次のようなさまざまなタイプのリソースに共通する少量の情報を定義します。

  • 名前

    このリソースを説明する、人間が判読できる一意の文字列。

  • タイプ

    1つまたは複数のリソースのセットのタイプを一意に識別する文字列。タイプは、さまざまなリソースインスタンスをグループ化するために使用される文字列です。たとえば、自動的に作成されるデフォルトリソースのデフォルトタイプはurn:resource-server-name:resources:defaultです。

  • URI

    リソースの場所/アドレスを提供するURI。HTTPリソースの場合、URIは通常、これらのリソースを提供するために使用される相対パスです。

  • スコープ

    リソースに関連付ける1つ以上のスコープ。

リソース属性

リソースには、属性を関連付けることができます。これらの属性は、リソースに関する追加情報を提供したり、リソースに関連付けられたパーミッションを評価する際にポリシーに追加情報を提供したりするために使用できます。

各属性はキーと値のペアであり、値は1つまたは複数の文字列のセットにすることができます。属性に複数の値を定義するには、各値をカンマで区切ります。

型付きリソース

リソースのタイプフィールドを使用すると、さまざまなリソースをグループ化して、共通のパーミッションセットを使用して保護できます。

リソースオーナー

リソースにはオーナーもいます。デフォルトでは、リソースはリソースサーバーによって所有されます。

ただし、リソースはユーザーに関連付けることもできるため、リソースオーナーに基づいてパーミッションを作成できます。たとえば、リソースオーナーのみが特定のリソースを削除または更新することを許可されるようにできます。

リソースのリモート管理

リソース管理は、リソースサーバーがリソースをリモートで管理できるように、Protection APIを通じて公開されています。

Protection APIを使用する場合、リソースサーバーは、ユーザーが所有するリソースを管理するように実装できます。この場合、ユーザー識別子を指定して、特定ユーザーに属するリソースとして構成できます。

Keycloakは、リソースサーバーにリソースの完全な制御を提供します。将来的には、ユーザーが自分のリソースを制御したり、特にUMAプロトコルを使用する場合に、オーソリゼーションリクエストを承認したり、パーミッションを管理したりできるようにする必要があります。

ポリシーの管理

前述のように、ポリシーは、オブジェクトへのアクセスを許可する前に満たす必要のある条件を定義します。

手順
  1. ポリシータブをクリックして、リソースサーバーに関連付けられたすべてのポリシーを表示します。

    ポリシー

    Policies

    このタブでは、以前に作成したポリシーのリストを表示したり、ポリシーを作成および編集したりできます。

新しいポリシーを作成するには、ポリシーを作成をクリックし、リストからポリシータイプを選択します。

各ポリシータイプの詳細については、このセクションで説明します。

ユーザーベースのポリシー

このタイプのポリシーを使用すると、1人または複数のユーザーのセットがオブジェクトへのアクセスを許可されるパーミッションの条件を定義できます。

新しいユーザーベースのポリシーを作成するには、ポリシーリストの右上隅にあるアイテムリストでユーザーを選択します。

ユーザーポリシーを追加

Add User Policy

設定

  • 名前

    ポリシーを識別する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • ユーザー

    このポリシーによってアクセスが許可されるユーザーを指定します。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

ロールベースのポリシー

このタイプのポリシーを使用すると、1つまたは複数のロールのセットがオブジェクトへのアクセスを許可されるパーミッションの条件を定義できます。

デフォルトでは、このポリシーに追加されたロールは必須として指定されておらず、アクセスをリクエストしているユーザーがこれらのロールのいずれかを付与されている場合、ポリシーはアクセスを許可します。ただし、特定のロールを強制したい場合は、特定のロールを必須として指定できます。レルムロールとクライアントロールのどちらであるかに関係なく、必須ロールと非必須ロールを組み合わせることもできます。

ロールポリシーは、特定のロールをオブジェクトへのアクセスを許可するために強制する必要がある、より制限されたロールベースのアクセス制御(RBAC)が必要な場合に役立ちます。たとえば、ユーザーがユーザーのリソースにアクセスするために(ユーザーに代わって行動している)クライアントアプリケーションを許可することに同意する必要があることを強制できます。Keycloakクライアントスコープマッピングを使用して、同意ページを有効にしたり、クライアントがKeycloakサーバーからアクセストークンを取得するときにスコープを明示的に提供するように強制したりすることもできます。

新しいロールベースのポリシーを作成するには、ポリシータイプリストからロールを選択します。

ロールポリシーを追加

Add Role Policy

設定

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • レルムロール

    このポリシーで許可されるレルムロールを指定します。

  • クライアントロール

    このポリシーで許可されるクライアントロールを指定します。このフィールドを有効にするには、最初にクライアントを選択する必要があります。

  • ロールのフェッチ

    デフォルトでは、認証リクエストとともに送信されたトークンから利用可能なロールのみが、ユーザーにロールが付与されているかどうかを確認するために使用されます。この設定を有効にすると、ポリシーはトークンからのロールを無視し、代わりにユーザーに関連付けられたロールを確認します。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

ロールを必須として定義する

ロールベースのポリシーを作成するときに、特定のロールをRequiredとして指定できます。これを行うと、アクセスをリクエストしているユーザーにすべて必須ロールが付与されている場合にのみ、ポリシーはアクセスを許可します。レルムロールとクライアントロールの両方をこのように構成できます。

必須ロールの例

Example of a required role

ロールを必須として指定するには、必須として構成するロールの必須チェックボックスをオンにします。

必須ロールは、ポリシーが複数のロールを定義しているが、そのサブセットのみが必須である場合に役立ちます。この場合、レルムロールとクライアントロールを組み合わせて、アプリケーションのよりきめ細かいロールベースのアクセス制御(RBAC)モデルを有効にできます。たとえば、クライアント固有のポリシーを持ち、そのクライアントに関連付けられた特定のクライアントロールを必須にすることができます。または、特定のレルムロールが存在する場合にのみアクセスが許可されるように強制することもできます。同じポリシー内で両方のアプローチを組み合わせることもできます。

JavaScriptベースのポリシー

属性ベースアクセス制御(ABAC)を以下の例のようにポリシー実装で使用している場合、ユーザーが保護された属性を編集できず、対応する属性が読み取り専用になっていることを確認してください。詳細については、脅威モデルの軽減の章を参照してください。

このタイプのポリシーを使用して、JavaScript を使用してパーミッションの条件を定義できます。これは、Keycloak でサポートされているルールベースのポリシータイプの 1 つであり、評価 API に基づいて任意のポリシーを柔軟に記述できます。

新しい JavaScript ベースのポリシーを作成するには、ポリシーリストの右上隅にある項目リストでJavaScriptを選択します。

デフォルトでは、JavaScript ポリシーをサーバーにアップロードすることはできません。JS ポリシーをサーバーに直接デプロイすることを推奨します。JavaScript プロバイダーで説明されています。

デプロイされた JAR ファイルから JS ポリシーを作成する

Keycloak では、サーバーにスクリプトをデプロイするために JAR ファイルをデプロイできます。詳細については、JavaScript プロバイダーを参照してください。

スクリプトをデプロイしたら、デプロイしたスクリプトを利用可能なポリシープロバイダーのリストから選択できるようになります。

評価コンテキストからの属性の確認

以下は、属性ベースアクセス制御(ABAC)を使用して、実行コンテキストから取得した属性に基づいて条件を定義する JavaScript ベースのポリシーの簡単な例です。

const context = $evaluation.getContext();
const contextAttributes = context.getAttributes();

if (contextAttributes.containsValue('kc.client.network.ip_address', '127.0.0.1')) {
    $evaluation.grant();
}
現在のアイデンティティからの属性の確認

以下は、属性ベースアクセス制御(ABAC)を使用して、現在のアイデンティティに関連付けられた属性に基づいて条件を定義する JavaScript ベースのポリシーの簡単な例です。

const context = $evaluation.getContext();
const identity = context.getIdentity();
const attributes = identity.getAttributes();
const email = attributes.getValue('email').asString(0);

if (email.endsWith('@keycloak.org')) {
    $evaluation.grant();
}

これらの属性は、認証リクエストで使用されたトークンで定義されているクレームからマッピングされます。

現在のアイデンティティに付与されたロールの確認

ポリシーでロールベースアクセス制御(RBAC)を使用することもできます。以下の例では、ユーザーに keycloak_user realm ロールが付与されているかどうかを確認します。

const context = $evaluation.getContext();
const identity = context.getIdentity();

if (identity.hasRealmRole('keycloak_user')) {
    $evaluation.grant();
}

または、ユーザーに my-client-role client ロールが付与されているかどうかを確認できます。ここで、my-client はクライアントアプリケーションのクライアント ID です。

const context = $evaluation.getContext();
const identity = context.getIdentity();

if (identity.hasClientRole('my-client', 'my-client-role')) {
    $evaluation.grant();
}
ユーザーに付与されたロールの確認

ユーザーに付与された realm ロールを確認するには

const realm = $evaluation.getRealm();

if (realm.isUserInRealmRole('marta', 'role-a')) {
    $evaluation.grant();
}

またはユーザーに付与されたクライアントロールを確認するには

const realm = $evaluation.getRealm();

if (realm.isUserInClientRole('marta', 'my-client', 'some-client-role')) {
    $evaluation.grant();
}
グループに付与されたロールの確認

グループに付与された realm ロールを確認するには

const realm = $evaluation.getRealm();

if (realm.isGroupInRole('/Group A/Group D', 'role-a')) {
    $evaluation.grant();
}
任意クレームのリソースサーバーへのプッシュ

パーミッションがどのように強制されるかに関する追加情報を提供するために、任意クレームをリソースサーバーにプッシュするには

const permission = $evaluation.getPermission();

// decide if permission should be granted

if (granted) {
    permission.addClaim('claim-a', 'claim-a');
    permission.addClaim('claim-a', 'claim-a1');
    permission.addClaim('claim-b', 'claim-b');
}
グループメンバーシップの確認
const realm = $evaluation.getRealm();

if (realm.isUserInGroup('marta', '/Group A/Group B')) {
    $evaluation.grant();
}
異なるアクセス制御メカニズムの組み合わせ

いくつかのアクセス制御メカニズムを組み合わせて使用することもできます。以下の例は、ロール(RBAC)とクレーム/属性(ABAC)のチェックを同じポリシー内でどのように使用できるかを示しています。この例では、ユーザーに admin ロールが付与されているか、または keycloak.org ドメインのメールアドレスを持っているかを確認します。

const context = $evaluation.getContext();
const identity = context.getIdentity();
const attributes = identity.getAttributes();
const email = attributes.getValue('email').asString(0);

if (identity.hasRealmRole('admin') || email.endsWith('@keycloak.org')) {
    $evaluation.grant();
}
独自のルールを記述する際には、$evaluation オブジェクトが org.keycloak.authorization.policy.evaluation.Evaluation を実装するオブジェクトであることを念頭に置いてください。このインターフェースからアクセスできるものの詳細については、評価 API を参照してください。

時間ベースポリシー

このタイプのポリシーを使用して、パーミッションの時間条件を定義できます。

新しい時間ベースポリシーを作成するには、ポリシーリストの右上隅にある項目リストで時間を選択します。

時間ポリシーを追加

Add Time Policy

設定

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • 開始時間

    アクセスを許可しない必要がある時間を定義します。パーミッションは、現在の日時がこの値以降である場合にのみ許可されます。

  • 有効期限

    アクセスを許可しない必要がある時間を定義します。パーミッションは、現在の日時がこの値以前である場合にのみ許可されます。特定の、またはにアクセスを繰り返す場合は、繰り返しを選択します。

  • アクセスを許可する必要がある日を定義します。日付の範囲を指定することもできます。この場合、パーミッションは、現在の日が指定された 2 つの値の間または等しい場合にのみ許可されます。

  • アクセスを許可する必要がある月を定義します。月の範囲を指定することもできます。この場合、パーミッションは、現在の月が指定された 2 つの値の間または等しい場合にのみ許可されます。

  • アクセスを許可する必要がある年を定義します。年の範囲を指定することもできます。この場合、パーミッションは、現在の年が指定された 2 つの値の間または等しい場合にのみ許可されます。

  • アクセスを許可する必要がある時間を定義します。時間の範囲を指定することもできます。この場合、パーミッションは、現在の時間が指定された 2 つの値の間または等しい場合にのみ許可されます。

  • アクセスを許可する必要がある分を定義します。分の範囲を指定することもできます。この場合、パーミッションは、現在の分が指定された 2 つの値の間または等しい場合にのみ許可されます。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

アクセスは、すべての条件が満たされた場合にのみ許可されます。Keycloak は、各条件の結果に基づいてANDを実行します。

集約ポリシー

前述のように、Keycloak ではポリシーのポリシー、つまりポリシー集約と呼ばれる概念を構築できます。ポリシー集約を使用すると、既存のポリシーを再利用してより複雑なポリシーを構築し、認証リクエストの処理中に評価されるポリシーからパーミッションをさらに分離できます。

新しい集約ポリシーを作成するには、ポリシータイプリストから集約を選択します。

集約ポリシーを追加

Add aggregated policy

機密リソースというリソースがあり、keycloak.org ドメインのユーザーと特定の IP アドレス範囲からのユーザーのみがアクセスできるとします。両方の条件を持つ単一のポリシーを作成できます。ただし、このポリシーのドメイン部分を、発信元ネットワークに関係なく動作するパーミッションに適用するために再利用したいと考えています。

ドメイン条件とネットワーク条件の両方に個別のポリシーを作成し、これら 2 つのポリシーの組み合わせに基づいて 3 番目のポリシーを作成できます。集約ポリシーを使用すると、他のポリシーを自由に組み合わせて、新しい集約ポリシーを任意のパーミッションに適用できます。

集約ポリシーを作成する際には、ポリシー間に循環参照または依存関係が発生しないように注意してください。循環依存関係が検出された場合、ポリシーを作成または更新することはできません。

設定

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用することを強くお勧めします。これにより、ポリシーをより簡単に識別し、その意味を理解できます。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • ポリシーを適用

    集約ポリシーに関連付ける 1 つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成できます。

  • 決定戦略

    このパーミッションの決定戦略。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

集約ポリシーの決定戦略

集約ポリシーを作成する際には、各ポリシーの結果に基づいて最終的な決定を判断するために使用される決定戦略も定義できます。

  • 全員一致

    何も指定されていない場合のデフォルトの戦略。この場合、最終的な決定も肯定的になるためには、すべてのポリシーが肯定的な決定を評価する必要があります。

  • 賛成

    この場合、最終的な決定も肯定的になるためには、少なくとも 1 つのポリシーが肯定的な決定を評価する必要があります。

  • 合意

    この場合、肯定的な決定の数が否定的な決定の数よりも多くなければなりません。肯定的な決定と否定的な決定の数が同じ場合、最終的な決定は否定的になります。

クライアントベースポリシー

このタイプのポリシーを使用して、1 つ以上のクライアントのセットがオブジェクトへのアクセスを許可されているパーミッションの条件を定義できます。

新しいクライアントベースポリシーを作成するには、ポリシータイプリストからクライアントを選択します。

クライアントポリシーを追加

Add a Client Policy

設定

  • 名前

    ポリシーを識別する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • クライアント

    このポリシーによってアクセスが許可されているクライアントを指定します。グループベースポリシー。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

グループベースポリシー

このタイプのポリシーを使用して、1 つ以上のグループ(およびその階層)のセットがオブジェクトへのアクセスを許可されているパーミッションの条件を定義できます。

新しいグループベースポリシーを作成するには、ポリシータイプリストからグループを選択します。

グループポリシー

Add Group Policy

設定

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • グループクレーム

    トークン内のグループ名やパスを保持するクレームの名前を指定します。通常、認証リクエストは、以前に一部のユーザーの代わりに行動するクライアントに発行された ID トークンまたはアクセストークンに基づいて処理されます。定義されている場合、トークンには、このポリシーがユーザーがメンバーであるグループを取得するクレームを含める必要があります。定義されていない場合、ユーザーのグループはレルム構成から取得されます。

  • グループ

    パーミッションを評価する際にこのポリシーによって強制されるグループを選択できます。グループを追加した後、子グループにも適用チェックボックスをオンにすることで、グループの子へのアクセスを拡張できます。オフのままにすると、アクセス制限は選択したグループにのみ適用されます。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

子グループへのアクセス拡張

デフォルトでは、グループをこのポリシーに追加すると、アクセス制限は選択したグループのメンバーにのみ適用されます。

状況によっては、グループ自体だけでなく、階層内の任意の子グループへのアクセスを許可する必要がある場合があります。追加された任意のグループについて、子グループへのアクセスを拡張するために子グループにも適用チェックボックスをオンにすることができます。

子グループへのアクセス拡張

Extending access to child groups

上記の例では、ポリシーは IT またはその子グループのメンバーであるすべてのユーザーにアクセスを許可しています。

クライアントスコープベースポリシー

このタイプのポリシーを使用して、1 つ以上のクライアントスコープのセットがオブジェクトへのアクセスを許可されているパーミッションの条件を定義できます。

デフォルトでは、このポリシーに追加されたクライアントスコープは必須として指定されておらず、アクセスをリクエストしているクライアントがこれらのクライアントスコープのいずれかを許可されている場合、ポリシーはアクセスを許可します。ただし、特定のクライアントスコープを強制したい場合は、特定のクライアントスコープを必須として指定できます。

新しいクライアントスコープベースのポリシーを作成するには、ポリシータイプリストからClient Scopeを選択します。

クライアントスコープポリシーの追加

Add Client Scope Policy

構成

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • クライアントスコープ

    このポリシーで許可されるクライアントスコープを指定します。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック。

クライアントスコープを必須として定義する

クライアントスコープベースのポリシーを作成する際に、特定のクライアントスコープをRequiredとして指定できます。その場合、アクセスをリクエストしているクライアントがすべての必須クライアントスコープを許可されている場合にのみ、ポリシーはアクセスを許可します。

必須クライアントスコープの例

Example of required client scope

クライアントスコープを必須として指定するには、必須として構成するクライアントスコープのRequiredチェックボックスをオンにします。

必須クライアントスコープは、ポリシーが複数のクライアントスコープを定義しているが、そのサブセットのみが必須である場合に役立ちます。

Regexベースのポリシー

このタイプのポリシーを使用すると、パーミッションの正規表現条件を定義できます。

新しいRegexベースのポリシーを作成するには、ポリシータイプリストからRegexを選択します。

このポリシーは、現在のアイデンティティから利用可能な属性を解決します。

Regexポリシーの追加

Add Regex Policy

構成

  • 名前

    ポリシーを説明する、人間が判読できる一意の文字列。ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることをお勧めします。

  • 説明

    このポリシーに関する詳細を含む文字列。

  • ターゲットクレーム

    トークン内のターゲットクレームの名前を指定します。JSONベースのクレームの場合、ドット表記法を使用してネストし、角括弧を使用してインデックスで配列フィールドにアクセスできます。たとえば、contact.address[0].country などです。ターゲットクレームがJSONオブジェクトを参照する場合、最初のパス(たとえば、contact)は、JSONオブジェクトを保持する属性名にマップする必要があります。

  • Regexパターン

    正規表現パターンを指定します。

  • ロジック

    他の条件が評価された後に適用するこのポリシーのロジック

肯定および否定ロジック

ポリシーは、肯定または否定ロジックで構成できます。簡単に言えば、このオプションを使用して、ポリシーの結果をそのまま維持するか、否定するかを定義できます。

たとえば、特定のロールが付与されていないユーザーのみにアクセス権を付与するポリシーを作成するとします。この場合、そのロールを使用してロールベースのポリシーを作成し、そのロジックフィールドをNegativeに設定できます。デフォルトの動作であるPositiveを維持すると、ポリシーの結果はそのまま維持されます。

ポリシー評価API

JavaScriptを使用してルールベースのポリシーを作成する場合、Keycloakは、パーミッションを付与する必要があるかどうかを判断するのに役立つ有用な情報を提供する評価APIを提供します。

このAPIは、次のような情報へのアクセスを提供するいくつかのインターフェースで構成されています。

  • 評価対象のパーミッション。リクエストされているリソースとスコープの両方を表します。

  • リクエストされているリソースに関連付けられた属性

  • ランタイム環境および実行コンテキストに関連付けられたその他の属性

  • グループメンバーシップやロールなどのユーザーに関する情報

メインインターフェースはorg.keycloak.authorization.policy.evaluation.Evaluationであり、次のコントラクトを定義します。

public interface Evaluation {

    /**
     * Returns the {@link ResourcePermission} to be evaluated.
     *
     * @return the permission to be evaluated
     */
    ResourcePermission getPermission();

    /**
     * Returns the {@link EvaluationContext}. Which provides access to the whole evaluation runtime context.
     *
     * @return the evaluation context
     */
    EvaluationContext getContext();

    /**
     * Returns a {@link Realm} that can be used by policies to query information.
     *
     * @return a {@link Realm} instance
     */
    Realm getRealm();

    /**
     * Grants the requested permission to the caller.
     */
    void grant();

    /**
     * Denies the requested permission.
     */
    void deny();
}

認証リクエストを処理する際、Keycloakはポリシーを評価する前にEvaluationインスタンスを作成します。このインスタンスは、アクセスがGRANTまたはDENYのどちらであるかを判断するために、各ポリシーに渡されます。

ポリシーは、Evaluationインスタンスでgrant()またはdeny()メソッドを呼び出すことによってこれを決定します。デフォルトでは、Evaluationインスタンスの状態は拒否されているため、ポリシー評価エンジンにパーミッションを付与する必要があることを示すには、ポリシーがgrant()メソッドを明示的に呼び出す必要があります。

追加リソース

評価コンテキスト

評価コンテキストは、ポリシーの評価中にポリシーに役立つ情報を提供します。

public interface EvaluationContext {

    /**
     * Returns the {@link Identity} that represents an entity (person or non-person) to which the permissions must be granted, or not.
     *
     * @return the identity to which the permissions must be granted, or not
     */
    Identity getIdentity();

    /**
     * Returns all attributes within the current execution and runtime environment.
     *
     * @return the attributes within the current execution and runtime environment
     */
    Attributes getAttributes();
}

このインターフェースから、ポリシーは以下を取得できます。

  • 認証されたIdentity

  • 実行コンテキストとランタイム環境に関する情報

Identityは、認証リクエストとともに送信されたOAuth2アクセストークンに基づいて構築されており、この構成は元のトークンから抽出されたすべてのクレームにアクセスできます。たとえば、プロトコルマッパーを使用してカスタムクレームをOAuth2アクセストークンに含める場合、ポリシーからこのクレームにアクセスして、条件を構築するために使用することもできます。

EvaluationContextは、実行環境とランタイム環境の両方に関連する属性へのアクセスも提供します。今のところ、これらはいくつかの組み込み属性のみです。

表1. 実行環境とランタイム環境の属性
名前 説明 タイプ

kc.time.date_time

現在の日時

文字列。形式 MM/dd/yyyy hh:mm:ss

kc.client.network.ip_address

クライアントのIPアドレス。有効なIPが提供されていない場合はnullになる可能性があります。

文字列

kc.client.network.host

クライアントのホスト名。IPアドレスまたはプロキシヘッダーによって提供されるものになります

文字列

kc.client.id

クライアントID

文字列

kc.client.user_agent

'User-Agent' HTTPヘッダーの値

文字列配列

kc.realm.name

レルムの名前

文字列

パーミッションの管理

パーミッションは、保護されるオブジェクトと、アクセスを許可するかどうかを決定するために評価する必要があるポリシーを関連付けます。

保護するリソースと、これらのリソースを保護するために使用するポリシーを作成したら、パーミッションの管理を開始できます。パーミッションを管理するには、リソースサーバーの編集時にPermissionsタブをクリックします。

パーミッション

Permissions

パーミッションは、主に2つのタイプのオブジェクトを保護するために作成できます。

  • リソース

  • スコープ

パーミッションを作成するには、パーミッションリストの右上隅にある項目リストから、作成するパーミッションタイプを選択します。次のセクションでは、これら2つのタイプのオブジェクトについて詳しく説明します。

リソースベースのパーミッションの作成

リソースベースのパーミッションは、1つ以上のリソースのセットを定義し、1つ以上の認証ポリシーのセットを使用して保護します。

新しいリソースベースのパーミッションを作成するには、パーミッションの作成ドロップダウンからリソースベースのパーミッションを作成を選択します。

リソースパーミッションの追加

Add Resource Permission

構成

  • 名前

    パーミッションを説明する人間が読める一意の文字列。ベストプラクティスは、ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることです。

  • 説明

    このパーミッションに関する詳細を含む文字列。

  • リソースタイプに適用

    パーミッションを特定のタイプを持つすべてのリソースに適用するかどうかを指定します。このフィールドを選択すると、保護するリソースタイプを入力するように求められます。

    • リソースタイプ

      保護するリソースタイプを定義します。定義すると、このパーミッションは、そのタイプに一致するすべてのリソースに対して評価されます。

  • リソース

    保護する1つ以上のリソースのセットを定義します。

  • ポリシー

    パーミッションに関連付ける1つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成できます。

  • 決定戦略

    このパーミッションの決定戦略

タイプ指定されたリソースパーミッション

リソースパーミッションは、特定のタイプを持つすべてのリソースに適用されるポリシーを定義するためにも使用できます。この形式のリソースベースのパーミッションは、共通のアクセス要件と制約を共有するリソースがある場合に役立ちます。

多くの場合、アプリケーション内のリソースは、カプセル化するデータまたは提供する機能に基づいて分類(またはタイプ指定)できます。たとえば、金融アプリケーションは、それぞれが特定の顧客に属するさまざまな銀行口座を管理できます。それらは異なる銀行口座ですが、銀行組織によってグローバルに定義された共通のセキュリティ要件と制約を共有しています。タイプ指定されたリソースパーミッションを使用すると、すべての銀行口座に適用する共通ポリシーを定義できます。例:

  • 所有者のみが自分の口座を管理できる

  • 所有者の国/地域からのアクセスのみを許可する

  • 特定の認証方法を強制する

タイプ指定されたリソースパーミッションを作成するには、新しいリソースベースのパーミッションを作成するときにリソースタイプに適用をクリックします。リソースタイプに適用オンに設定すると、保護するタイプと、指定したタイプを持つすべてのリソースへのアクセスを管理するために適用されるポリシーを指定できます。

タイプ指定されたリソースパーミッションの例

Example of a typed resource permission

スコープベースのパーミッションの作成

スコープベースのパーミッションは、1つ以上のスコープのセットを定義し、1つ以上の認証ポリシーのセットを使用して保護します。リソースベースのパーミッションとは異なり、このパーミッションタイプを使用すると、リソースだけでなく、それに関連付けられたスコープのパーミッションも作成でき、リソースとリソースで実行できるアクションを管理するパーミッションを定義する際に、よりきめ細かい制御が可能になります。

新しいスコープベースのパーミッションを作成するには、パーミッションの作成ドロップダウンからスコープベースのパーミッションを作成を選択します。

スコープパーミッションの追加

Add Scope Permission

構成

  • 名前

    パーミッションを説明する人間が読める一意の文字列。ベストプラクティスは、ビジネスおよびセキュリティ要件に密接に関連する名前を使用して、より簡単に識別できるようにすることです。

  • 説明

    このパーミッションに関する詳細を含む文字列。

  • リソース

    スコープを選択したリソースに関連付けられたスコープに制限します。何も選択されていない場合、すべてのスコープが利用可能です。

  • スコープ

    保護する1つ以上のスコープのセットを定義します。

  • ポリシー

    パーミッションに関連付ける1つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成できます。

  • 決定戦略

    このパーミッションの決定戦略

ポリシー決定戦略

ポリシーをパーミッションに関連付ける場合、関連付けられたポリシーの結果を評価してアクセスを決定する方法を指定する決定戦略も定義できます。

  • 全員一致

    何も指定されていない場合のデフォルトの戦略。この場合、最終的な決定も肯定的になるためには、すべてのポリシーが肯定的な決定を評価する必要があります。

  • 賛成

    この場合、最終的な決定を肯定的なものにするためには、少なくとも1つのポリシーが肯定的な決定として評価される必要があります。

  • 合意

    この場合、肯定的な決定の数が否定的な決定の数よりも多い必要があります。肯定的な決定と否定的な決定の数が等しい場合、最終的な決定は否定的になります。

ポリシーの評価とテスト

ポリシーを設計する際、ポリシーがどのように評価されるかをテストするために、認可リクエストをシミュレートできます。

リソースサーバーの編集時にEvaluateタブをクリックすると、ポリシー評価ツールにアクセスできます。そこで、実際のリクエストをシミュレートするためのさまざまな入力を指定し、ポリシーの効果をテストできます。

ポリシー評価ツール

Policy evaluation tool

アイデンティティ情報の提供

アイデンティティ情報フィルターは、許可をリクエストするユーザーを指定するために使用できます。

コンテキスト情報の提供

コンテキスト情報フィルターは、評価コンテキストに追加の属性を定義するために使用でき、ポリシーはこれらの同じ属性を取得できます。

許可の提供

許可フィルターは、認可リクエストを構築するために使用できます。1つまたは複数のリソースとスコープのセットに対する許可をリクエストできます。保護されたすべてのリソースとスコープに基づいて認可リクエストをシミュレートする場合は、ResourcesまたはScopesを指定せずにAddをクリックします。

目的の値を指定したら、Evaluateをクリックします。

認可サービス

Keycloak 認可サービスは、OAuth2 や User-Managed Access 仕様などのよく知られた標準に基づいて構築されています。

OAuth2クライアント(フロントエンドアプリケーションなど)は、トークンエンドポイントを使用してサーバーからアクセストークンを取得し、これらの同じトークンを使用して、リソースサーバー(バックエンドサービスなど)によって保護されたリソースにアクセスできます。同様に、Keycloak認可サービスは、リクエストされているリソースまたはスコープに関連付けられたすべてのポリシーの処理に基づいてアクセストークンを発行できるように、OAuth2への拡張機能を提供します。これは、リソースサーバーが、サーバーによって許可され、アクセストークンによって保持されているパーミッションに基づいて、保護されたリソースへのアクセスを強制できることを意味します。Keycloak認可サービスでは、パーミッションを持つアクセストークンは、リクエスターパーティートークンまたは略してRPTと呼ばれます。

RPT の発行に加えて、Keycloak 認可サービスは、リソースサーバーが保護されたリソース、スコープ、許可、およびポリシーを管理できるようにする一連の RESTful エンドポイントも提供し、開発者がこれらの機能をアプリケーションに拡張または統合して、きめ細かい認可をサポートできるようにします。

認可サービスのエンドポイントとメタデータの検出

Keycloak は、クライアントが Keycloak 認可サービスと対話するために必要なすべての情報 (エンドポイントの場所や機能など) を取得できるディスカバリー ドキュメントを提供します。

ディスカバリー ドキュメントは、以下から取得できます。

curl -X GET \
  http://${host}:${port}/realms/${realm-name}/.well-known/uma2-configuration

ここで、${host}:${port}は Keycloak が実行されているホスト名 (または IP アドレス) とポートであり、${realm-name}は Keycloak 内のレルムの名前です。

結果として、次のようなレスポンスが得られるはずです。

{

    // some claims are expected here

    // these are the main claims in the discovery document about Authorization Services endpoints location
    "token_endpoint": "http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token",
    "token_introspection_endpoint": "http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token/introspect",
    "resource_registration_endpoint": "http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set",
    "permission_endpoint": "http://${host}:${port}/realms/${realm-name}/authz/protection/permission",
    "policy_endpoint": "http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy"
}

これらの各エンドポイントは、特定の機能セットを公開します。

  • token_endpoint

    urn:ietf:params:oauth:grant-type:uma-ticketグラントタイプをサポートする OAuth2 準拠のトークンエンドポイント。このエンドポイントを介して、クライアントは認可リクエストを送信し、Keycloak によって許可されたすべての許可を含む RPT を取得できます。

  • token_introspection_endpoint

    OAuth2 準拠のトークンイントロスペクションエンドポイント。クライアントはこれを使用して、サーバーにクエリを実行して RPT のアクティブ状態を判断したり、Keycloak によって許可された許可など、トークンに関連付けられたその他の情報を判断したりできます。

  • resource_registration_endpoint

    UMA 準拠のリソース登録エンドポイント。リソースサーバーはこれを使用して、保護されたリソースとスコープを管理できます。このエンドポイントは、Keycloak でのリソースとスコープの作成、読み取り、更新、および削除操作を提供します。

  • permission_endpoint

    UMA 準拠の許可エンドポイント。リソースサーバーはこれを使用して、許可チケットを管理できます。このエンドポイントは、Keycloak での許可チケットの作成、読み取り、更新、および削除操作を提供します。

許可の取得

Keycloak から許可を取得するには、トークンエンドポイントに認可リクエストを送信します。結果として、Keycloak はリクエストされているリソースとスコープに関連付けられたすべてのポリシーを評価し、サーバーによって許可されたすべての許可を含む RPT を発行します。

クライアントは、次のパラメータを使用してトークンエンドポイントに認可リクエストを送信できます。

  • grant_type

    このパラメータは必須です。urn:ietf:params:oauth:grant-type:uma-ticketである必要があります。

  • ticket

    このパラメータはオプションです。UMA 認可プロセスの一部としてクライアントが受信した最新の許可チケット。

  • claim_token

    このパラメータはオプションです。リクエストされているリソースとスコープの許可を評価する際にサーバーが考慮する必要がある追加のクレームを表す文字列。このパラメータを使用すると、クライアントはクレームを Keycloak にプッシュできます。サポートされているすべてのトークン形式の詳細については、claim_token_formatパラメータを参照してください。

  • claim_token_format

    このパラメータはオプションです。claim_tokenパラメータで指定されたトークンの形式を示す文字列。Keycloak は、urn:ietf:params:oauth:token-type:jwthttps://openid.net/specs/openid-connect-core-1_0.html#IDTokenの 2 つのトークン形式をサポートしています。urn:ietf:params:oauth:token-type:jwt形式は、claim_tokenパラメータがアクセストークンを参照していることを示します。https://openid.net/specs/openid-connect-core-1_0.html#IDTokenは、claim_tokenパラメータが OpenID Connect ID トークンを参照していることを示します。

  • rpt

    このパラメータはオプションです。以前に発行された RPT。その許可も評価され、新しい RPT に追加される必要があります。このパラメータを使用すると、RPT を所有しているクライアントは、許可がオンデマンドで追加されるインクリメンタル認可を実行できます。

  • permission

    このパラメータはオプションです。クライアントがアクセスを求めている 1 つまたは複数のリソースとスコープのセットを表す文字列。このパラメータは、複数のリソースとスコープの許可をリクエストするために複数回定義できます。このパラメータは、許可チケットなしでクライアントが認可リクエストを送信できるようにするためのurn:ietf:params:oauth:grant-type:uma-ticketグラントタイプの拡張機能です。文字列の形式はRESOURCE_ID#SCOPE_IDである必要があります。例:Resource A#Scope AResource A#Scope A, Scope B, Scope CResource A#Scope A

  • permission_resource_format

    このパラメータはオプションです。permissionパラメータのリソースを示す形式を表す文字列。使用可能な値はiduriです。idは形式がRESOURCE_IDであることを示します。uriは形式がURIであることを示します。指定しない場合、デフォルトはidです。

  • permission_resource_matching_uri

    このパラメータはオプションです。permissionパラメータで URI 形式でリソースを表すときに、パスマッチングを使用するかどうかを示すブール値。指定しない場合、デフォルトは false です。

  • audience

    このパラメータはオプションです。クライアントがアクセスを求めているリソースサーバーのクライアント識別子。このパラメータは、permissionパラメータが定義されている場合に必須です。これは、許可を評価する必要があるコンテキストを示すヒントとして Keycloak に提供されます。

  • response_include_resource_name

    このパラメータはオプションです。リソース名を RPT の許可に含める必要があるかどうかをサーバーに示すブール値。false の場合、リソース識別子のみが含まれます。

  • response_permissions_limit

    このパラメータはオプションです。RPT が持つことができる許可の量を制限する整数 N。rptパラメータと一緒に使用すると、最後にリクエストされた N 個の許可のみが RPT に保持されます。

  • submit_request

    このパラメータはオプションです。サーバーが許可チケットによって参照されるリソースとスコープへの許可リクエストを作成する必要があるかどうかを示すブール値。このパラメータは、UMA 認可プロセスの一部としてticketパラメータと一緒に使用した場合にのみ有効です。

  • response_mode

    このパラメータはオプションです。サーバーが認可リクエストにどのように応答する必要があるかを示す文字列値。このパラメータは、標準の OAuth2 レスポンスではなく、主に全体的な決定またはサーバーによって許可された許可に関心がある場合に特に役立ちます。使用可能な値は次のとおりです。

    • decision

      サーバーからのレスポンスが、次の形式の JSON を返すことによって全体的な決定のみを表す必要があることを示します。

      {
          'result': true
      }

      認可リクエストが許可にマップされない場合、代わりに403 HTTP ステータスコードが返されます。

    • permissions

      サーバーからのレスポンスに、次の形式の JSON を返すことによってサーバーによって許可された許可が含まれる必要があることを示します。

      [
          {
              'rsid': 'My Resource'
              'scopes': ['view', 'update']
          },
      
          ...
      ]

      認可リクエストが許可にマップされない場合、代わりに403 HTTP ステータスコードが返されます。

クライアントがリソースサーバーによって保護された 2 つのリソースへのアクセスを求めている場合の認可リクエストの例。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "audience={resource_server_client_id}" \
  --data "permission=Resource A#Scope A" \
  --data "permission=Resource B#Scope B"

クライアントがリソースサーバーによって保護された任意のリソースとスコープへのアクセスを求めている場合の認可リクエストの例。注:これはすべてのリソースの許可を評価するわけではありません。代わりに、リソースサーバーが所有するリソース、リクエストユーザーが所有するリソース、および他の所有者によってリクエストユーザーに明示的に付与されたリソースの許可が評価されます。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "audience={resource_server_client_id}"

認可プロセスの一部としてリソースサーバーから許可チケットを受信した後、クライアントが UMA 保護リソースへのアクセスを求めている場合の認可リクエストの例

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "ticket=${permission_ticket}

Keycloak 評価プロセスが許可の発行につながった場合、許可が関連付けられている RPT を発行します。

Keycloak はクライアントに RPT で応答します。
HTTP/1.1 200 OK
Content-Type: application/json
...
{
    "access_token": "${rpt}",
}

サーバーからのレスポンスは、他のグラントタイプを使用する場合のトークンエンドポイントからの他のレスポンスとまったく同じです。RPT はaccess_tokenレスポンスパラメータから取得できます。クライアントが認可されていない場合、Keycloak は403 HTTP ステータスコードで応答します。

Keycloak は認可リクエストを拒否します。
HTTP/1.1 403 Forbidden
Content-Type: application/json
...
{
    "error": "access_denied",
    "error_description": "request_denied"
}

クライアント認証方法

クライアントが RPT を取得するには、トークンエンドポイントに対して認証を行う必要があります。urn:ietf:params:oauth:grant-type:uma-ticketグラントタイプを使用する場合、クライアントはこれらの認証方法のいずれかを使用できます。

  • ベアラートークン

    クライアントは、アクセストークンをベアラークレデンシャルとして HTTP Authorization ヘッダーでトークンエンドポイントに送信する必要があります。

    例:トークンエンドポイントに対して認証するためにアクセストークンを使用する認可リクエスト
    curl -X POST \
      http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
      -H "Authorization: Bearer ${access_token}" \
      --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket"

    この方法は、クライアントがユーザーの代わりに行動している場合に特に役立ちます。この場合、ベアラートークンは、以前に Keycloak によってユーザー(または自分自身)の代わりに行動する一部のクライアントに発行されたアクセストークンです。許可は、アクセストークンによって表されるアクセスコンテキストを考慮して評価されます。たとえば、アクセストークンがユーザー A の代わりに行動するクライアント A に発行された場合、許可はユーザー A がアクセスできるリソースとスコープに応じて付与されます。

  • クライアントクレデンシャル

    クライアントは、Keycloak でサポートされているクライアント認証方法のいずれかを使用できます。たとえば、client_id/client_secret または JWT などです。

    例:トークンエンドポイントに対して認証するためにクライアント ID とクライアントシークレットを使用する認可リクエスト
    curl -X POST \
      http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
      -H "Authorization: Basic cGhvdGg6L7Jl13RmfWgtkk==pOnNlY3JldA==" \
      --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket"

クレームのプッシュ

サーバーから許可を取得するときに、任意のクレームをプッシュして、許可を評価するときにポリシーでこれらのクレームを利用できるようにすることができます。

許可チケット (UMA フロー) を使用せずにサーバーから許可を取得している場合は、次のようにトークンエンドポイントに認可リクエストを送信できます。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "claim_token=ewogICAib3JnYW5pemF0aW9uIjogWyJhY21lIl0KfQ==" \
  --data "claim_token_format=urn:ietf:params:oauth:token-type:jwt" \
  --data "client_id={resource_server_client_id}" \
  --data "client_secret={resource_server_client_secret}" \
  --data "audience={resource_server_client_id}"

claim_tokenパラメータは、以下の例と同様の形式の BASE64 エンコードされた JSON を予期しています。

{
    "organization" : ["acme"]
}

この形式は、1 つ以上のクレームを予期しており、各クレームの値は文字列の配列である必要があります。

UMA を使用したクレームのプッシュ

UMA と許可チケットを使用する場合のクレームのプッシュ方法の詳細については、Permission API を参照してください。

ユーザー管理アクセス

Keycloak Authorization Services は、User-Managed Access (略して UMA) に基づいています。UMA は、OAuth2 の機能を以下の点で強化する仕様です。

  • プライバシー

    今日、ユーザーのプライバシーは、ますます多くのデータとデバイスが利用可能になり、クラウドに接続されるにつれて、大きな懸念事項となっています。UMA と Keycloak を使用することで、リソースサーバーは、ユーザーのプライバシーを尊重してリソースを保護する方法を改善するために、その機能を強化できます。ここでは、ユーザーによって定義されたポリシーに基づいて許可が付与されます。

  • パーティ間の認可

    リソースオーナー(例:一般のエンドユーザー)は、自分のリソースへのアクセスを管理し、他のパーティ(例:一般のエンドユーザー)がこれらのリソースにアクセスすることを認可できます。これは、ユーザーの代理として動作するクライアントアプリケーションに同意を与える OAuth2 とは異なり、UMA ではリソースオーナーは、完全に非同期的な方法で、他のユーザーへのアクセスを許可できます。

  • リソース共有

    リソースオーナーは、自分のリソースへの許可を管理し、特定のリソースに誰がどのようにアクセスできるかを決定できます。Keycloak は、リソースオーナーが自分のリソースを管理できる共有管理サービスとして機能できます。

Keycloak は、ほとんどの UMA 機能を提供する UMA 2.0 準拠の認可サーバーです。

例として、ユーザーのアリス(リソースオーナー)がインターネットバンキングサービス(リソースサーバー)を使用して自分の銀行口座(リソース)を管理しているとします。ある日、アリスは自分の銀行口座を会計専門家のボブ(リクエストパーティ)に公開することにしました。ただし、ボブはアリスの口座を閲覧(スコープ)するアクセス権のみを持つ必要があります。

リソースサーバーとして、インターネットバンキングサービスはアリスの銀行口座を保護できる必要があります。そのため、Keycloak リソース登録エンドポイントを利用して、アリスの銀行口座を表すリソースをサーバーに作成します。

現時点では、ボブがアリスの銀行口座にアクセスしようとすると、アクセスは拒否されます。インターネットバンキングサービスは、銀行口座に対していくつかのデフォルトポリシーを定義しています。そのうちの 1 つは、オーナー、この場合はアリスのみが自分の銀行口座にアクセスできることです。

ただし、インターネットバンキングサービスは、アリスのプライバシーを尊重して、銀行口座の特定のポリシーを変更することも許可しています。彼女が変更できるポリシーの 1 つは、自分の銀行口座を閲覧できる人を定義することです。そのため、インターネットバンキングサービスは Keycloak を利用して、アリスが個人と、それらの個人がアクセスできる操作(またはデータ)を選択できるスペースを提供します。アリスはいつでも、ボブへのアクセスを取り消したり、追加の許可を与えたりすることができます。

認可プロセス

UMA では、認可プロセスは、クライアントが UMA で保護されたリソースサーバーにアクセスしようとするときに開始されます。

UMA で保護されたリソースサーバーは、リクエストでベアラートークンを予期しており、そのトークンは RPT です。クライアントが RPT なしでリソースサーバーでリソースをリクエストすると

クライアントが RPT を送信せずに保護されたリソースをリクエストします
curl -X GET \
  http://${host}:${port}/my-resource-server/resource/1bfdfe78-a4e1-4c2d-b142-fc92b75b986f

リソースサーバーは、クライアントにパーミッションチケットと、RPT を取得するためにチケットを送信する必要がある Keycloak サーバーの場所を示す as_uri パラメータを含むレスポンスを返送します。

リソースサーバーがパーミッションチケットで応答します
HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="${realm-name}",
    as_uri="https://${host}:${port}/realms/${realm-name}",
    ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"

パーミッションチケットは、Keycloak Permission API によって発行される特別なタイプのトークンです。それらは、リクエストされている許可(例:リソースとスコープ)、およびリクエストに関連付けられたその他の情報を表します。リソースサーバーのみがこれらのトークンを作成できます。

クライアントは、パーミッションチケットと Keycloak サーバーの場所を取得したので、ディスカバリードキュメントを使用してトークンエンドポイントの場所を取得し、認可リクエストを送信できます。

クライアントが RPT を取得するためにトークンエンドポイントに認可リクエストを送信します
curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "ticket=${permission_ticket}

Keycloak 評価プロセスが許可の発行につながった場合、許可が関連付けられている RPT を発行します。

Keycloak はクライアントに RPT で応答します。
HTTP/1.1 200 OK
Content-Type: application/json
...
{
    "access_token": "${rpt}",
}

サーバーからのレスポンスは、他のグラントタイプを使用する場合のトークンエンドポイントからの他のレスポンスとまったく同じです。RPT は、access_token レスポンスパラメータから取得できます。クライアントが許可を持つ権限がない場合、Keycloak は 403 HTTP ステータスコードで応答します

Keycloak は認可リクエストを拒否します。
HTTP/1.1 403 Forbidden
Content-Type: application/json
...
{
    "error": "access_denied",
    "error_description": "request_denied"
}

パーミッションリクエストの送信

認可プロセスの一部として、クライアントは最初に UMA で保護されたリソースサーバーからパーミッションチケットを取得して、Keycloak トークンエンドポイントで RPT と交換する必要があります。

デフォルトでは、クライアントに RPT を発行できない場合、Keycloak は 403 HTTP ステータスコードと request_denied エラーで応答します。

Keycloak は認可リクエストを拒否します。
HTTP/1.1 403 Forbidden
Content-Type: application/json
...
{
    "error": "access_denied",
    "error_description": "request_denied"
}

このような応答は、Keycloak がパーミッションチケットによって表される許可で RPT を発行できなかったことを意味します。

状況によっては、クライアントアプリケーションは非同期認可フローを開始し、リクエストされているリソースのオーナーにアクセスを許可するかどうかを決定させたい場合があります。そのため、クライアントは submit_request リクエストパラメータを、トークンエンドポイントへの認可リクエストとともに使用できます。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token \
  -H "Authorization: Bearer ${access_token}" \
  --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket" \
  --data "ticket=${permission_ticket} \
  --data "submit_request=true"

submit_request パラメータを使用すると、Keycloak はアクセスが拒否された各リソースのパーミッションリクエストを永続化します。作成されると、リソースオーナーは自分のアカウントを確認し、パーミッションリクエストを管理できます。

この機能は、アプリケーションの アクセスリクエスト ボタンのように考えることができます。ユーザーは他のユーザーに自分のリソースへのアクセスを要求できます。

ユーザーリソースへのアクセスの管理

ユーザーは、Keycloak アカウントコンソールを使用して、自分のリソースへのアクセスを管理できます。この機能を有効にするには、まずレルムの User-Managed Access を有効にする必要があります。

手順
  1. 管理コンソールにログインします。

  2. メニューの レルム設定 をクリックします。

  3. User-Managed Accessオン に切り替えます。

  4. 管理コンソールの右上にあるユーザー名をクリックし、アカウントの管理 を選択します。

    My Resources

  5. メニューオプションの マイリソース をクリックします。次のオプションが表示されたページが表示されます。

    • マイリソース の管理

      このセクションには、ユーザーが所有するすべてのリソースのリストが含まれています。ユーザーは、リソースをクリックして詳細を確認し、リソースを他のユーザーと共有できます。許可リクエストが承認待ちの場合、リソースの名前の横にアイコンが表示されます。これらのリクエストは、特定のリソースへのアクセスをリクエストしているパーティ(ユーザー)に関連付けられています。ユーザーは、これらのリクエストを承認または拒否できます。アイコンをクリックして実行できます

      Resource Detail

    • 自分と共有されたリソース の管理

      このセクションには、ユーザーと共有されているすべてのリソースのリストが含まれています。

    • このリソースへのアクセス権を持つユーザー の管理

      このセクションには、このリソースへのアクセス権を持つユーザーのリストが含まれています。ユーザーは、取り消し ボタンをクリックするか、特定の 許可 を削除することでアクセスを取り消すことができます。

    • リソースを他のユーザーと共有する

      別のユーザーのユーザー名またはメールアドレスを入力することで、ユーザーはリソースを共有し、アクセスを許可する許可を選択できます。

Protection API

Protection API は、UMA 準拠のエンドポイントセットを提供します。

  • リソース管理

    このエンドポイントを使用すると、リソースサーバーはリソースをリモートで管理し、ポリシーエンフォーサー が保護が必要なリソースについてサーバーにクエリを実行できるようにすることができます。

  • パーミッション管理

    UMA プロトコルでは、リソースサーバーはこのエンドポイントにアクセスしてパーミッションチケットを作成します。Keycloak は、許可の状態を管理し、許可をクエリするエンドポイントも提供します。

  • Policy API

    Keycloak は、UMA Protection API を活用して、リソースサーバーがユーザーの許可を管理できるようにします。リソース API とパーミッション API に加えて、Keycloak は、リソースサーバーがユーザーに代わってリソースに許可を設定できる Policy API を提供します。

この API の重要な要件は、リソースサーバーのみ が、protection API トークン (PAT) と呼ばれる特別な OAuth2 アクセストークンを使用してそのエンドポイントにアクセスできることです。UMA では、PAT はスコープ uma_protection を持つトークンです。

PAT とその取得方法

protection API トークン (PAT) は、uma_protection として定義されたスコープを持つ特別な OAuth2 アクセストークンです。リソースサーバーを作成すると、Keycloak は対応するクライアントアプリケーションのロール、uma_protection を自動的に作成し、クライアントのサービスアカウントに関連付けます。

uma_protection ロールが付与されたサービスアカウント

Service Account granted with uma_protection role

リソースサーバーは、他の OAuth2 アクセストークンと同様に、Keycloak から PAT を取得できます。たとえば、curl を使用する場合

curl -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d 'grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}' \
    "http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token"

上記の例では、サーバーから PAT を取得するために client_credentials グラントタイプを使用しています。その結果、サーバーは次のようなレスポンスを返します。

{
  "access_token": ${PAT},
  "expires_in": 300,
  "refresh_expires_in": 1800,
  "refresh_token": ${refresh_token},
  "token_type": "bearer",
  "id_token": ${id_token},
  "not-before-policy": 0,
  "session_state": "ccea4a55-9aec-4024-b11c-44f6f168439e"
}
Keycloak は、さまざまな方法でクライアントアプリケーションを認証できます。簡単にするために、ここでは client_credentials グラントタイプを使用しています。これには、client_idclient_secret が必要です。サポートされている任意の認証方法を使用することを選択できます。

リソースの管理

リソースサーバーは、UMA 準拠のエンドポイントを使用してリソースをリモートで管理できます。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set

このエンドポイントは、次のように概説される操作を提供します(パス全体は明確にするために省略)。

  • リソースセット記述の作成:POST /resource_set

  • リソースセット記述の読み取り:GET /resource_set/{_id}

  • リソースセット記述の更新:PUT /resource_set/{_id}

  • リソースセット記述の削除:DELETE /resource_set/{_id}

  • リソースセット記述のリスト:GET /resource_set

これらの各操作の契約の詳細については、UMA リソース登録 API を参照してください。

リソースの作成

リソースを作成するには、次のように HTTP POST リクエストを送信する必要があります。

curl -v -X POST \
  http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '{
     "name":"Tweedl Social Service",
     "type":"http://www.example.com/rsrcs/socialstream/140-compatible",
     "icon_uri":"http://www.example.com/icons/sharesocial.png",
     "resource_scopes":[
         "read-public",
         "post-updates",
         "read-private",
         "http://www.example.com/scopes/all"
      ]
  }'

デフォルトでは、リソースのオーナーはリソースサーバーです。特定のユーザーなど、別のオーナーを定義する場合は、次のようにリクエストを送信できます。

curl -v -X POST \
  http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '{
     "name":"Alice Resource",
     "owner": "alice"
  }'

ここで、プロパティ owner は、ユーザーのユーザー名または識別子で設定できます。

ユーザー管理リソースの作成

デフォルトでは、Protection API 経由で作成されたリソースは、アカウントコンソール を介してリソースオーナーが管理することはできません。

リソースを作成し、リソースオーナーがこれらのリソースを管理できるようにするには、ownerManagedAccess プロパティを次のように設定する必要があります。

curl -v -X POST \
  http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '{
     "name":"Alice Resource",
     "owner": "alice",
     "ownerManagedAccess": true
  }'
リソースの更新

既存のリソースを更新するには、次のようにHTTP PUTリクエストを送信します。

curl -v -X PUT \
  http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set/{resource_id} \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '{
     "_id": "Alice Resource",
     "name":"Alice Resource",
     "resource_scopes": [
        "read"
     ]
  }'
リソースの削除

既存のリソースを削除するには、次のようにHTTP DELETEリクエストを送信します。

curl -v -X DELETE \
  http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set/{resource_id} \
  -H 'Authorization: Bearer '$pat
リソースのクエリ

idでリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set/{resource_id}

nameを指定してリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?name=Alice Resource

デフォルトでは、nameフィルターは、指定されたパターンに一致する任意のリソースにマッチングします。クエリを完全に一致するリソースのみを返すように制限するには、次を使用します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?name=Alice Resource&exactName=true

uriを指定してリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?uri=/api/alice

ownerを指定してリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?owner=alice

typeを指定してリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?type=albums

scopeを指定してリソースをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/resource_set?scope=read

サーバーにパーミッションをクエリするときは、結果を制限するためにパラメーターfirstmaxの結果を使用します。

パーミッションリクエストの管理

UMAプロトコルを使用するリソースサーバーは、特定のエンドポイントを使用してパーミッションリクエストを管理できます。このエンドポイントは、パーミッションリクエストを登録し、パーミッションチケットを取得するためのUMA準拠のフローを提供します。

http://${host}:${port}/realms/${realm-name}/authz/protection/permission

パーミッションチケットは、パーミッションリクエストを表す特別なセキュリティトークンタイプです。UMA仕様に従って、パーミッションチケットは

認可サーバーからリソースサーバーへ、リソースサーバーからクライアントへ、そして最終的にはクライアントから認可サーバーへと伝達される関連ハンドルであり、認可サーバーが認可データのリクエストに適用する適切なポリシーを評価できるようにします。

ほとんどの場合、このエンドポイントを直接扱う必要はありません。Keycloakは、リソースサーバーのUMAを有効にするポリシーエンフォーサーを提供し、認可サーバーからパーミッションチケットを取得し、このチケットをクライアントアプリケーションに返し、最終的なリクエスターパーティートークン(RPT)に基づいて認可決定を適用できるようにします。

Keycloakからパーミッションチケットを取得するプロセスは、リソースサーバーによって実行され、通常クライアントアプリケーションによって実行されません。パーミッションチケットは、クライアントがリソースにアクセスするための必要な許可なしに保護されたリソースにアクセスしようとすると取得されます。パーミッションチケットの発行は、UMAを使用する場合の重要な側面であり、リソースサーバーは次のことを可能にします。

  • リソースサーバーによって保護されたリソースに関連付けられたデータをクライアントから抽象化する

  • リソースの所有者の同意に基づいてアクセスを許可するために後でワークフローで使用できるKeycloak認可リクエストに登録する

  • リソースサーバーを認可サーバーから分離し、異なる認可サーバーを使用してリソースを保護および管理できるようにする

クライアント側では、パーミッションチケットには強調する価値のある重要な側面もあります。

  • クライアントは、認可データが保護されたリソースにどのように関連付けられているかを知る必要はありません。パーミッションチケットは、クライアントにとって完全に不透明です。

  • クライアントは、異なるリソースサーバー上のリソースにアクセスでき、異なる認可サーバーによって保護できます。

これらは、UMAの利点のほんの一部であり、UMAの他の側面は、特にプライバシーとユーザーが制御するリソースへのアクセスに関して、パーミッションチケットに強く基づいています。

パーミッションチケットの作成

パーミッションチケットを作成するには、次のようにHTTP POSTリクエストを送信します。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/authz/protection/permission \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '[
  {
    "resource_id": "{resource_id}",
    "resource_scopes": [
      "view"
    ]
  }
]'

チケットを作成するときに、任意のクレームをプッシュし、これらのクレームをチケットに関連付けることもできます。

curl -X POST \
  http://${host}:${port}/realms/${realm-name}/authz/protection/permission \
  -H 'Authorization: Bearer '$pat \
  -H 'Content-Type: application/json' \
  -d '[
  {
    "resource_id": "{resource_id}",
    "resource_scopes": [
      "view"
    ],
    "claims": {
        "organization": ["acme"]
    }
  }
]'

これらのクレームは、パーミッションチケットに関連付けられたリソースとスコープのパーミッションを評価するときに、ポリシーで利用可能になります。

その他の非UMA準拠エンドポイント
パーミッションチケットの作成

特定のリソース(id {resource_id})のパーミッションをユーザー(id {user_id})に付与するには、リソースのオーナーとして、次のようにHTTP POSTリクエストを送信します。

curl -X POST \
     http://${host}:${port}/realms/${realm-name}/authz/protection/permission/ticket \
     -H 'Authorization: Bearer '$access_token \
     -H 'Content-Type: application/json' \
     -d '{
       "resource": "{resource_id}",
       "requester": "{user_id}",
       "granted": true,
       "scopeName": "view"
     }'
パーミッションチケットの取得
curl http://${host}:${port}/realms/${realm-name}/authz/protection/permission/ticket \
     -H 'Authorization: Bearer '$access_token

これらのクエリパラメーターのいずれかを使用できます。

  • scopeId

  • resourceId

  • owner

  • requester

  • granted

  • returnNames

  • first

  • max

パーミッションチケットの更新
curl -X PUT \
     http://${host}:${port}/realms/${realm-name}/authz/protection/permission/ticket \
     -H 'Authorization: Bearer '$access_token \
     -H 'Content-Type: application/json' \
     -d '{
       "id": "{ticket_id}"
       "resource": "{resource_id}",
       "requester": "{user_id}",
       "granted": false,
       "scopeName": "view"
     }'
パーミッションチケットの削除
curl -X DELETE http://${host}:${port}/realms/${realm-name}/authz/protection/permission/ticket/{ticket_id} \
     -H 'Authorization: Bearer '$access_token

Policy APIを使用したリソースパーミッションの管理

Keycloak は、UMA Protection API を活用して、リソースサーバーがユーザーの許可を管理できるようにします。リソース API とパーミッション API に加えて、Keycloak は、リソースサーバーがユーザーに代わってリソースに許可を設定できる Policy API を提供します。

Policy APIは、次の場所にあります。

http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy/{resource_id}

このAPIは、ユーザーが自分の代わりにパーミッションを管理するためにリソースサーバーに付与した同意を表すベアラートークンによって保護されています。ベアラートークンは、トークンエンドポイントから取得した通常のアクセストークンにすることができます。

  • リソースオーナーパスワードクレデンシャルグラントタイプ

  • トークンエクスチェンジ。オーディエンスがリソースサーバーであるトークンに対して、(パブリッククライアント)クライアントに付与されたアクセストークンを交換するため。

リソースへのパーミッションの関連付け

特定のリソースにパーミッションを関連付けるには、次のようにHTTP POSTリクエストを送信する必要があります。

curl -X POST \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{resource_id} \
  -H 'Authorization: Bearer '$access_token \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "Any people manager",
        "description": "Allow access to any people manager",
        "scopes": ["read"],
        "roles": ["people-manager"]
}'

上記の例では、resource_idで表されるリソースに新しいパーミッションを作成して関連付けており、ロールpeople-managerを持つすべてのユーザーにreadスコープが付与されるはずです。

グループを使用するなど、他のアクセス制御メカニズムを使用してポリシーを作成することもできます。

curl -X POST \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{resource_id} \
  -H 'Authorization: Bearer '$access_token \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "Any people manager",
        "description": "Allow access to any people manager",
        "scopes": ["read"],
        "groups": ["/Managers/People Managers"]
}'

または特定のクライアント

curl -X POST \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{resource_id} \
  -H 'Authorization: Bearer '$access_token \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "Any people manager",
        "description": "Allow access to any people manager",
        "scopes": ["read"],
        "clients": ["my-client"]
}'

またはJavaScriptを使用したカスタムポリシーを使用することもできます。

curl -X POST \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{resource_id} \
  -H 'Authorization: Bearer '$access_token \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "Any people manager",
        "description": "Allow access to any people manager",
        "scopes": ["read"],
        "condition": "my-deployed-script.js"
}'

これらのアクセス制御メカニズムの任意の組み合わせを設定することも可能です。

既存のパーミッションを更新するには、次のようにHTTP PUTリクエストを送信します。

curl -X PUT \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{permission_id} \
  -H 'Authorization: Bearer '$access_token \
  -H 'Content-Type: application/json' \
  -d '{
    "id": "21eb3fed-02d7-4b5a-9102-29f3f09b6de2",
    "name": "Any people manager",
    "description": "Allow access to any people manager",
    "type": "uma",
    "scopes": [
        "album:view"
    ],
    "logic": "POSITIVE",
    "decisionStrategy": "UNANIMOUS",
    "owner": "7e22131a-aa57-4f5f-b1db-6e82babcd322",
    "roles": [
        "user"
    ]
}'
パーミッションの削除

リソースに関連付けられたパーミッションを削除するには、次のようにHTTP DELETEリクエストを送信します。

curl -X DELETE \
  https://#:8180/realms/photoz/authz/protection/uma-policy/{permission_id} \
  -H 'Authorization: Bearer '$access_token
パーミッションのクエリ

リソースに関連付けられたパーミッションをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy?resource={resource_id}

名前を指定してパーミッションをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy?name=Any people manager

特定のスコープに関連付けられたパーミッションをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy?scope=read

すべてのパーミッションをクエリするには、次のようにHTTP GETリクエストを送信します。

http://${host}:${port}/realms/${realm-name}/authz/protection/uma-policy

サーバーにパーミッションをクエリするときは、結果を制限するためにパラメーターfirstmaxの結果を使用します。

リクエスターパーティートークン

リクエスターパーティートークン(RPT)は、JSONウェブトークン(JWT)であり、JSONウェブ署名(JWS)を使用してデジタル署名されています。トークンは、以前にKeycloakによってユーザーまたは自身に代わって行動する特定のクライアントに発行されたOAuth2アクセストークンに基づいて構築されています。

RPTをデコードすると、次のようなペイロードが表示されます。

{
  "authorization": {
      "permissions": [
        {
          "resource_set_id": "d2fe9843-6462-4bfc-baba-b5787bb6e0e7",
          "resource_set_name": "Hello World Resource"
        }
      ]
  },
  "jti": "d6109a09-78fd-4998-bf89-95730dfd0892-1464906679405",
  "exp": 1464906971,
  "nbf": 0,
  "iat": 1464906671,
  "sub": "f1888f4d-5172-4359-be0c-af338505d86c",
  "typ": "kc_ett",
  "azp": "hello-world-authz-service"
}

このトークンから、サーバーによって付与されたすべてのパーミッションをpermissionsクレームから取得できます。

また、パーミッションは、保護しているリソース/スコープと直接関係があり、これらのパーミッションを実際に付与および発行するために使用されたアクセス制御方法とは完全に切り離されていることに注意してください。

リクエスターパーティートークンのイントロスペクション

リクエスターパーティートークン(RPT)をイントロスペクトして、その有効性を確認したり、トークン内のパーミッションを取得してリソースサーバー側で認可決定を適用したりすることが必要な場合があります。

トークンイントロスペクションが役立つ主なユースケースが2つあります。

  • クライアントアプリケーションがトークンの有効性をクエリして、同じまたは追加のパーミッションを持つ新しいトークンを取得する必要がある場合

  • 特に、組み込みのポリシーエンフォーサーがアプリケーションに適合しない場合に、リソースサーバー側で認可決定を適用する場合

RPTに関する情報の取得

トークンイントロスペクションは、基本的にOAuth2トークンイントロスペクション準拠のエンドポイントであり、ここからRPTに関する情報を取得できます。

http://${host}:${port}/realms/${realm-name}/protocol/openid-connect/token/introspect

このエンドポイントを使用してRPTをイントロスペクトするには、次のようにサーバーにリクエストを送信できます。

curl -X POST \
    -H "Authorization: Basic aGVsbG8td29ybGQtYXV0aHotc2VydmljZTpzZWNyZXQ=" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d 'token_type_hint=requesting_party_token&token=${RPT}' \
    "https://#:8080/realms/hello-world-authz/protocol/openid-connect/token/introspect"
上記のリクエストはHTTP BASICを使用しており、トークンをイントロスペクトしようとするクライアントを認証するためにクライアントのクレデンシャル(クライアントIDとシークレット)を渡していますが、Keycloakでサポートされている他のクライアント認証方法を使用することもできます。

イントロスペクションエンドポイントは、次の2つのパラメーターを想定しています。

  • token_type_hint

    このパラメーターの値としてrequesting_party_tokenを使用します。これは、RPTをイントロスペクトすることを意味します。

  • token

    認可プロセス中にサーバーから返されたトークン文字列を、このパラメーターの値として使用します。

結果として、サーバーの応答は次のようになります。

{
  "permissions": [
    {
      "resource_id": "90ccc6fc-b296-4cd1-881e-089e1ee15957",
      "resource_name": "Hello World Resource"
    }
  ],
  "exp": 1465314139,
  "nbf": 0,
  "iat": 1465313839,
  "aud": "hello-world-authz-service",
  "active": true
}

RPTがアクティブでない場合、代わりにこの応答が返されます。

{
  "active": false
}

RPTをイントロスペクトしたいときは毎回サーバーを呼び出す必要がありますか?

いいえ。Keycloakサーバーによって発行された通常のアクセストークンと同様に、RPTもデフォルト形式としてJSONウェブトークン(JWT)仕様を使用しています。

リモートイントロスペクションエンドポイントを呼び出さずにこれらのトークンを検証する場合は、RPTをデコードして、ローカルでその有効性をクエリできます。トークンをデコードすると、トークン内のパーミッションを使用して認可決定を適用することもできます。

これは基本的にポリシーエンフォーサーが行うことです。必ず次のことを行ってください。

  • RPTの署名を検証します(レルムの公開鍵に基づきます)。

  • expiat、およびaudクレームに基づいてトークンの有効性をクエリします。

ポリシーエンフォーサー

ポリシー執行ポイント(PEP)は設計パターンであり、さまざまな方法で実装できます。Keycloakは、さまざまなプラットフォーム、環境、およびプログラミング言語のPEPを実装するために必要なすべての手段を提供します。Keycloak Authorization Servicesは、RESTful APIを提供し、OAuth2認可機能を活用して、集中型認可サーバーを使用したきめ細かい認可を実現します。

Keycloakで利用可能なポリシーエンフォーサーは次のとおりです。

ポリシーエンフォーサーのJavaScript統合

Keycloakサーバーには、ポリシーエンフォーサーによって保護されたリソースサーバーと対話するために使用できるJavaScriptライブラリが付属しています。このライブラリは、Keycloak JavaScriptアダプターに基づいており、クライアントがKeycloakサーバーからパーミッションを取得できるように統合できます。

このライブラリは、NPMからインストールすることで取得できます。

npm install keycloak-js

次に、次のようにKeycloakAuthorizationインスタンスを作成できます。

import Keycloak from "keycloak-js";
import KeycloakAuthorization from "keycloak-js/authz";

const keycloak = new Keycloak({
    url: "http://keycloak-server",
    realm: "my-realm",
    clientId: "my-app"
});

const authorization = new KeycloakAuthorization(keycloak);

await keycloak.init();

// Now you can use the authorization object to interact with the server.

keycloak-js/authzライブラリは、主に次の2つの機能を提供します。

  • UMA保護されたリソースサーバーにアクセスしている場合は、パーミッションチケットを使用してサーバーからパーミッションを取得します。

  • アプリケーションがアクセスしたいリソースとスコープを送信して、サーバーからパーミッションを取得します。

どちらの場合も、このライブラリを使用すると、リソースサーバーとKeycloak Authorization Servicesの両方と簡単にやり取りして、クライアントがリソースサーバー上の保護されたリソースにアクセスするためのベアラートークンとして使用できるパーミッションを持つトークンを取得できます。

UMA保護されたリソースサーバーからの認可応答の処理

リソースサーバーがポリシーエンフォーサーによって保護されている場合、ベアラートークンと一緒に伝達されるパーミッションに基づいてクライアントリクエストに応答します。通常、保護されたリソースにアクセスするためのパーミッションが不足しているベアラートークンを使用してリソースサーバーにアクセスしようとすると、リソースサーバーは401ステータスコードとWWW-Authenticateヘッダーで応答します。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="${realm-name}",
    as_uri="https://${host}:${port}/realms/${realm-name}",
    ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"

詳細については、UMA認可プロセスを参照してください。

クライアントが行う必要があるのは、リソースサーバーから返される WWW-Authenticate ヘッダーからパーミッションチケットを抽出し、ライブラリを使用して次のように認可リクエストを送信することです。

// prepare a authorization request with the permission ticket
const authorizationRequest = { ticket };

// send the authorization request, if successful retry the request
authorization.authorize(authorizationRequest).then((rpt) => {
    // onGrant
}, () => {
    // onDeny
}, () => {
    // onError
});

authorize 関数は完全に非同期であり、サーバーからの通知を受信するためのいくつかのコールバック関数をサポートしています。

  • onGrant: 関数の最初の引数です。認可が成功し、サーバーが要求されたパーミッションを含む RPT を返す場合、コールバックは RPT を受信します。

  • onDeny: 関数の 2 番目の引数です。サーバーが認可リクエストを拒否した場合にのみ呼び出されます。

  • onError: 関数の 3 番目の引数です。サーバーが予期しない応答を返した場合にのみ呼び出されます。

ほとんどのアプリケーションは、401 応答後にリクエストを再試行するために onGrant コールバックを使用する必要があります。後続のリクエストには、再試行のためのベアラートークンとして RPT を含める必要があります。

エンタイトルメントの取得

keycloak-js/authz ライブラリは、クライアントがアクセスしたいリソースとスコープを提供することで、サーバーから RPT を取得するために使用できる entitlement 関数を提供します。

ユーザーがアクセスできるすべてのリソースとスコープに対するパーミッションを含む RPT を取得する方法の例
authorization.entitlement("my-resource-server-id").then((rpt) => {
    // onGrant callback function.
    // If authorization was successful you'll receive an RPT
    // with the necessary permissions to access the resource server
});
特定のリソースとスコープに対するパーミッションを含む RPT を取得する方法の例
authorization.entitlement("my-resource-server", {
    permissions: [
        {
            id: "Some Resource"
        }
    ]
}).then((rpt) => {
    // onGrant
});

entitlement 関数を使用する場合、アクセスしたいリソースサーバーの client_id を提供する必要があります。

entitlement 関数は完全に非同期であり、サーバーからの通知を受信するためのいくつかのコールバック関数をサポートしています。

  • onGrant: 関数の最初の引数です。認可が成功し、サーバーが要求されたパーミッションを含む RPT を返す場合、コールバックは RPT を受信します。

  • onDeny: 関数の 2 番目の引数です。サーバーが認可リクエストを拒否した場合にのみ呼び出されます。

  • onError: 関数の 3 番目の引数です。サーバーが予期しない応答を返した場合にのみ呼び出されます。

認可リクエスト

authorize 関数と entitlement 関数の両方が、認可リクエストオブジェクトを受け入れます。このオブジェクトには、次のプロパティを設定できます。

  • permissions

    リソースとスコープを表すオブジェクトの配列。例:

    const authorizationRequest = {
       permissions: [
           {
               id: "Some Resource",
               scopes: ["view", "edit"]
           }
       ]
    }
  • メタデータ

    そのプロパティが、認可リクエストがサーバーによってどのように処理されるべきかを定義するオブジェクト。

    • response_include_resource_name

      リソース名を RPT のパーミッションに含める必要があるかどうかをサーバーに示すブール値。false の場合、リソース識別子のみが含まれます。

    • response_permissions_limit

      RPT が持つことができるパーミッションの量を制限する整数 N。rpt パラメーターと一緒に使用すると、最後に要求された N 個のパーミッションのみが RPT に保持されます。

  • submit_request

    サーバーがパーミッションチケットによって参照されるリソースとスコープに対してパーミッションリクエストを作成する必要があるかどうかを示すブール値。このパラメーターは、UMA 認可プロセスの一部として ticket パラメーターと一緒に使用した場合にのみ有効になります。

RPT の取得

ライブラリによって提供される認可関数のいずれかを使用して RPT をすでに取得している場合は、認可オブジェクトから次のように RPT を常に取得できます (以前に示された手法のいずれかによって初期化されていると仮定します)。

const rpt = authorization.rpt;