連載
» 2019年12月11日 05時00分 公開

Keycloak超入門(最終回):Keycloakで認可サービスを試してみよう[後編] (2/3)

[和田広之, 相田洋志, 田村広平, 上田直樹, 青柳隆,野村総合研究所/野村総合研究所/フリーランス/株式会社リック/フリーランス]

設定と実装の確認

 一通りの動作確認を終え、UMA方式の挙動を理解できたでしょうか?

 以降では、UMA方式を動かすに当たっての各アクターの主要な設定を確認していきます。設定の解説に先立って、各アクターで必要となる設定や実装の概要をあらためて記載しておきます。

・Keycloak(認可サーバ)
   UMA機能の有効化
   リソースサーバのクライアントの設定(認可の有効化)
   リソースサーバ上のリソースに対し、リソースオーナーからのアクセス
   だけを許可する認可設定

・Webアプリ(クライアント)
   Webアプリのアダプター(JavaScriptアダプター)の設定
   RPTを取得/パーミッション申請の実装方法

・APIサービス(リソースサーバ)
   APIサービスのアダプター(Tomcatアダプター)の設定
   Keycloakへリソース情報を登録/削除する際の実装方法


Keycloak(認可サーバ)の設定

●レルムの設定

 まずは、Keycloak管理コンソール(http://sso.example.com/auth/admin/)にアクセスし、Keycloak管理者(admin)でログインして、「Demo-authz」レルムの「レルムの設定」を確認します(画面16)。UMA方式を利用するためには、「User-Managed Access」が「オン」になっている必要があります。

画面16 画面16 レルムの設定

●UMA方式に関連するクライアント設定

 「Demo-authz」レルムの「クライアント」には、後述するクライアントアダプターの設定と対応する「authz-uma-api」(リソースサーバ)と「authz-uma-client」(クライアント)の2つのクライアントを登録しておく必要があります。ここでは、UMA方式を利用する上で特徴的な設定が必要な「authz-uma-api」のクライアント設定についてのみ解説します。

 「Demo-authz」レルムの「クライアント」から「authz-uma-api」を選択し、以下の表4〜7の設定意図を確認します。UMAのリソースサーバはOAuthのクライアントでもあるため、Keycloakにはクライアントとして登録します。UMAのリソースサーバが他のOAuthのクライアントと異なるのは、スコープ「uma_protection」を必要とすることです。表4の「認可の有効」をオンにすると、「uma_protection」ロールが付与されてProtection APIを利用できるようになります。また、設定ページのタブが増えてきめ細かな認可の制御ができるようになります。ただ、集中管理方式とは異なり、リソースは動的に追加されていくため、管理者としての設定はあまりありません。

タブ 設定項目 設定値 設定意図
設定 認可の有効 オン 認可サービスを利用するために必要
表4 「設定」タブ

名前 uris 設定意図
Default Resource /* ※デフォルトで作成されているリソース
表5 「認可」→「リソース」タブ

名前 タイプ 設定項目 設定値 設定意図
Default Policy js コード JavaScriptコード(割愛) 特に条件なくアクセスを許可する設定
※デフォルトで作成されているポリシー
Owner Only js コード JavaScriptコード(割愛) リソースオーナーのみアクセスを許可する設定
表6 「認可」→「ポリシー」タブ

名前 タイプ リソースタイプ ポリシー 設定意図
Default Permission resource urn:authz-uma-api:resources:default Default Policy ※デフォルトで作成されているパーミッション(認証済みであれば許可される)
Item Permission resource urn:authz-uma-api:resources:item Owner Only 指定したリソースタイプとOwner Onlyを関連付ける設定
表7 「認可」→「アクセス権」タブ

 パーミッションを「リソースタイプ」で設定すると、複数のリソースをまとめて同一のパーミッションに設定できます。後述しますが、UMA方式でKeycloakにリソースを作成する際に、「urn:authz-uma-api:resources:item」というリソースタイプで作成するようにします。こうすることで、当該リソースが自動的にOwner Onlyのポリシーが適用される動きになります。


Webアプリ(クライアント)の設定とソースコードの解説

●JavaScriptアダプター(keycloak.json)の設定

 このkeycloak.jsonで、JavaScriptアダプターの設定を行います。主な設定としては、第8回と同様、認可サーバのURLやレルム名、クライアント名が含まれます(表8)。この設定ファイルはエンドユーザーから参照できるパスに配置することになるため、秘匿情報(クライアントシークレットなど)を含めることはできません。このクライアントでは認可制御はなく、認証済みかどうかだけがチェックされる動きになります。

{
  "realm": "demo-authz",
  "auth-server-url": "http://sso.example.com/auth",
 "ssl-required" : "none", 
  "resource": "authz-uma-client",
  "public-client" : true
}
▲/usr/local/tomcat/webapps/authz-uma-client/keycloak.json
パラメーター名 必須 説明
realm クライアントが定義されているレルム名を指定
auth-server-url 認可サーバURLを指定
ssl-required SSLが必須かどうかを指定
今回はHTTPでアクセスを許可しているため、noneを指定
本番環境では決してこのパラメーターをnoneにしてはいけません
resource クライアント名を指定
public-client パブリッククライアントの場合は、trueを設定
表8 JavaScriptアダプターの設定

●RPTの取得処理、およびパーミッション申請処理の解説

 RPTの取得処理および、パーミッションの申請処理は、Webアプリ側のJavaScript(uma-client.jsのsubmit関数内)で行っています。Keycloakの認可クライアントJavaScript API(keycloak-authz.js)を利用することで、Keycloakとの通信部分(RPTの取得/パーミッション申請)に関しては処理を委譲できますが、それ以外の部分に関しては、アプリケーション側で実装する必要があります。

401: function(response, statusText) {
	// HTTPレスポンスヘッダに WWW-Authenticate : UMA ... が返ってきている場合は、以降の処理継続
	var wwwAuthenticateHeader = response.getResponseHeader('WWW-Authenticate');
	if (wwwAuthenticateHeader.indexOf('UMA') >= 0) {
		var params = wwwAuthenticateHeader.split(',');
		var ticket;
		// (1)WWW-Authenticateヘッダ内のticketパラメーターを取得
		for (i = 0; i < params.length; i++) {
			var param = params[i].split('=');
			if (param[0] == 'ticket') {
				ticket = param[1].substring(1, param[1].length - 1).trim();
				break;
			}
		}
		// (2)認可リクエストインスタンスを生成し、取得したticketを設定
		var authorizationRequest = {};
		authorizationRequest.ticket = ticket;
		// (3)パーミッション申請の有無を設定
		if (submitRequest) {
			authorizationRequest.submitRequest = submitRequest;
		} else {
			authorizationRequest.submitRequest = false;
		}
		// (4)認可サーバへ認可リクエスト送信
		authorization.authorize(authorizationRequest).then(function (rpt) {
		// パーミッション申請でなければ
			if (!submitRequest) {
		// (5)取得したRPTを使って当初のリクエストをリトライ
			submit(requestPath, method, rpt);
			}
		}, function () {
			// RPTが取得できない場合はアクセス権限がないので、401エラーをそのまま返す
			if (!submitRequest) {
				$(".resultConsole").text("<HTTPリクエスト>\n");
				$(".resultConsole").append(method + " " + requestUri + "\n\n");
				$(".resultConsole").append("<HTTPレスポンス>\n");
				$(".resultConsole").append("ステータス : 401 error\n");
				document.getElementById("resultMessage").value = "リソースの" + operationName[method] + "権限がありません";
			}
		}, function () {
			$('.resultConsole').text("リクエスト失敗!");
		});

(1)リソースへのアクセスで401応答が返ってきた場合は、HTTPヘッダの「WWW-Authenticate: UMA」というヘッダ内に、パーミッションチケットが戻ってきます。ここでは、ヘッダ内のticketパラメーター部分を抽出しています。

(2)認可リクエストインスタンスを生成して、ticket属性に(1)のパーミッションチケットを設定します。

(3)認可リクエストインスタンスのsubmitRequest属性により、RPT取得処理なのか、権限申請なのかを切り替えられます。RPT取得の場合は、submitRequest属性をfalseに、権限申請の場合は、trueに設定します。

(4)Keycloakの認可クライアントJavaScript APIを利用して、認可リクエストを送信します。当該ユーザーにリソースへのアクセス権があり、RPTが正常に取得できた場合、コールバック関数により、1番目のfunctionが呼び出されます。権限エラーの場合は、2番目のfunctionが呼び出されます。アクセス権がない場合/権限申請を行った場合のどちらも、こちらのfunctionが呼び出されます。3番目のfunctionは、サーバエラーなどの異常が発生した場合に呼び出されます。

(5)権限申請でない場合は、取得したRPTを使用して、当初のリソースへのアクセスをリトライします。適切なRPTを付与してリクエストを送信した場合には、アクセスが許可されます。


 認可クライアントJavaScript API(keycloak-authz.js)の利用方法については、こちらのページも併せてご参照ください。


Copyright © ITmedia, Inc. All Rights Reserved.

編集部からのお知らせ

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。