一通りの動作確認を終え、UMA方式の挙動を理解できたでしょうか?
以降では、UMA方式を動かすに当たっての各アクターの主要な設定を確認していきます。設定の解説に先立って、各アクターで必要となる設定や実装の概要をあらためて記載しておきます。
・Keycloak(認可サーバ)
UMA機能の有効化
リソースサーバのクライアントの設定(認可の有効化)
リソースサーバ上のリソースに対し、リソースオーナーからのアクセス
だけを許可する認可設定
・Webアプリ(クライアント)
Webアプリのアダプター(JavaScriptアダプター)の設定
RPTを取得/パーミッション申請の実装方法
・APIサービス(リソースサーバ)
APIサービスのアダプター(Tomcatアダプター)の設定
Keycloakへリソース情報を登録/削除する際の実装方法
まずは、Keycloak管理コンソール(http://sso.example.com/auth/admin/)にアクセスし、Keycloak管理者(admin)でログインして、「Demo-authz」レルムの「レルムの設定」を確認します(画面16)。UMA方式を利用するためには、「User-Managed Access」が「オン」になっている必要があります。
「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のポリシーが適用される動きになります。
この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 }
パラメーター名 | 必須 | 説明 |
---|---|---|
realm | ○ | クライアントが定義されているレルム名を指定 |
auth-server-url | ○ | 認可サーバURLを指定 |
ssl-required | SSLが必須かどうかを指定 今回はHTTPでアクセスを許可しているため、noneを指定 本番環境では決してこのパラメーターをnoneにしてはいけません |
|
resource | ○ | クライアント名を指定 |
public-client | パブリッククライアントの場合は、trueを設定 | |
表8 JavaScriptアダプターの設定 |
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.