OAuth 2.0 リソース・サーバとしての Caché Web アプリケーションの使用法
この章では、OAuth 2.0 フレームワークを使用するリソース・サーバとして Caché Web アプリケーションを使用する方法について説明します。以下の項目について説明します。
この章では、リソース・サーバが承認サーバのイントロスペクション・エンドポイントを使用するシナリオについて主に説明します。バリエーションの詳細は、前のセクションを参照してください。
JWT の署名、暗号化、シグニチャの検証、および解読に使用されるキーの回転については、前の章を参照してください。
Caché リソース・サーバの前提条件
この章に記載されているタスクを開始する前に、以下のものが利用可能であることを確認します。
-
OAuth 2.0 承認サーバ。
-
リソース・サーバが承認サーバのエンドポイントを使用する場合は、そのリソース・サーバを OAuth 2.0 承認サーバのクライアントとして登録することができます。詳細は、承認サーバの実装環境によって異なります。
この場合は、後でこのサーバの具体的な詳細情報も必要になります。
-
承認サーバの場所 (発行者エンドポイント)
-
トークン・エンドポイントの場所
-
Userinfo エンドポイントの場所 (サポートされている場合。OpenID Connect CoreOpens in a new tab を参照)
-
トークン・イントロスペクション・エンドポイントの場所 (サポートされている場合。RFC 7662Opens in a new tab を参照)
-
トークン取り消しエンドポイントの場所 (サポートされている場合。RFC 7009Opens in a new tab を参照)
-
承認サーバによるダイナミック登録のサポートの有無
-
-
承認サーバがダイナミック登録をサポートしない場合、リソース・サーバのクライアント ID およびクライアント秘密鍵が必要です。承認サーバがこの 2 つの情報を生成します (1 回限り)。ユーザは、この情報をリソース・サーバ・マシンへ安全に伝える必要があります。
構成要件
前の章の “構成要件” を参照してください。クライアント構成の作成手順に以下の変更を加えます。
-
[アプリケーション名] にはリソース・サーバのアプリケーション名を指定します。
-
[クライアント・タイプ] には [リソース・サーバ] を指定します。
[リソース・サーバ] をタイプとして指定した場合、構成ページにはリソース・サーバに適用されるオプションのみが表示されることに注意してください。
-
[ClientID] にはリソース・サーバのクライアント ID を使用します。
-
[clientSecret] にはリソース・サーバのクライアント秘密鍵を使用します。
コード要件
OAuth 2.0 リソース・サーバは要求を受け取り、そこに含まれるアクセス・トークンを検証し、(そのアクセス・トークンに応じて) 要求された情報を返します。
Caché リソース・サーバを作成するには、リソース・サーバの Web アプリケーションが使用するネームスペースの CSP ページを作成します。(このページではコールバック・メソッドを定義する必要があるだけであり、このページはユーザには表示されないため、Zen や Zen Mojo を使用する必要はありません。)具体的には %CSP.RESTOpens in a new tab のサブクラスを作成することをお勧めします。
この CSP ページで OnPage() メソッドを実装します。(または、%CSP.RESTOpens in a new tab のサブクラスを作成済みの場合は、URL map とその対応するメソッドを作成します。)
OnPage() メソッド (または該当する REST メソッド) で以下の手順を実行します。
-
%SYS.OAuth2.AccessTokenOpens in a new tab の GetAccessTokenFromRequest() メソッドを呼び出します。このメソッドは、以下のとおりです。
ClassMethod GetAccessTokenFromRequest(Output sc As %Status) As %String
このページが受信した HTTP 要求にアクセス・トークンがある場合、メソッドはそれを返します。RFC 6750Opens in a new tab にある 3 つのフォーマットの 1 つが使用されます。出力として返されるパラメータ sc は、エラー検出の有無を示すステータス・コードです。要求で SSL/TLS を使用しなかった場合はエラーが発生します。さらに、要求に有効なベアラー・ヘッダが含まれていなかった場合にもエラーが発生します。
-
ステータス・コードがエラーであるかどうかを確認します。
ステータスがエラーの場合、メソッドは適切なエラーを返します (要求された情報は返しません)。
-
ステータス・コードがエラーでない場合は、アクセス・トークンを検証します。そのためには、ValidateJWT() を使用するか、独自のカスタム・メソッドを使用します。前の章の “メソッドの詳細” を参照してください。
-
必要に応じて、追加情報を得るために GetIntrospection() メソッドを呼び出します。このメソッドは承認サーバのイントロスペクション・エンドポイントを呼び出し、アクセス・トークンに関するクレームを取得します。このメソッドは、以下のとおりです。
ClassMethod GetIntrospection(applicationName As %String, accessToken As %String, Output jsonObject As %RegisteredObject) As %Status
引数は以下のとおりです。
-
applicationName はクライアント・アプリケーションの名前です。
-
accessToken は以前に返されたアクセス・トークンです。
-
出力として返される jsonObject は、承認サーバがこのアクセス・トークンに関して作成したクレームを含む JSON オブジェクトです。
-
-
情報に対するユーザの要求を認可すべきであることを前述の手順が示している場合は、要求された処理を実行し、要求された情報を返します。
以下に例を示します。
// This is a dummy resource server which just gets the access token from the request
// and uses the introspection endpoint to ensure that the access token is valid.
// Normally the response would not be security related, but would ocntain some interesting
// data based on the request parameters.
set accessToken=##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.sc)
if $$$ISOK(sc) {
set sc=##class(%SYS.OAuth2.AccessToken).GetIntrospection("demo resource",accessToken,.jsonObject)
if $$$ISOK(sc) {
write "OAuth 2.0 access token used to authorize resource server (RFC 6749)<br>"
write "Access token validated using introspection endpoint (RFC 7662)<br>"
write " scope='"_jsonObject.scope_"'<br>"
write " user='"_jsonObject.username_"'",!
} else {
write "Introspection Error="_..EscapeHTML($system.Status.GetErrorText(sc)),!
}
} else {
write "Error Getting Access Token="_$system.Status.GetErrorText(sc),!
}
Quit $$$OK
バリエーション
この章では、Caché リソース・サーバが承認サーバのイントロスペクション・エンドポイントを使用するシナリオについて主に説明します。このセクションでは、使用可能ないくつかのバリエーションについて説明します。
バリエーション:リソース・サーバによる Userinfo エンドポイントの呼び出し
リソース・サーバは Userinfo エンドポイントを呼び出すこともできます。そのためには、前の章で説明した GetUserinfo() メソッドをリソース・サーバのコードで使用する必要があります。
バリエーション:リソース・サーバでエンドポイントを呼び出さない
Caché リソース・サーバが承認サーバのエンドポイントを使用しない場合は、このマシンで OAuth 2.0 構成を作成する必要はありません。
さらに、リソース・サーバが GetAccessTokenFromRequest() を使用する必要はありません。代わりに、リソース・サーバは HTTP 承認ヘッダからアクセス・トークンを直接取得し、必要に応じて使用することができます。