認可サービスの概要
Keycloakはきめ細かい認可ポリシーをサポートし、以下のような異なるアクセス・コントロール機構を組み合わせることができます。
-
属性ベースのアクセス・コントロール(ABAC)
-
ロールベースのアクセス・コントロール(RBAC)
-
ユーザーベースのアクセス・コントロール(UBAC)
-
コンテキストベースのアクセス・コントロール(CBAC)
-
ルールベースのアクセス・コントロール
-
JavaScriptを使用
-
-
時間ベースのアクセス・コントロール
-
サービス・プロバイダー・インタフェース(SPI)によるカスタムACM(Access Control Mechanism)のサポート
Keycloakは、一連の管理UIとRESTful APIに基づいており、保護されるリソースとスコープのパーミッションを作成し、そのパーミッションを認可ポリシーに関連づけ、アプリケーションやサービスで認可判断を行うために必要な手段を提供します。
リソースサーバー(保護されたリソースを提供するアプリケーションまたはサービス)は、保護されたリソースへのアクセスを許可すべきかどうかを判定するために、何らかの情報を頼りにします。 RESTfulベースのリソースサーバーの場合、通常、その情報はセキュリティー・トークンから取得されます。そのトークンは、通常、リソースサーバーへのリクエストのたびにベアラートークンとして送信されます。ユーザーを認証するためにセッションに依存するWebアプリケーションの場合、通常、その情報はユーザーのセッションに格納され、リクエストのたびにそこから取得されます。
多くの場合、リソースサーバーはロールベースのアクセス・コントロール(RBAC)に基づいて認可判断のみを行います。ロールベースのアクセス・コントロールでは、保護されたリソースにアクセスしようとするユーザーに付与されたロールが、同リソースにマップされたロールに対してチェックされます。ロールは非常に有用で、アプリケーションにより使用されますが、以下のようないくつかの制限もあります。
-
リソースとロールは密結合されており、ロールへの変更(アクセス・コンテキストの追加、削除、変更など)は複数のリソースに影響を与える可能性があります。
-
セキュリティー要件の変更を反映するためには、アプリケーションのコードの大幅な変更が必要となる可能性があります。
-
アプリケーションのサイズによっては、ロール管理が困難になり、エラーを起こしやすくなる可能性があります。
-
これは最も柔軟なアクセス・コントロール機構ではありません。ロールは、誰であるかを表すものではなく、コンテキスト情報が欠けています。ロールが付与されているということは、少なくともいくらかのアクセス権を持っている、ということを表すだけです。
今日、ユーザーは異なるローカルポリシーの異なる地域におり、異なるデバイスを使用し、情報共有のニーズが高い異種環境を考慮する必要があります。Keycloak認可サービスは以下を提供し、アプリケーションやサービスの認可機能を向上させるのに役立つでしょう。
-
きめ細かい認可ポリシーと異なるアクセス・コントロール機構を使用したリソース保護
-
一元的なリソース、アクセス許可、およびポリシー管理
-
一元的なポリシー決定点
-
一連のRESTベースの認可サービスに基づくRESTセキュリティー
-
認可ワークフローとUser-Managed Access
-
プロジェクト間でのコードの複製(と再デプロイ)を防止し、セキュリティー要件の変更に迅速に対応するのに役立つ基盤
アーキテクチャー
設計の観点から、認可サービスは、明確に定義された認可パターンのセットに基づいて次の機能を提供します。
-
ポリシー管理ポイント(PAP)
リソースサーバー、リソース、スコープ、パーミッション、およびポリシーを管理するためのKeycloak管理コンソールに基づいたUIのセットを提供します。このうちの一部は、Protection APIを使用してリモートでも実現できます。
-
ポリシー決定点(PDP)
認可リクエストが送信され、リクエストが許可されることでポリシーが評価される場所に配布可能なポリシー決定点を提供します。詳細については、パーミッションの取得を参照してください。
-
ポリシー実施ポイント(PEP)
異なる環境に実装を提供し、リソースサーバー側で実際に認可の決定を実施します。Keycloakには、組み込みのポリシー・エンフォーサーが用意されています。
-
ポリシー情報ポイント(PIP)
Keycloak認証サーバーに基づいて、認可ポリシーの評価中にアイデンティティーとラインタイム環境から属性を取得できます。
認可プロセス
アプリケーションに対するきめ細かな認可を可能にするために、Keycloakの使用方法を理解する上で必要な手順を定義する3つの主要なプロセスは、以下のとおりです。
-
リソースの管理
-
パーミッションとポリシーの管理
-
ポリシーの実施
リソースの管理
リソースの管理 には、何が保護されているかを定義するために必要なすべてのステップが含まれます。
まず、保護しようとしているものをKeycloakに指定する必要があります。これは通常、Webアプリケーションまたは1つ以上のサービスのセットを表します。リソースサーバーの詳細については、用語集を参照してください。
リソースサーバーは、Keycloak管理コンソールを使用して管理されます。そこで、登録されたクライアント・アプリケーションをリソースサーバーとして有効にし、保護するリソースとスコープの管理を開始できます。
リソースには、Webページ、RESTFulリソース、ファイルシステム内のファイル、EJBなどがあります。それらは(JavaのClassのように)リソースのグループを表すことも、単一の具体的なリソースを表すこともできます。
たとえば、すべての銀行口座を表す Bank Account リソースがあり、それを使用してすべての銀行口座に共通する認可ポリシーを定義することができます。ただし、 Alice Account (ある顧客に属しているリソース・インスタンス)に対しては、オーナーだけが情報にアクセスしたり、操作を実行することができるように、特定のポリシーを定義することもできます。
リソースは、Keycloak管理コンソールまたはProtection APIを使用して管理できます。後者の場合、リソースサーバーはリソースをリモートで管理できます。
スコープは、通常、リソースに対して実行できるアクションを表しますが、これに限定されるものではありません。スコープを使用して、リソース内の1つ以上の属性を表すこともできます。
パーミッションとポリシーの管理
リソースサーバーと保護するすべてのリソースを定義したら、パーミッションとポリシーを設定する必要があります。
このプロセスには、リソースを管理するセキュリティーおよびアクセス要件を実際に定義するために必要なすべての手順が含まれます。
ポリシーは、何か(リソースまたはスコープ)へのアクセスや操作を実行するために満たす条件を定義しますが、保護しているものとは結びついていません。これらは一般的なもので、パーミッションやさらに複雑なポリシーを構築するために再利用することができます。
たとえば、ロール "User Premium" が付与されたユーザーに対してのみリソースのグループへのアクセスを許可するために、RBAC(ロールベースのアクセス・コントロール)を使用できます。
Keycloakには、最も一般的なアクセス・コントロール機構をカバーするいくつかの組み込みのポリシー・タイプ(およびそれぞれのポリシー・プロバイダー)が用意されています。JavaScriptを使用して作成されたルールに基づいてポリシーを作成することもできます。
ポリシーを定義したら、パーミッションの定義を開始できます。パーミッションは、保護しているリソースと結合されます。ここでは、保護する対象(リソースまたはスコープ)と、パーミッションを許可または拒否するために満たす必要のあるポリシーを指定します。
ポリシー実施
Policy Enforcement には、リソースサーバーへの認可の決定を実際に実施するために必要な手順が含まれます。これは、認可サーバーと通信できるリソースサーバーで Policy Enforcement Point またはPEPを有効にし、サーバーによって返された決定とパーミッションに基づいて認可データを要求し、保護されたリソースへのアクセスを制御することによって実現されます。
Keycloakには、実行中のプラットフォームに応じてアプリケーションを保護するために使用できる組み込みのポリシー・エンフォーサー実装がいくつか用意されています。
認可サービス
認可サービスは以下のRESTFulエンドポイントで構成されています。
-
トークン・エンドポイント
-
リソース管理エンドポイント
-
パーミッション管理エンドポイント
これらの各サービスは、認可プロセスに関わるさまざまなステップをカバーする特定のAPIを提供します。
トークン・エンドポイント
OAuth2クライアント(フロントエンド・アプリケーションなど)は、トークン・エンドポイントを使用してサーバーからアクセストークンを取得し、これらのトークンを使用してリソースサーバーによって保護されたリソース(バックエンド・サービスなど)にアクセスできます。同様に、Keycloak認可サービスは、要求されているリソースまたはスコープに関連するすべてのポリシーの処理に基づいてアクセストークンを発行できるように、OAuth2の拡張機能を提供します。つまり、リソースサーバーは、サーバーによって付与され、アクセストークンによって保持されているアクセス許可に基づいて、保護されたリソースへのアクセスを強制できます。Keycloak認可サービスでは、アクセス権を持つアクセストークンはリクエスティング・パーティー・トークンまたはRPTと呼ばれます。
Protection API
Protection API は UMA準拠 のエンドポイントのセットであり、リソースサーバーがリソース、スコープ、パーミッション、およびそれらに関連付けられたポリシーを管理する上で役立つ操作を提供します。リソースサーバーだけがこのAPIにアクセスできますが、 uma_protection スコープも必要です。
Protection APIによって提供される操作は、次の2つの主要なグループに分けられます。
-
リソースの管理
-
Create Resource
-
Delete Resource
-
Find by Id
-
Query
-
-
パーミッションの管理
-
パーミッション・チケットの発行
-
デフォルトでは、リモートリソース管理が有効になっています。Keycloak管理コンソールを使用して変更することができ、コンソールからのリソース管理のみを許可できます。 |
UMAプロトコルを使用する場合、Protection APIによるパーミッション・チケットの発行は、認可プロセス全体の重要な部分です。次のセクションで説明するように、これらはクライアントによって要求されたパーミッションを表し、要求されているリソースとスコープに関連付けられたパーミッションとポリシーの評価中に付与されたすべてのパーミッションを持つ最終的なトークンを取得するためにサーバーに送信されます。
用語
先に進む前に、Keycloak認可サービスで紹介されたこれらの用語と概念を理解することが重要です。
リソースサーバー
OAuth2の用語では、リソースサーバーは保護されたリソースをホスティングし、保護されたリソースへのリクエストを受け入れてレスポンスを返すことができるサーバーです。
通常、リソースサーバーは、保護されたリソースへのアクセスを許可するかどうかを決定するために、何らかの情報を頼りにします。 RESTfulベースのリソースサーバーの場合、大抵、その情報はセキュリティー・トークンに格納され、一般的に、サーバーへのすべてのリクエストと一緒にベアラートークンとして送信されます。セッションを利用してユーザーを認証するWebアプリケーションは、その情報をユーザーのセッションに格納し、リクエストごとにそこから取得します。
Keycloakでは、 confidential クライアント・アプリケーションはリソースサーバーとして動作できます。このクライアントのリソースとそれぞれのスコープは、一連の認可ポリシーによって保護、管理されます。
リソース
リソースは、アプリケーションと組織の資産の一部です。これは、1つ以上のエンドポイントのセット(HTMLページなどの古典的なWebリソースなど)です。認可ポリシーの用語では、リソースは保護される オブジェクト です。
すべてのリソースには、単一のリソースまたはリソースのセットを表すことができる一意の識別子があります。たとえば、すべての銀行口座に対して一連の認可ポリシーを表し定義する Banking Account Resource を管理することができます。ただし、 Alice’s Banking Account と呼ばれる別のリソースを持つこともできます。これは、単一の顧客が所有する単一のリソースを表し、独自の一連の認可ポリシーを持つことができます。
スコープ
リソースのスコープは、リソース上で実行可能な限定されたアクセスの範囲です。認可ポリシーの用語では、スコープは論理的にリソースに適用できる、潜在的に多くの 動詞 の1つです。
通常は、特定のリソースで何ができるかを示します。スコープの例としては、表示、編集、削除などです。ただし、リソースによって提供される特定の情報に関連付けることもできます。この場合、プロジェクト・リソースとコスト・スコープを持つことができます。コスト・スコープは、ユーザーがプロジェクトのコストにアクセスするための特定のポリシーとパーミッションを定義するために使用されます。
Permission
シンプルでとても一般的なパーミッションを考えてみましょう。
パーミッションは、保護されるオブジェクトと、アクセスが許可されるかどうかを判断するために評価されなければならないポリシーとを関連付けます。
-
X CAN DO Y ON RESOURCE Z
-
ここでは、以下を意味します。
-
X は、1つ以上のユーザー、ロール、またはグループ、またはそれらの組み合わせを表します。クレームとコンテキストを使うこともできます。
-
Y は、実行するアクション(書き込み、表示など)を表します。
-
Z は、"/accounts"などの保護されたリソースを表します。
-
-
Keycloakは、単純なルールから非常に複雑なルールベースの動的なパーミッションまで、幅広いパーミッション戦略を構築するための豊富なプラットフォームを提供します。柔軟性を提供し、次のことに役立ちます。
-
コードのリファクタリングとパーミッション管理のコストを削減
-
より柔軟なセキュリティー・モデルをサポートし、セキュリティー要件の変更に容易に対応できます
-
実行時に変更を加えます。アプリケーションは、保護されているリソースとスコープについてのみに考慮し、それらがどのように保護されるかについては考慮しません。
Policy
ポリシーは、オブジェクトへのアクセスを許可するために必要な条件を定義します。パーミッションとは異なり、保護されるオブジェクトを指定するのではなく、特定のオブジェクト(リソース、スコープ、またはその両方)へのアクセスを満たす条件を指定します。ポリシーは、リソースを保護するために使用できるさまざまなアクセス・コントロール・メカニズム(ACM)に強く関連しています。ポリシーを使用すると、属性ベースのアクセス・コントロール(ABAC)、ロールベースのアクセス・コントロール(RBAC)、コンテキストベースのアクセス・コントロール、またはこれらの任意の組み合わせのための戦略を実装できます。
Keycloakは、"ポリシーのポリシー"を構築して評価の動作を制御できる集約されたポリシーの概念を提供することによって、ポリシーの概念とその定義方法を活用します。特定のリソースへのアクセスを満たすすべての条件を含んだ1つの大きなポリシーを書くのではなく、Keycloak認可サービスのポリシー実装は分割統治のテクニックに従います。つまり、個々のポリシーを作成し、異なる権限でそれらを再利用し、個々のポリシーを組み合わせてより複雑なポリシーを構築することができます。
ポリシー・プロバイダー
ポリシー・プロバイダーは、特定のポリシー・タイプの実装です。Keycloakには、対応するポリシー・プロバイダーに基づいた組み込みのポリシーが用意されており、独自のポリシー・タイプを作成して特定の要件をサポートすることができます。
Keycloakには、独自のポリシー・プロバイダー実装をプラグイン化するために使用できるSPI(サービス・プロバイダー・インターフェイス)が用意されています。
パーミッション・チケット
パーミッション・チケットは、UMA(User-Managed Access)仕様で定義された特別なタイプのトークンで、その形式が認可サーバーによって決定されるOpaque構造体を提供します。この構造体は、クライアントによって要求されているリソースおよび/またはスコープ、アクセス・コンテキスト、および認可データ(リクエスティング・パーティ・トークン[RPT]を要求する)に適用する必要のあるポリシーを表します。
UMAでは、個人対個人の共有や個人対組織の共有をサポートするためにパーミッション・チケットが重要です。承認ワークフローにパーミッション・チケットを使用すると、単純なものから複雑なものまでさまざまなシナリオが可能になります。リソースオーナーとリソースサーバーは、これらのリソースへのアクセスを管理するきめ細かいポリシーに基づいてリソースを完全に制御できます。
UMAのワークフローでは、パーミッション・チケットは認可サーバーによってリソースサーバーに発行されます。リソースサーバーは、保護されたリソースにアクセスしようとするクライアントにパーミッション・チケットを返します。クライアントは、チケットを受信すると、チケットを認可サーバーに送り返すことによって、RPT(認可データを保持する最後のトークン)を要求することができます。
パーミッション・チケットの詳細については、User-Managed Accessおよび UMA の仕様を参照してください。
Getting Started
このチュートリアルを始める前に、Keycloakのインストールを完了し、Getting Started Guideのチュートリアルに沿って初期管理者ユーザーを作成する必要があります。これには注意事項があります。Keycloakサーバーと同じマシンで、別途WildFlyインスタンスを起動する必要があります。この別インスタンスではJavaサーブレットのアプリケーションを起動します。そのため、同じマシンで起動させる際にポートが競合しないように、異なるポートでKeycloakを起動する必要があります。コマンドラインで jboss.socket.binding.port-offset
システム・プロパティーを使います。当プロパティーの値は、Keycloakサーバーで開いた全ポートの基準値に加算される数値です。
Keycloakサーバーを起動するには下記を実行します。
$ .../bin/kc.sh start-dev --http-port 8180
> ...\bin\kc.bat start-dev --http-port 8180
インストールと両サーバーの起動後、Keycloak管理コンソールは http://localhost:8180/auth/admin/ 、WildFlyインスタンスは http://localhost:8080 でアクセス可能となります。
-
WildFlyインスタンスのインストールと設定の詳細については、 Securing Applications and Services Guide を参照してください。
サーブレット・アプリケーションのセキュリティー保護
このgetting startedガイドの目的はできるだけ短時間でKeycloakのさまざまな認可機能を試すことができるようにすることです。本書はデフォルトのデータベースとサーバー設定に大きく依存したクイックツアーとなっています。複雑な配備オプションは本書の範囲外です。機能と設定の詳細については本書の適切な章を参照してください。
本ガイドはKeycloak認可サービスについての重要な概念を説明します。
-
クライアント・アプリケーションに対するきめ細かい認可の有効化
-
保護されたリソースをもつリソースサーバーとしてのクライアント・アプリケーションの設定
-
保護されたリソースへのアクセスを統括するためのパーミッションと認可ポリシーの定義
-
アプリケーションのポリシー実行の有効化
レルムとユーザーの作成
このチュートリアルの最初のステップは、レルムとそのレルム内にユーザーを作成することです。次に、レルム内で、単一のクライアント・アプリケーションを作成します。このアプリケーションは、認可サービスを有効にする必要があるリソースサーバーになります。
-
hello-world-authz という名前のレルムを作成します。作成されると、次のようなページが表示されます。
hello-world-authzレルム -
Users をクリックします。
ユーザー一覧ページが表示され、ユーザーを作成することができます。
-
Create user をクリックします。
-
Username 、 Email 、 First Name 、 Last Name の各項目を入力してください。
-
User Enabled を ON にします。
-
Create をクリックします。
Add User -
Credentials タブをクリックして、ユーザーのパスワードを設定します。
ユーザーのパスワード設定 -
New Password と Password Confirmation フィールドにパスワードを入力し、 Temporary を OFF に切り替えます。
-
Save をクリックします。
-
Save password をクリックします。
認可サービスの有効化
OpenID Connectプロトコルを使用するように設定された既存のクライアント・アプリケーションで、認可サービスを有効にすることができます。以下の手順でクライアントを作成することもできます。
-
メニューの Clients をクリックします。
-
Client type を入力します。
-
Next をクリックします。
-
Client authentication を ON に切り替えます。
-
Authorization を ON に切り替えます。
-
Save をクリックします。
-
Capability config のセクションまでスクロールダウンしてください。
-
Root URL フィールドに入力します。
-
Save をクリックします。
クライアント・アプリケーションの作成クライアントのための新しい Authorization タブが表示されます。
クライアントの設定 -
Authorization タブをクリックします。
以下のような認可の設定ページが表示されます。
認可の設定
クライアント・アプリケーションに対して認可サービスを有効にすると、Keycloakは自動的にクライアント認可設定のデフォルト設定をいくつか作成します。
アプリケーションのビルド、デプロイ、およびテスト
app-authz-vanilla リソースサーバー(またはクライアント)が正しく設定され、認可サービスが有効になったので、サーバーにデプロイすることができます。
デプロイするアプリケーションのプロジェクトとコードは、Keycloak Quickstarts Repositoryから入手できます。続行するには、マシンに以下をインストールし、PATHを通す必要があります。
-
Java JDK 8
-
Apache Maven 3.1.1以上
-
Git
https://github.com/keycloak/keycloak-quickstarts のリポジトリーをクローンして、コードを入手することができます。このクイックスタートはKeycloakの最新リリースで動作するように設計されています。
コードをダウンロードするには、次の手順に従います。
$ git clone https://github.com/keycloak/keycloak-quickstarts
ビルドおよびデプロイをするアプリケーションは次の場所にあります
$ cd keycloak-quickstarts/app-authz-jee-vanilla
アダプターの設定を取得
アプリケーションをビルドおよびデプロイする前に、まずアダプターの設定を取得する必要があります。
-
管理コンソールにログインします。
-
メニューの Clients をクリックします。
-
クライアント一覧で、 app-authz-vanilla クライアント・アプリケーションをクリックします。クライアントの設定ページが表示されます。
クライアントの設定 -
Action の一覧から、 Download adapter config を選択します。
-
Format Optionの一覧から、 Keycloak OIDC JSON を選択します。
アダプターの設定は、JSON形式で表示されます。
-
Download をクリックします。
アダプターの設定 -
keycloak.json
ファイルをapp-authz-jee-vanilla/config
ディレクトリーに移動します。 -
オプションで、リダイレクトURLを指定します。
デフォルトでは、ポリシー・エンフォーサーは、ユーザーがリソースサーバー上の保護されたリソースにアクセスする許可がない場合に、
403
ステータスコードで応答します。ただし、権限のないユーザーに対して、リダイレクトURLを指定することもできます。リダイレクトURLを指定するには、更新した keycloak.json ファイルを編集し、policy-enforcer
の設定を次のものに置き換えます。"policy-enforcer": { "on-deny-redirect-to" : "/app-authz-vanilla/error.jsp" }
この変更は、保護されたリソースにアクセスするための必要な権限を持っていない場合に、ポリシー・エンフォーサーに対して、ユーザーを
/app-authz-vanilla/error.jsp
ページにリダイレクトするよう指定します(役に立たない403 Unauthorized
メッセージを返すのではなく)。
アプリケーションのビルドとデプロイ
アプリケーションをビルドしてデプロイするには、次のコマンドを実行します。
$ cd keycloak-quickstarts/app-authz-jee-vanilla
$ mvn clean package wildfly:deploy
アプリケーションのテスト
アプリケーションが正常にデプロイされた場合は、 http://localhost:8080/app-authz-vanilla でアクセスできます。Keycloakログインページが開きます。
-
そのユーザーに指定したパスワードを使用して、 alice としてログインします。以下のページが表示されます。
Hello World Authzのメインページクライアント・アプリケーションの認可サービスを有効にしたときに、Keycloakで定義されたデフォルト設定は、このポリシーで保護されているリソースへのアクセスを常に許可する単純なポリシーを提供します。
まず、デフォルトのアクセス許可とポリシーを変更し、アプリケーションの応答方法をテストするか、Keycloakが提供するさまざまなポリシータイプを使用して新しいポリシーを作成します。
このアプリケーションをテストするために、今できることがたくさんあります。たとえば、クライアントの Authorization
タブをクリックし、次に Policies
タブのクライアント、そしてリストの中の Default Policy
をクリックすれば、デフォルトのポリシーを変更することができます。次に、このページのドロップダウン・リストを使用して、 Logic
を Negative
に変更します。
-
デモ・アプリケーションからログアウトして、再度ログインしてください。
アプリケーションにアクセスできなくなります。
次のステップ
追加で次のようなことができます。
-
スコープを作成し、ポリシーとアクセス許可を定義し、アプリケーション側でテストします。ユーザーがアクション(または作成したスコープで表されるもの)を実行できるでしょうか?
-
さまざまな種類のポリシーを作成し、これらのポリシーと
Default Permission
を関連付けます。 -
複数のポリシーを
Default Permission
に適用し、動作をテストします。 たとえば、複数のポリシーを組み合わせて、それに応じてDecision Strategy
を変更します。
-
アプリケーション内でパーミッションを表示およびテストする方法の詳細については、認可コンテキストの取得を参照してください。
認可のクイックスタート
前のセクションでサンプル・アプリケーションとして使用されていた app-authz-jee-vanilla クイックスタートに加えて、Keycloak Quickstarts Repositoryには、このドキュメントに記載されている認可サービスを利用する他のアプリケーションが含まれています。
認可クイックスタートは、認可サービスがさまざまなシナリオで機能し、さまざまなテクノロジーと統合を使用するように設計されています。認可を含むすべての可能なユースケースの包括的なセットではありませんが、認可サービスをどのようにして自分のアプリケーションで使用できるかを理解することに関心のあるユーザーにとっては、出発点となります。
各クイックスタートには、サンプル・アプリケーションのビルド、デプロイ、テストの方法に関する説明を含む README
ファイルがあります。次の表に、使用可能な認可クイックスタートの簡単な説明を示します。
名前 | 説明 |
---|---|
特定のリソースを保護し、Keycloakサーバーから取得したパーミッションに基づいて動的メニューを構築するために、Jakarta EEアプリケーションに対するきめ細かい認可を有効にする方法を示します。 |
|
Jakarta EEアプリケーションに対するきめ細かな認可を有効にし、デフォルトの認可設定を使用してアプリケーション内のすべてのリソースを保護する方法を示します。 |
|
Keycloak認可サービスを使用してSpring Boot RESTサービスを保護する方法を示します。 |
|
Keycloakによって認証および認可の両方の側面が管理されるSpring Boot Webアプリケーションの作成方法を示します。 |
|
HTML5+AngularJS+JAX-RSに基づくシンプルなアプリケーションで、アプリケーションへのUser-Managed Accessを有効にし、ユーザーにリソースのパーミッションを管理させる方法を示します。 |
リソースサーバーの管理
OAuth2の仕様によれば、リソースサーバーは保護されたリソースをホストし、保護されたリソースへのリクエストを受け入れて応答することができるサーバーです。
Keycloakでは、リソースサーバーに保護されたリソースに対してきめ細かい認可を与えるための豊富なプラットフォームが用意されており、異なるアクセス制御の仕組みに基いた認可決定を行うことができます。
どのクライアント・アプリケーションも、きめ細かいパーミッションをサポートするように設定できます。そうすることで、概念的にクライアント・アプリケーションをリソースサーバーに変えています。
クライアント・アプリケーションの作成
Keycloak認可サービスを有効にするための最初の手順は、リソースサーバーにするクライアント・アプリケーションを作成することです。
-
Clients をクリックします。
Clients -
このページで、 Create client をクリックします。
Add Client -
クライアントの
Client ID
を入力します。たとえば、 my-resource-server 。 -
Next をクリックします。
-
Client authentication をONに切り替えます。
-
Save をクリックします。
-
アプリケーションの
Root URL
を入力します。たとえばhttp://${host}:${port}/my-resource-server
-
Save をクリックします。クライアントが作成され、クライアントの設定ページが開きます。次のようなページが表示されます。
クライアントの設定
認可サービスの有効化
OIDCクライアントをリソースサーバーにし、きめ細かな認可を有効にすることができます。
-
Authorization Enabled を On に切り替えます。
-
Save をクリックします。
認可サービスの有効化クライアントに新しいAuthorizationタブが表示されます。 Authorization タブをクリックすると、次のようなページが表示されます。
リソースサーバーの設定
Authorizationタブには、アプリケーションのリソースを実際に保護するために従わなければならないさまざまなステップを補う追加のサブタブが含まれています。各タブは、このドキュメントの特定のトピックで個別に解説されています。ここではそれぞれについて簡単に説明します。
-
Settings
リソースサーバーの一般設定。このページの詳細については、リソースサーバーの設定のセクションを参照してください。
-
Resource
このページから、アプリケーションのリソースを管理できます。
-
Authorization Scopes
このページから、スコープを管理できます。
-
Policies
このページから、認可ポリシーを管理し、許可を得るために必要な条件を定義することができます。
-
Permissions
このページから、保護されたリソースとスコープのパーミッションを、作成したポリシーとリンクさせることにより管理できます。
-
Evaluate
このページでは、認可リクエストのシミュレート、および定義したパーミッションと認可ポリシーの評価結果を表示できます。
-
Export Settings
このページから、認可設定をJSONファイルにエクスポートできます。
リソースサーバーの設定
リソースサーバー設定ページでは、ポリシーの強制モードの設定や、リモートリソース管理の許可、認可構成の設定のエクスポートができます。
-
Policy Enforcement Mode
サーバーに送信された認可要求を処理するときに、ポリシーがどのように強制されるかを指定します。
-
Enforcing
(デフォルトモード)特定のリソースに関連付けられたポリシーがない場合でも、デフォルトでリクエストは拒否されます。
-
Permissive
特定のリソースに関連付けられたポリシーがない場合でも、リクエストは許可されます。
-
Disabled
すべてのポリシーの評価を無効にし、すべてのリソースへのアクセスを許可します。
-
-
Decision Strategy
この設定により、評価されたすべてのパーミッションの結果に基づいて、ポリシー評価エンジンがリソースまたはスコープを許可するかどうか決定する方法が変更されます。
Affirmative
とは、リソースとそのスコープへのアクセスを許可するために、少なくとも1つのパーミッションが肯定的な決定に評価される必要があることを意味します。Unanimous
とは、最終決定も肯定的であるために、すべてのパーミッションが肯定的決定に評価されなければならないことを意味します。たとえば、同じリソースまたはスコープの2つのパーミッションが競合している場合(一方がアクセスを許可し、もう一方がアクセスを拒否している場合)、選択された戦略がAffirmative
であれば、リソースまたはスコープへのパーミッションが許可されます。そうでなければ、パーミッションからの単一の拒否は、リソースまたはスコープへのアクセスも拒否します。 -
Remote Resource Management
リソースサーバーによってリソースをリモート管理できるかどうかを指定します。falseの場合、リソースは管理コンソールからのみ管理できます。
デフォルト設定
リソースサーバーを作成すると、Keycloakは新しく作成したリソースサーバーのデフォルト設定を作成します。
デフォルト設定は次のとおりです。
-
アプリケーションのすべてのリソースを表すデフォルトの保護されたリソース。
-
このポリシーで保護されているリソースへのアクセスを常に許可するポリシー。
-
デフォルトのポリシーに基づいてすべてのリソースへのアクセスを管理するパーミッション。
デフォルトの保護されたリソースは default resource と呼ばれ、 Resources タブに移動すると表示できます。
このリソースは、 Type
を urn:my-resource-server:resources:default
という名前で、 URI
を /*
で定義します。ここで、URIフィールドは、このリソースがアプリケーションのすべてのパスを表すことをKeycloakに示すワイルドカード・パターンで定義します。つまり、アプリケーションのポリシー適用を有効にすると、アクセス権を付与する前に、リソースに関連付けられているすべてのパーミッションが検査されます。
前述の Type
は、デフォルトのリソースまたは同じタイプを使用して作成したリソースに適用させるタイプ付きリソース・パーミッションを作成するために使用できる値を定義します。
デフォルトのポリシーは、 only from realm policy と呼ばれ、 Policies タブに移動すると表示できます。
このポリシーはJavaScriptベースのポリシーで、このポリシーによって保護されているリソースへのアクセスを常に許可する条件を定義しています。このポリシーをクリックすると、次のようにルールが定義されていることが分かります。
// デフォルトでは、このポリシーに関連する全てのパーミッションを付与します。
$evaluation.grant();
最後に、デフォルトのパーミッションは、 default permission と呼ばれ、 Permissions タブに移動すると表示できます。
このパーミッションはリソースベースのパーミッションで、特定のタイプのすべてのリソースに適用される1つ以上のポリシーのセットを定義します。
デフォルト設定の変更
デフォルトの設定を変更するには、デフォルトのリソース、ポリシー、またはパーミッションの定義を削除し、独自の定義を作成します。
デフォルトのリソースは、 /* パターンを使用してアプリケーション内の任意のリソースまたはパスにマップされる URI で作成されます。独自のリソース、パーミッション、ポリシーを作成する前に、デフォルト設定が自分の設定と競合しないことを確認してください。
デフォルト設定では、アプリケーションのすべてのパスに対応するリソースを定義します。独自のリソースにパーミッションを書き込もうとしている場合は、 Default Resource を削除するか、 フィールドをアプリケーション内の特定のパスに変更してください。それ以外の場合は、デフォルト・リソース(デフォルトでは常にアクセスを許可する)に関連付けられたポリシーにより、Keycloakは保護されたリソースへのアクセスを許可します。
|
認可設定のエクスポートおよびインポート
リソースサーバー(またはクライアント)の構成設定をエクスポートおよびダウンロードできます。また、リソースサーバーの既存の設定ファイルをインポートすることもできます。設定ファイルのインポートとエクスポートは、リソースサーバーの初期設定を作成したり、既存の設定を更新する場合に役立ちます。設定ファイルには次の定義が含まれています。
-
保護されたリソースとスコープ
-
ポリシー
-
パーミッション
リソースとスコープの管理
リソース管理は簡単かつ一般的です。リソースサーバーを作成したら、保護するリソースとスコープの作成を開始できます。リソースおよびスコープは、 Resource タブおよび Authorization Scopes タブにそれぞれナビゲートすることで管理できます。
リソースの表示
Resource ページには、リソースサーバーに関連付けられているリソースの一覧が表示されます。
リソースリストには、次のような保護されたリソースに関する情報が表示されます。
-
Type
-
URI
-
オーナー
-
関連するスコープ(存在する場合)
-
関連するパーミッション
このリストから、パーミッションを作成したいリソースの Create Permission をクリックして、パーミッションを直接作成することもできます。
リソースに対するパーミッションを作成する前に、そのパーミッションに関連付けたいポリシーが定義済みであることを確認してください。 |
リソースの作成
リソースの作成は簡単で一般的です。主な関心事は、作成するリソースの粒度です。言い換えれば、1つ以上のリソースのセットを作成することができ、それらを定義する方法はパーミッションを管理するために重要なことです。
新しいリソースを作成するには、 Create resource をクリックします。
Keycloakでは、リソースは、次のようなさまざまなタイプのリソースに共通する細かい情報のセットを定義します。
-
Name
このリソースを説明する、人間が読める形式で一意な文字列。
-
Type
1つ以上のリソースのセットのタイプを一意に識別する文字列。タイプは、異なるリソース・インスタンスをグループ化するために使用される string です。たとえば、自動的に作成されるデフォルト・リソースのデフォルトのタイプは、
urn:resource-server-name:resources:default
です。
-
URIS
リソースのロケーション/アドレスを提供するURI。HTTPリソースの場合、URIは通常、これらのリソースを提供するために使用される相対パスです。
-
Scopes
リソースに関連付ける1つ以上のスコープ。
リソース属性
リソースには属性が関連付けられている場合があります。これらの属性を使用すると、リソースに関する追加情報を提供したり、リソースに関連付けられているアクセス許可を評価するときにポリシーに追加情報を提供できます。
各属性はキーと値のペアで、値は1つ以上の文字列のセットになります。属性に複数の値を定義するには、各値をカンマで区切ります。
リソースオーナー
リソースにはオーナーがいます。デフォルトでは、リソースはリソースサーバーによって所有されています。
ただし、リソースはユーザーと関連付けることもできるため、リソースオーナーに基づいてパーミッションを作成できます。たとえば、リソースオーナーだけが特定のリソースを削除または更新することができます。
リモートでリソースを管理する
リソース管理は、Protection APIを介しても公開され、リソースサーバーがリソースをリモートで管理できます。
Protection APIを使用すると、リソースサーバーを実装して、ユーザーが所有するリソースを管理できます。この場合、リソースを特定のユーザーに属するものとして設定するためのユーザー識別子を指定できます。
Keycloakは、リソースサーバーがリソースを完全に制御できるようにします。将来的には、特にUMAプロトコルを使用している場合に、ユーザーが自分のリソースを制御したり、認可リクエストを承認したり、パーミッションを管理できるようにする必要があります。 |
ポリシーの管理
前の章で述べたように、ポリシーはオブジェクトへのアクセスを与えられる前に満たすべき条件を定義します。
-
リソースサーバーに関連するすべてのポリシーを表示するには、 Policy タブをクリックします。
ポリシーこのタブでは、ポリシーの閲覧、作成、変更を行うことができます。
新しいポリシーを作成するには、 Create policy をクリックし、一覧からポリシーの種類を選択します。
各ポリシーの種類についての詳細は、このセクションで説明します。
ユーザーベース・ポリシー
1人以上のユーザーの集合がオブジェクトへのアクセスを許可されるパーミッションの条件を定義するために、このタイプのポリシーを使用することができます。
新しいユーザーベースのポリシーを作成するには、ポリシー一覧の右上にある項目リストで User を選択します。
ロールベース・ポリシー
1つ以上のロールの集合がオブジェクトへのアクセスを許可されるパーミッションの条件を定義するために、このタイプのポリシーを使用することができます。
デフォルトでは、このポリシーに追加されたロールは、Requiredとして指定されず、アクセスを要求するユーザーにこれらのロールのいずれかが付与されている場合に、ポリシーはアクセスを許可します。ただし、特定のロールを強制したい場合は、Requiredとして特定のロールを指定できます。レルムまたはクライアントのロールにかかわらず、RequiredのロールとRequiredではないロールを組み合わせることもできます。
ロールのポリシーは、オブジェクトへのアクセスを許可するのに特定のロールを強制する必要がある、より限定されたロールベースのアクセス・コントロール(RBAC)が必要な場合に役立ちます。たとえば、(ユーザーの代理として動作している)クライアント・アプリケーションがユーザーのリソースにアクセスできるようにするために、ユーザーの同意が必要であることを強制するようにできます。Keycloakクライアント・スコープ・マッピングを使用して同意ページを有効にしたり、Keycloakサーバーからアクセス・トークンを取得するときに明示的にスコープを指定したりすることもできます。
新しいロールベースのポリシーを作成するには、ポリシータイプの一覧から Role を選択します。
設定
-
Name
ポリシーを説明する、人が判読可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別することができます。
-
説明
このポリシーに関する詳細情報を含む文字列。
-
Realm Roles
このポリシーによって、どの realm ロールが許可されるかを指定します。
-
Client Roles
このポリシーで許可される client ロールを指定します。このフィールドを有効にするには、最初に
Client
を選択する必要があります。 -
Logic
他の条件が評価された後に適用するロジックです。
ロールを必須として定義する
ロールベース・ポリシーを定義するとき、特定のロールを Required
と指定することができます。こうすることで、 全て の 必須 ロールを付与されたユーザーにのみアクセス権を与えることができます。レルムロールとクライアントロールの両方にこの設定を適用することができます。
ロールを必須と指定するには、そのロールの Required
チェックボックスをチェックします。
複数のロールがポリシーに定義されており、そのうちのいくつかが必須の場合にこの機能は有用です。より細かいロールベース・アクセス・コントロール(RBAC)のためにレルムロールとクライアントロールを組み合わせることが可能です。たとえば、あるクライアントに適用されるポリシーがある場合、そのクライアントに関連付けられた特定のクライアントロールを必須とすることができます。また、特定のレルムロールを持つ場合のみアクセスを許可することもできます。1つのポリシーに両方のアプローチを適用することもできます。
JavaScriptベースポリシー
以下の例のように、ポリシーの実装で属性ベースのアクセス・コントロール(ABAC)を使用している場合は、ユーザーが保護された属性を編集できず、対応する属性が読み取り専用であることを確認してください。詳細については 脅威モデルの緩和の章 を参照してください。 |
このポリシーは、JavaScriptを使用可能にする条件を定義するために使うことができます。これはKeycloakによってサポートされるルール・ベースのポリシータイプの1つであり、Evaluation APIに基づいて任意のポリシーを柔軟に作成できます。
新しいJavaScriptベースポリシーを作成するには、ポリシーリストの右上隅にある項目のリストから JavaScript を選択します。
デフォルトでは、JavaScript ポリシーをサーバーにアップロードすることはできません。 JavaScript Providersで説明されているように、JavaScript ポリシーをサーバーに直接デプロイすることを推奨します。 |
デプロイされたJARファイルから取得したJSポリシーの作成
Keycloakを使用すると、JARファイルをデプロイして、サーバーにスクリプトをデプロイできます。詳細については、JavaScript Providersを参照してください。
スクリプトをデプロイしたら、利用可能なポリシー・プロバイダーのリストからデプロイしたスクリプトを選択できるようになります。
サンプル
評価コンテキストから取得した属性のチェック
コンテキストから取得した属性で条件を定義するために、属性ベース・アクセス・コントロール(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
レルム ロールを与えられているかどうかを調べています。
const context = $evaluation.getContext();
const identity = context.getIdentity();
if (identity.hasRealmRole('keycloak_user')) {
$evaluation.grant();
}
または、ユーザーが my-client-role
クライアント ・ロールを与えられているかどうかを確認できます。my-clientはクライアント・アプリケーションのクライアントIDです。
const context = $evaluation.getContext();
const identity = context.getIdentity();
if (identity.hasClientRole('my-client', 'my-client-role')) {
$evaluation.grant();
}
ユーザーに付与されているロールのチェック
ユーザーに付与されているレルムロールをチェックするには、次のようにします。
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();
}
グループに付与されたロールのチェック
グループに付与されているレルムロールをチェックするには、次のようにします。
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 を実装するオブジェクトであることに注意してください。このインターフェイスから何にアクセスできるかの詳細については、Evaluation APIを参照してください。 |
タイムベース・ポリシー
このタイプのポリシーを使用して、パーミッションの時間条件を定義することができます。
新しい時間ベースのポリシーを作成するには、ポリシー一覧の右上にある項目リストで Time を選択します。
設定
-
Name
ポリシーを説明する、人が判読可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別することができます。
-
説明
このポリシーに関する詳細情報を含む文字列。
-
Start time
アクセスを許可 しない 時間を定義します。現在の日付/時刻がこの値よりも後の場合にのみ許可が与えられます。
-
Expire time
アクセスを許可してはならない時刻を定義します。現在の日付/時刻がこの値より早いか等しい場合にのみ、アクセスが許可されます。特定の 曜日 、 月 、 年 、 時 、 分 にアクセスを繰り返し許可する場合は、 Repeat を選択します。
-
Day of Month
アクセスを許可する月の日を定義します。また、日付の範囲を指定することもできます。この場合、その月の現在の日が指定された2つの値の間にあるまたは等しい場合にのみ許可が与えられます。
-
Month
アクセスを許可する月を定義します。また、月の範囲を指定することもできます。この場合、現在の月が指定された2つの値の間にあるまたは等しい場合にのみ許可が与えられます。
-
Year
アクセスを許可する年を定義します。また、年の範囲を指定することもできます。この場合、現在の年が指定された2つの値の間にあるまたは等しい場合にのみ許可が与えられます。
-
Hour
アクセスを許可する時間を定義します。また、時間の範囲を指定することもできます。この場合、現在の時間が指定された2つの値の間にあるまたは等しい場合にのみ許可が与えられます。
-
Minute
アクセスを許可する分を定義します。また、分の範囲を指定することもできます。この場合、現在の分が指定された2つの値の間にあるまたは等しい場合にのみ許可が与えられます。
-
Logic
他の条件が評価された後に適用するロジックです。
アクセスは、すべての条件が満たされている場合にのみ許可されます。Keycloakは、各条件の結果に基づいて AND を実行します。
集約されたポリシー
前述のとおり、Keycloakではポリシーのポリシーを構築できます。これはポリシー集約と呼ばれる概念です。 ポリシー集約を使用すると、既存のポリシーを再利用してより複雑なポリシーを構築し、認可リクエストの処理中に評価されるポリシーとのアクセスをさらに分離することができます。
新しい集約ポリシーを作成するには、ポリシータイプの一覧から Aggregated を選択します。
Confidential Resource というリソースがあり、 keycloak.org ドメインと特定の範囲のIPアドレスからアクセスできるユーザーがいるとします。両方の条件で単一のポリシーを作成できます。ただし、このポリシーのドメイン部分を再利用して、元のネットワークに関係なく動作するパーミッションに適用したいかもしれません。
ドメインとネットワークの両方の条件に対して個別のポリシーを作成し、これらの2つのポリシーの組み合わせに基づいて第3のポリシーを作成することができます。集約されたポリシーを使用すると、他のポリシーを自由に組み合わせて、新しい集約ポリシーを任意のパーミッションに適用できます。
集約されたポリシーを作成する場合は、ポリシー間で循環参照または依存関係を導入していないことに注意してください。循環依存が検出された場合、ポリシーを作成または更新することはできません。 |
設定
-
Name
ポリシーを説明する、人が判読可能な一意の文字列。ビジネス要件とセキュリティー要件に密接に関連する名前を使用することを強くお勧めします。そうすることで、それらが実際に何を意味するのか簡単に識別することができます。
-
説明
このポリシーの詳細を示す文字列。
-
Apply Policy
集約されたポリシーに関連付ける1つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成します。
-
Decision Strategy
このパーミッションのための決定戦略。
-
Logic
他の条件が評価された後に適用するロジックです。
クライアントベース・ポリシー
このポリシーは、1つ以上のクライアントが、ある対象へアクセスすることを可能にする条件を定義するために使うことができます。
新しいクライアントベースのポリシーを作成するには、ポリシータイプの一覧から Client を選択します。
グループベース・ポリシー
このポリシーは、1つ以上のグループ(およびそれらの階層)が、ある対象へアクセスすることを可能にする条件を定義するために使うことができます。
新しいグループベースのポリシーを作成するには、ポリシータイプの一覧から Group を選択します。
設定
-
Name
ポリシーを説明する、人が判読可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別することができます。
-
説明
このポリシーに関する詳細情報を含む文字列。
-
Groups Claim
グループの名前および/またはパスを保持するトークン内のクレームの名前を指定します。通常、認可リクエストは、ユーザーに代わって動作するクライアントに対して、以前に発行されたIDトークンまたはアクセストークンに基づいて処理されます。これが定義されている場合、トークンには、このポリシーがユーザーの所属するグループを取得する場所を示すクレームが含まれている必要があります。定義されていない場合、ユーザーのグループはレルム設定から取得されます。
-
Groups
パーミッションを評価するときに、このポリシーにより実施されるグループを選択できます。 グループを追加した後、 Extend to Children チェックボックスをオンにすることで、子グループへのアクセスを拡張できます。マークされていない場合、アクセス制限は選択したグループにのみ適用されます。
-
Logic
他の条件が評価された後に適用するロジックです。
クライアント・スコープ・ベース・ポリシー
このポリシーは、1つ以上のクライアント・スコープが、ある対象へアクセスすることを可能にする条件を定義するために使うことができます。
デフォルトでは、このポリシーに追加されたクライアント・スコープは必要に応じて指定されておらず、アクセスを要求しているクライアントにこれらのクライアントスコープのいずれかが許可されている場合、ポリシーはアクセスを許可します。ただし、特定のクライアントスコープを適用する場合は、特定のクライアントスコープをrequiredとして指定できます。
新しいスコープベースのポリシーを作成するには、ポリシータイプの一覧から Client Scope を選択します。
設定
-
Name
ポリシーを説明する、人が判読可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別することができます。
-
説明
このポリシーに関する詳細情報を含む文字列。
-
Client Scopes
このポリシーによって、どのクライアント・スコープが許可されるかを指定します。
-
Logic
他の条件が評価された後に適用するロジックです。
必須としてクライアント・スコープを定義する
クライアント・スコープ・ベースのポリシーを作成するときに、特定のクライアント・スコープを Required
として指定できます。これを行うと、アクセスを要求しているクライアントに 全て の 必須 クライアント・スコープが付与されている場合にのみ、ポリシーはアクセスを許可します。
クライアント・スコープを必須と指定するには、そのクライアント・スコープの Required
チェックボックスをチェックします。
必須のクライアント・スコープは、ポリシーで複数のクライアント・スコープが定義されているが、それらのサブセットのみが必須である場合に役立ちます。
正規表現ベースのポリシー
このタイプのポリシーを使用して、パーミッションの正規表現の条件を定義することができます。
新しい正規表現ベースのポリシーを作成するには、ポリシータイプの一覧から Regex を選択します。
このポリシーは、現在のIDから利用可能な属性を解決します。
設定
-
Name
ポリシーを説明する、人が判読可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別することができます。
-
説明
このポリシーに関する詳細情報を含む文字列。
-
Target Claim
トークン内の対象クレームの名称を指定します。JSONベースのクレームでは、ドット記法で入れ子を行い、角括弧でインデックスによる配列フィールドにアクセスすることができます。例えば、contact.address[0].countryのようになります。対象のトクレームがJSONオブジェクトを参照する場合、最初のパス(たとえば、
contact
)は、JSONオブジェクトを保持する属性名にマッピングする必要があります。 -
Regex Pattern
正規表現パターンを指定します。
-
Logic
他の条件が評価された後に適用する、このポリシーのロジック。
肯定ロジックと否定ロジック
ポリシーには肯定または否定のオプションを付与できます。これにより、ポリシー適用の結果を反転させることができます。
たとえば、特定のロールを与えられて いない ユーザーのみアクセスを許可したいとします。この場合、まずそのロールを使ったロールベース・ポリシーを作成し、 Logic を Negative にセットします。Positive のままにしておくと、ポリシーはその定義どおりに適用されます。
Policy Evaluation API
JavaScriptを使用してルールベースのポリシーを作成する場合、Keycloakは、パーミッションを与える必要があるかどうかの判断に役立つ情報を提供するEvaluation 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アクセストークンに基づいて構築され、この構造は元のトークンから抽出されたすべてのクレームへのアクセスを有します。たとえば、 Protocol Mapper を使用してカスタムクレームをOAuth2アクセストークンに含める場合は、ポリシーからこのクレームにアクセスして、それを使用して条件を構築することもできます。
EvaluationContext
は、実行およびランタイム環境の両方に関連する属性へのアクセスも提供します。今のところ、いくつかの組み込み属性しかありません。
名前 | 説明 | Type |
---|---|---|
kc.time.date_time |
現在の日付と時刻 |
String。 |
kc.client.network.ip_address |
クライアントのIPv4アドレス |
String |
kc.client.network.host |
クライアントのホスト名 |
String |
kc.client.id |
クライアントID |
String |
kc.client.user_agent |
'User-Agent' HTTPヘッダーの値 |
String[] |
kc.realm.name |
レルムの名前 |
String |
パーミッションの管理
パーミッションは、保護されているオブジェクトとアクセスを許可するかどうかを決定するために評価されなければならないポリシーを関連付けます。
保護したいリソースを作成し、それらのリソースを保護するために使用するポリシーを作成したら、権限の管理を開始できます。パーミッションを管理するには、リソースサーバーを編集するときに Permissions タブをクリックします。
主な2つのタイプのオブジェクトを保護するパーミッションを作成できます。
-
Resources
-
Scopes
パーミッションを作成するには、パーミッションのリストの右上隅にある項目のリストから、作成するパーミッション・タイプを選択します。次のセクションでは、これら2種類のオブジェクトについて詳しく説明します。
リソースベースのパーミッションの作成
リソースベースのパーミッションは、1つ以上の認可ポリシーのセットを使用して保護する1つ以上のリソースのセットを定義します。
新しいリソースベースのパーミッションを作成するには、 Create permission*ドロップダウンから *Create resource-based permission を選択します。
設定
-
Name
パーミッションを説明する、人が判別可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別できます。
-
説明
パーミッションに関する詳細を含む文字列。
-
Apply To Resource Type
指定されたタイプのすべてのリソースにパーミッションを適用するかどうかを指定します。このフィールドを選択すると、保護するリソースタイプを入力するよう求められます。
-
Resource Type
保護するリソース・タイプを定義します。定義されている場合、このパーミッションはそのタイプに一致するすべてのリソースに対して評価されます。
-
-
Resources
保護する1つ以上のリソースのセットを定義します。
-
ポリシー
パーミッションに関連付ける1つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成します。
-
Decision Strategy
パーミッションのための決定戦略
タイプ付きリソース・パーミッション
リソース・パーミッションは、特定のタイプのすべてのリソースに適用されるポリシーを定義するためにも使用できます。この形式のリソース・ベースのパーミッションは、共通のアクセス要件と制約を共有するリソースを持つ場合に役立ちます。
多くの場合、アプリケーション内のリソースは、カプセル化したデータまたは提供する機能に基づいて分類(またはタイプ指定)できます。たとえば、金融アプリケーションは、ある特定の顧客が属している異なる銀行口座を管理することができます。それらは異なる銀行口座ですが、銀行組織によって全体的に定義される共通のセキュリティー要件および制約を共有します。タイプ付きのリソース・パーミッションを使用して、以下のようなすべての銀行口座に適用する共通ポリシーを定義することができます。
-
オーナーのみが自分のアカウントを管理できます。
-
オーナーの国や地域からのアクセスのみを許可します。
-
特定の認証方法を強制します。
タイプ付きのリソース・パーミッションを作成するには、新しいリソース・ベースのパーミッションを作成するときに、Apply to Resource Typeをクリックします。 Apply to Resource Type
を On
に設定すると、保護するタイプと、指定したタイプのすべてのリソースへのアクセスを制御するために適用されるポリシーを指定できます。
スコープベースのパーミッションの作成
スコープベースのパーミッションは、1つ以上の認可ポリシーのセットを使用して保護する1つ以上のスコープのセットを定義します。リソースベースのパーミッションとは異なり、このパーミッションのタイプを使用して、リソースだけでなく、それに関連付けられたスコープのパーミッションを作成し、リソースを管理するパーミッションとそれらに対して実行可能なアクションを定義する際に、より詳細な情報を提供します。
新しいスコープベースのパーミッションを作成するには、 Create permission*ドロップダウンから *Create scope-based permission を選択します。
設定
-
Name
パーミッションを説明する、人が判別可能で一意の文字列。ベスト・プラクティスは、ビジネス要件とセキュリティー要件に密接に関連する名前を使用することです。そうすることで簡単に識別できます。
-
説明
パーミッションに関する詳細を含む文字列。
-
Resource
選択したリソースに関連付けられているものにスコープを制限します。選択されていない場合は、すべてのスコープを使用できます。
-
Scopes
保護する1つ以上のスコープのセットを定義します。
-
ポリシー
パーミッションに関連付ける1つ以上のポリシーのセットを定義します。ポリシーを関連付けるには、既存のポリシーを選択するか、作成するポリシーのタイプを選択して新しいポリシーを作成します。
-
Decision Strategy
パーミッションのための決定戦略
ポリシーの評価とテスト
ポリシーを設計する際に、認可リクエストをシミュレートして、ポリシーの評価方法をテストすることができます。
リソースサーバーを編集するときに Evaluate
タブをクリックすると、ポリシー評価ツールにアクセスできます。そこで、さまざまな入力を指定して、実際の認可リクエストをシミュレートし、ポリシーの効果をテストすることができます。
認可サービス
Keycloak認可サービスは、OAuth2やUser-Managed Accessなどのよく知られている標準をベースに構築されています。
OAuth2クライアント(フロントエンド・アプリケーションなど)は、トークン・エンドポイントを使用してサーバーからアクセストークンを取得し、これらのトークンを使用してリソースサーバーによって保護されたリソース(バックエンド・サービスなど)にアクセスできます。同様に、Keycloak認可サービスは、要求されているリソースまたはスコープに関連するすべてのポリシーの処理に基づいてアクセストークンを発行できるように、OAuth2の拡張機能を提供します。つまり、リソースサーバーは、サーバーによって付与され、アクセストークンによって保持されているアクセス許可に基づいて、保護されたリソースへのアクセスを強制できます。Keycloak認可サービスでは、アクセス権を持つアクセストークンはリクエスティング・パーティー・トークンまたはRPTと呼ばれます。
RPTの発行に加えて、Keycloak認可サービスは、保護されたリソース、スコープ、パーミッション、およびポリシーをリソースサーバーが管理できるようにする一連のRESTfulエンドポイントも提供し、きめ細かい認可をサポートするために開発者がこれらのケイパビリティーをアプリケーションに拡張または統合することを支援します。
認可サービスのエンドポイントとメタデータの検出
Keycloakは、クライアントがKeycloak認可サービスと対話するために必要なすべての情報を取得するためのディスカバリー・ドキュメントを提供します。これにはエンドポイントの場所とケイパビリティーを含んでいます。
ディスカバリー・ドキュメントは以下から取得できます。
curl -X GET \
http://${host}:${port}/realms/${realm}/.well-known/uma2-configuration
${host}:${port}
は、Keycloakが実行されているホスト名(またはIPアドレス)とポートであり、 ${realm}
は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}/protocol/openid-connect/token",
"token_introspection_endpoint": "http://${host}:${port}/realms/${realm}/protocol/openid-connect/token/introspect",
"resource_registration_endpoint": "http://${host}:${port}/realms/${realm}/authz/protection/resource_set",
"permission_endpoint": "http://${host}:${port}/realms/${realm}/authz/protection/permission",
"policy_endpoint": "http://${host}:${port}/realms/${realm}/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
このパラメーターは required です。
urn:ietf:params:oauth:grant-type:uma-ticket
でなければなりません。 -
ticket
このパラメーターは optional です。UMA認可プロセスの一環としてクライアントが受信した最新のパーミッション・チケットです。
-
claim_token
このパラメーターは optional です。要求されているリソースとスコープのパーミッションを評価するときに、サーバーが考慮する必要がある追加の要求を表す文字列です。このパラメーターにより、クライアントはKeycloakにクレームをプッシュできます。サポートされているすべてのトークン形式の詳細については、
claim_token_format
パラメーターを参照してください。 -
claim_token_format
このパラメーターは optional です。
claim_token
パラメーターで指定されたトークンの形式を示す文字列です。Keycloakはurn:ietf:params:oauth:token-type:jwt
とhttps://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
このパラメーターは optional です。以前に発行されたRPTで、そのパーミッションも評価して新しいものに追加する必要があります。このパラメーターを使用すると、RPTを所有しているクライアントは、必要に応じてパーミッションが追加される増分認可を実行できます。
-
permission
このパラメーターは optional です。クライアントがアクセスしようとしている1つ以上のリソースとスコープのセットを表す文字列です。このパラメーターは、複数のリソースとスコープに対するパーミッションを要求するために複数回定義することができます。このパラメーターは、クライアントがパーミッション・チケットなしで認可リクエストを送信できるようにするための、
urn:ietf:params:oauth:grant-type:uma-ticket
グラントタイプの拡張です。文字列の形式は次のとおりでなければなりません。RESOURCE_ID#SCOPE_ID
。例:Resource A#Scope A
、Resource A#Scope A, Scope B, Scope C
、Resource A
、#Scope A
。 -
audience
このパラメーターは optional です。クライアントがアクセスしようとしているリソースサーバーのクライアント識別子です。このパラメーターは
permission
パラメーターが定義されている場合に必須です。パーミッションが評価されるべきコンテキストを示すための、Keycloakへのヒントとして役立ちます。 -
response_include_resource_name
このパラメーターは optional です。リソース名をRPTのパーミッションに含めるかどうかをサーバーに示すブール値です。falseの場合、リソース識別子のみが含まれます。
-
response_permissions_limit
このパラメーターは optional です。RPTが持つことができるパーミッションの量の限界を定義する整数Nです。
rpt
パラメーターと一緒に使用すると、最後に要求されたN個のパーミッションだけがRPTに保持されます。 -
submit_request
このパラメーターは optional です。サーバーがリソースへのパーミッション・リクエストを作成する必要があるかどうかを示すブール値であり、パーミッション・チケットによって参照されるスコープです。このパラメーターは、UMA認可プロセスの一部として
ticket
パラメーターとともに使用される場合にのみ有効です。 -
response_mode
このパラメーターは optional です。サーバーが認可リクエストにどのように応答するかを示す文字列値。このパラメーターは、標準的な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}/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}/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}/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が発行されます。
HTTP/1.1 200 OK
Content-Type: application/json
...
{
"access_token": "${rpt}",
}
サーバーからのレスポンスは、他のグラントタイプを使用しているときのトークン・エンドポイントからの任意のレスポンスとまったく同じです。RPTは access_token
レスポンス・パラメーターから取得できます。クライアントが認可されていない場合、Keycloakは次のように 403
HTTPステータスコードで応答します。
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
グラントタイプを使う際に、クライアントは以下の認証方式のどれかを使用できます。
-
Bearer Token
クライアントは、トークン・エンドポイントにHTTP Authorizationヘッダーのベアラー・クレデンシャルとしてアクセストークンを送信する必要があります。
例:アクセストークンを使用してトークン・エンドポイントで認証する認可リクエストcurl -X POST \ http://${host}:${port}/realms/${realm}/protocol/openid-connect/token \ -H "Authorization: Bearer ${access_token}" \ --data "grant_type=urn:ietf:params:oauth:grant-type:uma-ticket"
この方法は、クライアントがユーザーに代わって動作している場合に特に便利です。この場合、ベアラートークンは以前にKeycloakにより、ユーザーの代わりに(またはそれ自体のために)動作しているクライアントに発行されたアクセストークンです。パーミッションは、アクセストークンによって表されるアクセス・コンテキストを考慮して評価されます。たとえば、アクセストークンがユーザーAの代わりに動作するクライアントAに発行された場合、ユーザーAがアクセス権を持つリソース及びスコープに応じてパーミッションが与えられます。
-
Client Credentials
クライアントは、Keycloakでサポートされているクライアント認証方式を使用できます。たとえば、client_id / client_secretやJWTです。
例:クライアントIDとクライアント・シークレットを使用して、トークン・エンドポイントで認証する認可リクエストcurl -X POST \ http://${host}:${port}/realms/${realm}/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}/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を参照してください。
User-Managed Access
Keycloak認可サービスは、User-Managed Access(略してUMA)に基づいています。UMAは、以下の方法でOAuth2の機能を強化する仕様です。
-
Privacy
現在、クラウドに接続するデータやデバイスが増えているため、ユーザーのプライバシーは大きな問題になっています。UMAとKeycloakを使用すると、リソースサーバーは、ユーザーが定義したポリシーに基づいてパーミッションが与えられているユーザーのプライバシーに関するリソースの保護方法を向上させるように機能を強化できます。
-
Party-to-Party Authorization
リソースオーナー(たとえば、通常のエンドユーザー)は、そのリソースへのアクセスを管理し、他の関係者(たとえば、通常のエンドユーザー)がこれらのリソースにアクセスすることを認可することができます。これは、完全に非同期に、UMAリソースオーナーが他のユーザーへのアクセスを同意することを許可された状態で、ユーザーに代わって動作するクライアント・アプリケーションに同意が与えられるOAuth2とは異なります。
-
Resource Sharing
リソースオーナーは、リソースへのアクセス許可を管理し、特定のリソースにアクセスできるユーザーとその方法を決定できます。Keycloakは、リソースオーナーがリソースを管理できる共有管理サービスとして機能します。
Keycloakは、大部分のUMA機能を提供するUMA 2.0準拠の認可サーバーです。
たとえば、インターネット・バンキング・サービス(リソースサーバー)を使用して自分の銀行口座(リソース)を管理するユーザーAlice(リソースオーナー)を考えてみましょう。ある日、アリスはアカウンティング・プロフェッショナルのボブ(依頼者)に銀行口座を開設することに決めました。しかし、BobはAliceのアカウントを表示(スコープ)するためのアクセス権しか持つべきではありません。
リソースサーバーとして、インターネット・バンキング・サービスはアリスの銀行口座を保護できなければなりません。そのため、Keycloakリソース登録エンドポイントを使用して、Aliceの銀行口座を表すサーバーにリソースを作成します。
この時点で、BobがAliceの銀行口座にアクセスしようとすると、アクセスは拒否されます。インターネット・バンキング・サービスは、銀行口座のいくつかのデフォルト・ポリシーを定義しています。そのうちの1つは、オーナー(この場合はアリス)のみが自分の銀行口座にアクセスできることです。
しかし、インターネット・バンキング・サービスは、アリスのプライバシーに関して、彼女が銀行口座の特定のポリシーを変更することも可能にします。彼女が変更できるこれらのポリシーの1つは、誰が自分の銀行口座を見ることができるかを定義することです。そのために、インターネット・バンキング・サービスは、Keycloakを利用して、個人が選択できるスペースとアクセスが許可されている操作(またはデータ)をAliceに提供します。Aliceはいつでも、アクセス権を取り消したり、Bobに追加の許可を与えることができます。
認可プロセス
UMAでは、クライアントがUMAで保護されたリソースサーバーにアクセスしようとすると、認可プロセスが開始されます。
UMAで保護されたリソースサーバーは、リクエスト内のベアラートークンがRPTであることを想定しています。クライアントがRPTなしでリソースサーバーにリソースを要求する場合、次のようになります。
curl -X GET \
http://${host}:${port}/my-resource-server/resource/1bfdfe78-a4e1-4c2d-b142-fc92b75b986f
リソースサーバーは、RPTを取得するためにチケットが送られるべきKeycloakサーバーの場所とともに、パーミッション ticket
と as_uri
パラメーターを持つレスポンスをクライアントに返します。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="${realm}",
as_uri="https://${host}:${port}/realms/${realm}",
ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"
パーミッション・チケットは、Keycloak Permission APIによって発行される特別なタイプのトークンです。これらは、要求されるパーミッション(たとえば、リソースおよびスコープ)、ならびにリクエストに関連する他の情報を表します。リソースサーバーのみがこれらのトークンを作成できます。
クライアントはパーミッション・チケットを持つとともにKeycloakサーバーの場所も知っているので、クライアントはディスカバリー文書を使用してトークン・エンドポイントの場所を取得し、認可リクエストを送信できます。
curl -X POST \
http://${host}:${port}/realms/${realm}/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が発行されます。
HTTP/1.1 200 OK
Content-Type: application/json
...
{
"access_token": "${rpt}",
}
サーバーからのレスポンスは、他のグラントタイプを使用しているときのトークン・エンドポイントからの任意のレスポンスとまったく同じです。RPTは access_token
レスポンス・パラメーターから取得できます。パーミッションを得るためにクライアントが認可されていない場合、Keycloakは次のように 403
HTTPステータスコードで応答します。
HTTP/1.1 403 Forbidden
Content-Type: application/json
...
{
"error": "access_denied",
"error_description": "request_denied"
}
パーミッション・リクエストの送信
認可プロセスの一環として、クライアントはKeycloakトークン・エンドポイントでRPTと交換するために、まずUMAで保護されたリソースサーバーからパーミッション・チケットを取得する必要があります。
クライアントがRPTを発行できない場合、デフォルトでKeycloakは 403
HTTPステータスコードと request_denied
エラーで応答します。
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}/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は、アクセスが拒否された各リソースに対して、パーミッション・リクエストを永続化します。作成されると、リソースオーナーは自分のアカウントを確認し、パーミッション・リクエストを管理できます。
この機能は、アプリケーション内の Request Access
ボタンとして考えることができます。このボタンは、ユーザーが他のユーザーにリソースへのアクセスを求めることを可能にします。
ユーザーリソースへのアクセスの管理
ユーザーは、Keycloakのアカウント・コンソールを使用して、自分のリソースへのアクセスを管理することができます。この機能を有効にするには、まずレルムに対してUser-Managed Accessを有効にする必要があります。
-
管理コンソールにログインします。
-
メニューの Realm Settings をクリックします。
-
User-Managed Access を ON に切り替えます。
-
管理コンソールの右上にあるユーザー名をクリックし、 Manage Account を選択します。
-
メニューオプションの My Resources をクリックします。以下のオプションが付いたページが表示されます。
-
My resources の管理
このセクションには、ユーザーが所有するすべてのリソースの一覧が含まれています。ユーザーは、リソースをクリックして詳細を確認したり、リソースを他のユーザーと共有することができます。承認待ちのパーミッション・リクエストがある場合、リソースの名前の横にアイコンが表示されます。これらのリクエストは、特定のリソースへのアクセスを要求する当事者(ユーザー)に接続されています。ユーザーは、これらのリクエストの承認または拒否を行うことができます。アイコンをクリックすることで、承認することができます。
-
Resources shared with me の管理
このセクションには、ユーザーと共有するすべてのリソースのリストが含まれています。
-
People with access to this resource の管理
このセクションには、リソースにアクセスできるユーザーのリストが含まれています。 ユーザーは、
Revoke
ボタンをクリックするか、特定のPermission
を削除することによって、アクセスを取り消すことができます。 -
他の人とリソースを共有する
別のユーザーのユーザー名または電子メールを入力することにより、ユーザーはリソースを共有し、アクセスを許可するパーミッションを選択することができます。
-
Protection API
Protection APIは、UMA準拠のエンドポイントのセットを提供します。
-
リソースの管理
このエンドポイントを使用すると、リソースサーバーはリソースをリモートで管理し、ポリシー・エンフォーサーが保護を必要とするリソースをサーバーに問い合わせできるようになります。
-
パーミッションの管理
UMAプロトコルでは、リソースサーバーはこのエンドポイントにアクセスしてパーミッション・チケットを作成します。Keycloakには、パーミッションの状態やクエリー・パーミッションを管理するためのエンドポイントも用意されています。
-
Policy API
KeycloakはUMA Protection APIを利用して、リソースサーバーがユーザーのパーミッションを管理できるようにします。KeycloakはリソースAPIとパーミッションAPIに加えて、ユーザーの代わりにリソースサーバーによって、リソースにパーミッションを設定できるPolicy APIを提供します。
このAPIの重要な要件は、Protection APIトークン(PAT)と呼ばれる特別なOAuth2アクセストークンを使用して、リソースサーバー だけ がエンドポイントにアクセスできることです。UMAでは、PATはスコープ uma_protection を持つトークンです。
PATとは何か、そしてそれをどのように取得するか
Protection APIトークン (PAT)は、 uma_protection として定義されたスコープを持つ特殊なOAuth2アクセストークンです。リソースサーバーを作成すると、Keycloakは対応するクライアント・アプリケーションのロール uma_protection を自動的に作成し、クライアントのサービス・アカウントに関連付けます。
リソースサーバーは、Keycloakから他のOAuth2アクセストークンと同様に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://localhost:8080/realms/${realm_name}/protocol/openid-connect/token"
上記の例では、 client_credentials グラントタイプを使用してサーバーからPATを取得しています。その結果、サーバーは次のような応答を返します。
{
"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_id と client_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 Resource Registration 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
サーバーにパーミッションを問い合わせる際に、結果を制限するためにパラメーター first
と max
を使用します。
パーミッション・リクエストの管理
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"
}'
Policy APIを使用したリソース・パーミッションの管理
KeycloakはUMA Protection APIを利用して、リソースサーバーがユーザーのパーミッションを管理できるようにします。KeycloakはリソースAPIとパーミッションAPIに加えて、ユーザーの代わりにリソースサーバーによって、リソースにパーミッションを設定できるPolicy APIを提供します。
Policy APIは次の場所にあります。
http://${host}:${port}/realms/${realm_name}/authz/protection/uma-policy/{resource_id}
このAPIは、ユーザーからリソースサーバーへの承諾を表すベアラトークンによって保護されています。ベアラトークンは、以下を使用することで、トークン・エンドポイントから取得された通常のアクセストークンとすることができます。
-
リソース・オーナー・パスワード・クレデンシャル・グラント・タイプ
-
Audienceがリソースサーバーであるトークンのために、あるクライアント(パブリック・クライアント)に与えられたアクセストークンを交換するためのToken Exchange
パーミッションとリソースの関連付け
パーミッションを特定のリソースに関連付けるには、次のようにHTTP POSTリクエストを送信する必要があります。
curl -X POST \
http://localhost: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"]
}'
上記の例では、 people-manager
ロールを持つユーザに対して read
スコープを付与するように、 resource_id
で表されるリソースに新しいパーミッションを作成して関連付けています。
次のようにグループを使用するなど、他のアクセス・コントロールの機構を使用してポリシーを作成することもできます。
curl -X POST \
http://localhost: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 \
http://localhost: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を使用してカスタムポリシーを使用することもできます。
Upload Scriptsは 非推奨 であり、将来のリリースで削除されます。この機能はデフォルトで無効になっています。 有効にするには、 |
curl -X POST \
http://localhost: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 \
http://localhost: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 \
http://localhost:8180/realms/photoz/authz/protection/uma-policy/{permission_id} \
-H 'Authorization: Bearer '$access_token
パーミッションの問い合わせ
リソースに関連付けられているパーミッションを参照するには、次のようにHTTP GETリクエストを送信します。
http://${host}:${port}/realms/${realm}/authz/protection/uma-policy?resource={resource_id}
名前でパーミッションを参照するには、次のようにHTTP GETリクエストを送信します。
http://${host}:${port}/realms/${realm}/authz/protection/uma-policy?name=Any people manager
特定のスコープに関連付けられているパーミッションを参照するには、次のようにHTTP GETリクエストを送信します。
http://${host}:${port}/realms/${realm}/authz/protection/uma-policy?scope=read
すべてのパーミッションを参照するには、次のようにHTTP GETリクエストを送信します。
http://${host}:${port}/realms/${realm}/authz/protection/uma-policy
サーバーにパーミッションを問い合わせる際に、結果を制限するためにパラメーター first
と max
を使用します。
リクエスティング・パーティー・トークン
Requesting party token(RPT)は JSON web signature(JWS) でデジタル署名された JSON web token(JWT) です。RPTは、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に関する情報の取得
トークン・イントロスペクションは基本的に、RPTに関する情報を取得するための OAuth2トークン・イントロスペクション 準拠のエンドポイントです。
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}' \
"http://localhost: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もJWT(JSON Web Token)仕様をデフォルトのフォーマットとして使用します。
リモート・イントロスペクション・エンドポイントを呼び出さずにこれらのトークンを検証する場合は、RPTをデコードしてローカルでその有効性を問い合わせることができます。トークンをデコードすると、トークン内のパーミッションを使用して認可の決定を行うこともできます。
これは、基本的にポリシー・エンフォーサーが行うことです。以下を確認してください。
-
RPTのシグネチャーを検証する(レルムの公開鍵に基づいて)
-
exp 、iat 、および aud のクレームに基づいてトークンの有効性を問い合わせる
認可クライアントJava API
要件に応じて、リソースサーバーはリソースをリモートで管理したり、プログラムでパーミッションをチェックしたりすることもできます。Javaを使用している場合は、認可クライアントAPIを使用してKeycloak認可サービスにアクセスできます。
これは、トークン・エンドポイント、リソース・エンドポイント、およびパーミッション管理エンドポイントなど、サーバーが提供するさまざまなエンドポイントに、アクセスするリソースサーバーを対象としています。
Mavenの依存関係
<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-client</artifactId>
<version>${KEYCLOAK_VERSION}</version>
</dependency>
</dependencies>
設定
クライアントの設定は、 keycloak.json
ファイルで次のように定義されています。
{
"realm": "hello-world-authz",
"auth-server-url" : "http://localhost:8080",
"resource" : "hello-world-authz-service",
"credentials": {
"secret": "secret"
}
}
-
realm (必須)
レルムの名前。
-
auth-server-url (必須)
The base URL of the Keycloak server. All other Keycloak pages and REST service endpoints are derived from this. It is usually in the form https://host:port.
-
resource (必須)
アプリケーションのクライアントID。各アプリケーションには、アプリケーションを識別するために使用されるクライアント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);
}
ポリシー・エンフォーサー
ポリシー実施ポイント(PEP)はデザインパターンの1つであり、さまざまな方法で実装できます。Keycloakは、さまざまなプラットフォーム、環境、およびプログラミング言語に対してPEPを実装するために必要なすべての手段を提供します。Keycloak認可サービスは、RESTfulなAPIを提供し、一元的な認可サーバーを使用してきめ細かな認可を行うための、OAuth2認可機能を活用します。
PEPは、保護されたリソースに関連するポリシーを評価することによって、これらの決定が行われるKeycloakサーバーからのアクセス決定を強制する責任があります。これらの決定によって与えられたパーミッションに基づいて、保護されたリソースへの特定の要求が満たされているかどうかをチェックするために、アプリケーションのフィルターまたはインターセプターとして機能します。
パーミッションは、使用しているプロトコルによって異なります。UMAを使用する場合、ポリシー・エンフォーサーは、リクエストを処理できるかどうかを決定するために、RPTをベアラートークンとして常に想定しています。つまり、クライアントは、リソースサーバーにリクエストを送信する前に、まずKeycloakからRPTを取得する必要があります。
ただし、UMAを使用していない場合は、通常のアクセストークンをリソースサーバーに送信することもできます。この場合、ポリシー・エンフォーサーはサーバーから直接パーミッションを取得しようとします。
Keycloak OIDCアダプターのいずれかを使用している場合は、 keycloak.json ファイルに次のプロパティーを追加することで簡単にポリシー・エンフォーサーを有効にできます。
{
"policy-enforcer": {}
}
ポリシー・エンフォーサーを有効にすると、アプリケーションに送信されたすべてのリクエストはインターセプトされ、リクエストしているアイデンティティーにKeycloakが付与したパーミッションに応じて、保護されたリソースへのアクセスが許可されます。
ポリシー適用は、アプリケーションのパスと、Keycloak管理コンソールを使用してリソースサーバー用に作成したリソースに強く関連しています。デフォルトでは、リソースサーバーを作成すると、Keycloakはリソースサーバーのデフォルト設定を作成し、ポリシー適用を即時に有効化することができます。
設定
アプリケーションのポリシー適用を有効にするには、 keycloak.json ファイルに次のプロパティーを追加します。
{
"policy-enforcer": {}
}
または、保護されているリソースを手動で定義する場合は、以下のようにもう少し詳細化します。
{
"policy-enforcer": {
"user-managed-access" : {},
"enforcement-mode" : "ENFORCING",
"paths": [
{
"path" : "/someUri/*",
"methods" : [
{
"method": "GET",
"scopes" : ["urn:app.com:scopes:view"]
},
{
"method": "POST",
"scopes" : ["urn:app.com:scopes:create"]
}
]
},
{
"name" : "Some Resource",
"path" : "/usingPattern/{id}",
"methods" : [
{
"method": "DELETE",
"scopes" : ["urn:app.com:scopes:delete"]
}
]
},
{
"path" : "/exactMatch"
},
{
"name" : "Admin Resources",
"path" : "/usingWildCards/*"
}
]
}
}
各設定オプションの説明は次のとおりです。
-
policy-enforcer
ポリシーが実際にどのように実施されるのかを定義する設定オプションと、保護したいパス(任意)を指定します。指定されていない場合、ポリシー・エンフォーサーは、保護されているリソースサーバーに関連付けられているすべてのリソースをサーバーに問い合わせます。この場合、保護するパスと一致するURISプロパティーを持つリソースが適切に設定されていることを確認する必要があります。
-
user-managed-access
アダプターがUMAプロトコルを使用することを指定します。指定されている場合、アダプターはサーバーにパーミッション・チケットを問い合わせ、UMA仕様に従ってクライアントに戻します。指定されていない場合、ポリシー・エンフォーサーは、通常のアクセストークンまたはRPTに基づいて、パーミッションを適用できます。この場合、トークンにパーミッションがないときは、リソースへのアクセスを拒否する前に、ポリシー・エンフォーサーはサーバーから直接パーミッションを取得しようとします。
-
enforcement-mode
ポリシーの適用方法を指定します。
-
ENFORCING
(デフォルトモード)特定のリソースに関連付けられたポリシーがない場合でも、デフォルトでリクエストは拒否されます。
-
PERMISSIVE
特定のリソースに関連付けられたポリシーがない場合でも、リクエストは許可されます。
-
DISABLED
ポリシーの評価を完全に無効にし、任意のリソースへのアクセスを許可します。
enforcement-mode
がDISABLED
のとき、アプリケーションは 認可コンテキストを介してKeycloakによって与えられたすべてのパーミッションを引き続き取得できます。
-
-
on-deny-redirect-to
サーバーから"access denied"のメッセージを取得したときに、クライアント・リクエストがリダイレクトされるURLを定義します。デフォルトでは、アダプターは403 HTTPステータスコードで応答します。
-
path-cache
ポリシー・エンフォーサーがアプリケーション内のパスとKeycloakで定義されているリソースとの間の関連性を追跡する方法を定義します。キャッシュは、パスと保護されたリソース間の関連付けをキャッシュすることによって、Keycloakサーバーへの不要なリクエストを回避するために必要です。
-
lifespan
エントリーを期限切れにする時間をミリ秒単位で定義します。指定されていない場合、デフォルト値は 30000 です。0を設定してキャッシュを完全に無効にすることができます。または、-1を設定してキャッシュの有効期限を無効にすることもできます。
-
max-entries
キャッシュに保持する必要があるエントリーの制限を定義します。指定されていない場合、デフォルト値は 1000 です。
-
-
paths
保護するパスを指定します。この設定はオプションです。定義されていない場合、ポリシー・エンフォーサーはKeycloakでアプリケーションに定義したリソースをフェッチすることによってすべてのパスを検出します。これらのリソースは、アプリケーションのパスを表す
URIS
で定義されます。-
name
指定されたパスに関連付けられるサーバー上のリソースの名前。ポリシー・エンフォーサーは、 path と組み合わせて使用すると、リソースの URIS プロパティーを無視し、代わりに指定したパスを使用します。
-
path
(必須)アプリケーションのコンテキストパスに関連するURI。このオプションを指定すると、ポリシー・エンフォーサーは、同じ値の URI を持つリソースをサーバーに問い合わせます。現在、パスマッチングのための最も基本的なロジックがサポートされています。有効なパスの例は次のとおりです。
-
ワイルドカード:
/*
-
サフィックス:
/*.html
-
サブパス:
/path/*
-
パスパラメーター:/resource/{id}
-
完全一致:/resource
-
パターン:/{version}/resource、 /api/{version}/resource、 /api/{version}/resource/*
-
-
methods
保護するHTTPメソッド(GET、POST、PATCHなど)と、サーバー内の特定のリソースのスコープにどのように関連付けられているかを示します。
-
method
HTTPメソッドの名前。
-
scopes
メソッドに関連付けられたスコープを持つ文字列の配列。スコープを特定のメソッドに関連付けると、保護されたリソース(またはパス)にアクセスしようとするクライアントは、そのリストに指定されたすべてのスコープにパーミッションを与えるRPTを提供する必要があります。たとえば、スコープ create を持つメソッド POST を定義した場合、RPTにはパスへのPOSTを実行したときに create スコープへのアクセスを許可するパーミッションが含まれていなければなりません。
-
scopes-enforcement-mode
メソッドに関連付けられたスコープの適用モードを参照する文字列。値は ALL または ANY にすることができます。 ALL の場合、そのメソッドを使用してリソースにアクセスするには、すべての定義されたスコープを付与する必要があります。 ANY の場合は、そのメソッドを使用してリソースにアクセスするために、少なくとも1つのスコープを付与する必要があります。デフォルトでは、適用モードは ALL に設定されています。
-
-
enforcement-mode
ポリシーの適用方法を指定します。
-
ENFORCING
(デフォルトモード)特定のリソースに関連付けられたポリシーがない場合でも、デフォルトでリクエストは拒否されます。
-
DISABLED
-
-
claim-information-point
これらのクレームをポリシーで利用できるようにするために解決され、Keycloakサーバーにプッシュされなければならない1つ以上のクレームのセットを定義します。詳細については、Claim Information Pointを参照してください。
-
-
lazy-load-paths
アプリケーションのパスに関連付けられたリソースに対して、アダプターがサーバーをフェッチする方法を指定します。 true の場合、ポリシー・エンフォーサーは、要求されているパスに従ってオンデマンド・リソースをフェッチします。配備中にサーバーからすべてのリソースを取得したくない場合(
paths
を指定しなかった場合)や、paths
のサブセットしか定義せず、要求に応じて他のものをフェッチしたい場合に、この設定は特に便利です。 -
http-method-as-scope
スコープをHTTPメソッドにマッピングする方法を指定します。 true に設定されている場合、ポリシー・エンフォーサーは現在のリクエストからのHTTPメソッドを使用して、アクセスを許可する必要があるかどうかをチェックします。有効になっている場合は、Keycloakのリソースが保護している各HTTPメソッドを表すスコープに関連付けられていることを確認してください。
-
claim-information-point
これらのクレームをポリシーで利用できるようにするために解決され、Keycloakサーバーにプッシュされなければならない1つ以上の global クレームのセットを定義します。詳細については、Claim Information Pointを参照してください。
-
クレーム情報ポイント
クレーム情報ポイント(CIP)は、クレームを解決し、それらのクレームをKeycloakサーバーにプッシュすることにより、ポリシーへのアクセス・コンテキストに関する詳細情報を提供します。さまざまなソースからの要求を解決するために、次のようなポリシー・エンフォーサーの設定オプションとして定義できます。
-
HTTPリクエスト(パラメーター、ヘッダー、ボディーなど)
-
外部HTTPサービス
-
設定で定義された静的な値
-
クレーム情報プロバイダーSPIを実装することによる他のソース
クレームをKeycloakサーバーにプッシュすると、ポリシーは、ユーザーが誰であるかだけでなく、コンテキストとコンテンツを考慮して決定を下すことができます(トランザクションに対して誰が、何を、いつ、どこで、どのような、に基づいて)。それはコンテキストベースの認可と、きめ細かい認可決定をサポートするためのランタイム情報の使用方法に関するすべてのものです。
HTTPリクエストからの情報の取得
HTTPリクエストからクレームを抽出する方法を示すいくつかの例を以下に示します。
"policy-enforcer": {
"paths": [
{
"path": "/protected/resource",
"claim-information-point": {
"claims": {
"claim-from-request-parameter": "{request.parameter['a']}",
"claim-from-header": "{request.header['b']}",
"claim-from-cookie": "{request.cookie['c']}",
"claim-from-remoteAddr": "{request.remoteAddr}",
"claim-from-method": "{request.method}",
"claim-from-uri": "{request.uri}",
"claim-from-relativePath": "{request.relativePath}",
"claim-from-secure": "{request.secure}",
"claim-from-json-body-object": "{request.body['/a/b/c']}",
"claim-from-json-body-array": "{request.body['/d/1']}",
"claim-from-body": "{request.body}",
"claim-from-static-value": "static value",
"claim-from-multiple-static-value": ["static", "value"],
"param-replace-multiple-placeholder": "Test {keycloak.access_token['/custom_claim/0']} and {request.parameter['a']} "
}
}
}
]
}
外部HTTPサービスからの情報の取得
外部HTTPサービスからクレームを抽出する方法を示すいくつかの例を以下に示します。
"policy-enforcer": {
"paths": [
{
"path": "/protected/resource",
"claim-information-point": {
"http": {
"claims": {
"claim-a": "/a",
"claim-d": "/d",
"claim-d0": "/d/0",
"claim-d-all": ["/d/0", "/d/1"]
},
"url": "http://mycompany/claim-provider",
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"header-b": ["header-b-value1", "header-b-value2"],
"Authorization": "Bearer {keycloak.access_token}"
},
"parameters": {
"param-a": ["param-a-value1", "param-a-value2"],
"param-subject": "{keycloak.access_token['/sub']}",
"param-user-name": "{keycloak.access_token['/preferred_username']}",
"param-other-claims": "{keycloak.access_token['/custom_claim']}"
}
}
}
}
]
}
静的なクレーム
"policy-enforcer": {
"paths": [
{
"path": "/protected/resource",
"claim-information-point": {
"claims": {
"claim-from-static-value": "static value",
"claim-from-multiple-static-value": ["static", "value"],
}
}
}
]
}
クレーム情報プロバイダーSPI
ビルトインのプロバイダーでは要件を満たすことができない場合、異なるクレーム情報ポイントをサポートするために、開発者はクレーム情報プロバイダーSPIを使用することができます。
たとえば、新しいCIPプロバイダーを実装するには、 org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory
と ClaimInformationPointProvider
を実装し、アプリケーションのクラスパスに META-INF/services/org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory
ファイルを提供する必要があります。
org.keycloak.adapters.authorization.ClaimInformationPointProviderFactory
の例:
public class MyClaimInformationPointProviderFactory implements ClaimInformationPointProviderFactory<MyClaimInformationPointProvider> {
@Override
public String getName() {
return "my-claims";
}
@Override
public void init(PolicyEnforcer policyEnforcer) {
}
@Override
public MyClaimInformationPointProvider create(Map<String, Object> config) {
return new MyClaimInformationPointProvider(config);
}
}
すべてのCIPプロバイダーは、上記の MyClaimInformationPointProviderFactory.getName
メソッドで定義されている名前に関連付けられている必要があります。この名前は policy-enforcer
設定の claim-information-point
セクションから実装への設定をマッピングするために使用されます。
リクエストを処理する際に、ポリシー・エンフォーサーは、MyClaimInformationPointProviderのインスタンスを取得するため、MyClaimInformationPointProviderFactory.createメソッドを呼び出します。呼び出されると、この特定のCIPプロバイダー用に定義された設定(claim-information-pointを経由)がマップとして渡されます。
ClaimInformationPointProvider
の例:
public class MyClaimInformationPointProvider implements ClaimInformationPointProvider {
private final Map<String, Object> config;
public MyClaimInformationPointProvider(Map<String, Object> config) {
this.config = config;
}
@Override
public Map<String, List<String>> resolve(HttpFacade httpFacade) {
Map<String, List<String>> claims = new HashMap<>();
// put whatever claim you want into the map
return claims;
}
}
認可コンテキストの取得
ポリシーの施行が有効になっている場合、サーバーから取得したパーミッションは org.keycloak.AuthorizationContext
で利用できます。このクラスは、パーミッションを取得し、特定のリソースまたはスコープに対してパーミッションが付与されているかどうかを確認するために使用できるいくつかのメソッドを提供します。
サーブレット・コンテナー内の認可コンテキストの取得
HttpServletRequest request = ... // obtain javax.servlet.http.HttpServletRequest
KeycloakSecurityContext keycloakSecurityContext =
(KeycloakSecurityContext) request
.getAttribute(KeycloakSecurityContext.class.getName());
AuthorizationContext authzContext =
keycloakSecurityContext.getAuthorizationContext();
KeycloakSecurityContext を得る方法の詳細については、アダプターの設定を参照してください。Keycloakでサポートされているサーブレット・コンテナーのいずれかを使用してアプリケーションを起動している場合は、上記の例でコンテキストを取得できます。
|
認可コンテキストを使用すると、サーバーによって行われて返された決定を、より詳細に制御できます。たとえば、リソースまたはスコープに関連付けられたパーミッションに応じて、アイテムを表示または非表示にする動的なメニューを作成することができます。
if (authzContext.hasResourcePermission("Project Resource")) {
// user can access the Project Resource
}
if (authzContext.hasResourcePermission("Admin Resource")) {
// user can access administration resources
}
if (authzContext.hasScopePermission("urn:project.com:project:create")) {
// user can create new projects
}
AuthorizationContext
は、Keycloak認可サービスのメイン機能の1つです。上記の例から、保護されたリソースはそれらを管理するポリシーに直接関連付けられていないことが分かります。
次のような、ロールベースのアクセス制御(RBAC)を使用した同様のコードを考えてみましょう。
if (User.hasRole('user')) {
// user can access the Project Resource
}
if (User.hasRole('admin')) {
// user can access administration resources
}
if (User.hasRole('project-manager')) {
// user can create new projects
}
どちらの例も同じ要件に対応していますが、異なる方法で対応しています。RBACでは、ロールはリソースに対するアクセスのみを 暗黙的に 定義します。Keycloakを使用すると、RBAC、属性ベースのアクセス制御(ABAC)、その他のBACバリアントのいずれを使用していても、リソースに直接フォーカスした管理しやすいコードを作成できます。与えられたリソースまたはスコープに対するパーミッションを持っているかどうかです。
セキュリティー要件が変更され、プロジェクト・マネージャーに加えて、PMOが新しいプロジェクトを作成できるようになったとします。
セキュリティー要件は変更されますが、Keycloakを使用すると、新しい要件を満たすためにアプリケーションコードを変更する必要はありません。アプリケーションがリソースとスコープの識別子に基づいていれば、認可サーバー内の特定のリソースに関連付けられているパーミッションまたはポリシーの設定を変更するだけで済みます。この場合、 Project Resource
および(または)スコープ urn:project.com:project:create
に関連するパーミッションとポリシーが変更されます。
認可クライアント・インスタンスを取得するためAuthorizationContextを使用する
AuthorizationContext
は、以下のようにアプリケーションに設定された認可クライアントAPI への参照を取得するためにも使用できます。
ClientAuthorizationContext clientContext = ClientAuthorizationContext.class.cast(authzContext);
AuthzClient authzClient = clientContext.getClient();
場合によっては、ポリシー・エンフォーサーによって保護されたリソースサーバーが、認可サーバーによって提供されるAPIにアクセスする必要があります。取得した
インスタンスで、リソースサーバーはリソースを作成したり、プログラムで特定のパーミッションをチェックするためにサーバーとやりとりすることができます。AuthzClient
JavaScriptの統合
Keycloakサーバーには、ポリシー・エンフォーサーによって保護されたリソースサーバーと対話するために使用できるJavaScriptライブラリーが付属しています。このライブラリーはKeycloak JavaScriptアダプターに基づいています。これを統合すると、クライアントはKeycloakサーバーからパーミッションを取得できます。
次の script
タグをWebページに含めることで、実行中のKeycloakサーバー・インスタンスからこのライブラリーを入手できます。
<script src="http://.../js/keycloak-authz.js"></script>
これを実行すると、次のように KeycloakAuthorization
インスタンスを作成できます。
const keycloak = ... // obtain a Keycloak instance from keycloak.js library
const authorization = new KeycloakAuthorization(keycloak);
keycloak-authz.js ライブラリには2つの主な機能があります。
-
UMAで保護されたリソースサーバーにアクセスする場合は、パーミッション・チケットを使用して、サーバーからパーミッションを取得します。
-
アプリケーションがアクセスしたいリソースとスコープを送信して、サーバーからパーミッションを取得します。
いずれの場合も、リソースサーバーとKeycloak認可サービスの両方との対話を容易にし、クライアントがリソースサーバー上の保護されたリソースにアクセスするベアラー・トークンとして使用できる権限を持つトークンを取得できます。
UMAで保護されたリソースサーバーからの認可レスポンスの処理
リソースサーバーがポリシー・エンフォーサーによって保護されている場合、リソースサーバーは、ベアラートークンとともに搬送されるパーミッションに基づいてクライアント・リクエストに応答します。通常、保護されたリソースにアクセスする権限がないベアラトークンを使用してリソースサーバーにアクセスしようとすると、リソースサーバーは 401 ステータスコードと WWW-Authenticate
ヘッダーで応答します。
HTTP/1.1 401 Unauthorized
WWW-Authenticate: UMA realm="${realm}",
as_uri="https://${host}:${port}/realms/${realm}",
ticket="016f84e8-f9b9-11e0-bd6f-0021cc6004de"
詳細については、UMAの認可プロセスを参照してください。
クライアントが行う必要があるのは、リソースサーバーから返された
ヘッダーからパーミッション・チケットを抽出し、ライブラリーを使用して次のように認可リクエストを送信することです。WWW-Authenticate
// prepare a authorization request with the permission ticket
const authorizationRequest = {};
authorizationRequest.ticket = ticket;
// send the authorization request, if successful retry the request
Identity.authorization.authorize(authorizationRequest).then(function (rpt) {
// onGrant
}, function () {
// onDeny
}, function () {
// onError
});
authorize
関数は完全に非同期で、サーバーからの通知を受け取るためのいくつかのコールバック関数をサポートしています。
-
onGrant
: 関数の第1引数。認可が成功し、サーバーが要求されたパーミッションでRPTを返した場合、コールバックはRPTを受け取ります。 -
onDeny
: 関数の第2引数。サーバーがリクエストを拒否した場合にのみ呼び出されます。 -
onError
: 関数の第3引数。サーバーが予期せず応答する場合にのみ呼び出されます。
ほとんどのアプリケーションは、 onGrant
コールバックを使用して401応答後にリクエストをリトライする必要があります。以降のリクエストには、RPTをリトライのためのベアラー・トークンとして含める必要があります。
エンタイトルメントの取得
keycloak-authz.js
ライブラリーは、クライアントがアクセスしたいリソースとスコープを提供することによって、サーバーからRPTを取得するために使用できる entitlement
関数を提供します。
authorization.entitlement('my-resource-server-id').then(function (rpt) {
// onGrant callback function.
// If authorization was successful you'll receive an RPT
// with the necessary permissions to access the resource server
});
authorization.entitlement('my-resource-server', {
"permissions": [
{
"id" : "Some Resource"
}
]
}).then(function (rpt) {
// onGrant
});
entitlement
を使用する場合は、アクセスするリソースサーバーの client_id を指定する必要があります。
entitlement
関数は完全に非同期で、サーバーからの通知を受け取るためのコールバック関数をいくつかサポートしています。
-
onGrant
: 関数の第1引数。認可が成功し、サーバーが要求されたパーミッションでRPTを返した場合、コールバックはRPTを受け取ります。 -
onDeny
: 関数の第2引数。サーバーがリクエストを拒否した場合にのみ呼び出されます。 -
onError
: 関数の第3引数。サーバーが予期せず応答する場合にのみ呼び出されます。
認可リクエスト
authorize
と
の両方の関数は、認可リクエスト・オブジェクトを受け入れます。このオブジェクトは、次のプロパティーで設定できます。entitlement
-
permissions
リソースとスコープを表すオブジェクトの配列。以下に例を示します。
const authorizationRequest = { "permissions": [ { "id" : "Some Resource", "scopes" : ["view", "edit"] } ] }
-
metadata
サーバーで認可リクエストをどのように処理するかを定義したプロパティーを持つオブジェクト。
-
response_include_resource_name
リソース名をRPTのパーミッションに含めるかどうかをサーバーに示すブール値。falseの場合、リソース識別子のみが含まれます。
-
response_permissions_limit
RPTが持つことができるパーミッションの量の限界を定義する整数N。
rpt
パラメーターと一緒に使用すると、最後に要求されたN個のパーミッションだけがRPTに保持されます。
-
-
submit_request
サーバーがリソースとパーミッション・チケットによって参照されるスコープへのパーミッション・リクエストを作成する必要があるかどうかを示すブール値。このパラメーターは、UMA認証プロセスの一部として
ticket
パラメーターとともに使用されるときにのみ有効になります。
TLS/HTTPSの設定
サーバーでHTTPSを使用する場合は、アダプターが次のように設定されていることを確認してください。
{
"truststore": "path_to_your_trust_store",
"truststore-password": "trust_store_password"
}
上記の設定により、認可クライアントでTLS/HTTPSが有効になり、HTTPSスキームを使用してリモートからKeycloakサーバーにアクセスできるようになります。
Keycloakサーバーのエンドポイントにアクセスする際は、TLS/HTTPSを有効にすること強くお勧めします。 |