OAuth 2.0 リソース・サーバとしての InterSystems IRIS Web アプリケーションの使用法
このページでは、OAuth 2.0 フレームワークを使用するリソース・サーバとして InterSystems IRIS® の Web アプリケーションを使用する方法について説明します。
このページでは、リソース・サーバが承認サーバのイントロスペクション・エンドポイントを使用するシナリオについて主に説明します。バリエーションの詳細は、前のセクションを参照してください。
JWT の署名、暗号化、シグニチャの検証、および解読に使用するキーの回転のプロセスについては別途説明します。
InterSystems IRIS リソース・サーバの前提条件
このページに記載されているタスクを開始する前に、以下のものが利用可能であることを確認します。
-
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 リソース・サーバは要求を受け取り、そこに含まれるアクセス・トークンを検証し、(そのアクセス・トークンに応じて) 要求された情報を返します。
InterSystems IRIS リソース・サーバを作成するには、リソース・サーバの Web アプリケーションが使用するネームスペースの %CSP.RESTOpens in a new tab のサブクラスを作成します。このクラスでは、URL マップおよび対応するメソッドを作成します。これらメソッドでは、以下を実行します。
-
%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
トークンの検証
アクセス・トークンを受け取ったリソース・サーバは、追加のチェックを実行して、要求されたリソースの使用に必要な権限をユーザが保有しているかどうかを確認します。この検証を実行するために、クライアントは、ここで説明するメソッドを使用して追加情報を取得することができます。
場所:このメソッドはクラス %SYS.OAuth2.ValidationOpens in a new tab にあります。
ClassMethod ValidateJWT(applicationName As %String,
accessToken As %String,
scope As %String,
aud As %String,
Output jsonObject As %RegisteredObject,
Output securityParameters As %String,
Output sc As %Status) As %Boolean
アクセス・トークンが (opaque トークンではなく) JWT である場合にのみこのメソッドを使用します。
このメソッドは JWT の復号化 (必要な場合) と検証を行い、オブジェクト (jsonObject) を作成して JWT プロパティを格納します。JWT を検証するために、このメソッドは、対象者 (aud が指定されている場合)、発行者エンドポイント (サーバ記述で指定されているものとの一致が必要)、スコープ (scope が指定されている場合) を確認します。このメソッドは、アクセス・トークンの有効期限が切れていないことも確認します。署名された JWT と署名されていない JWT の両方が許可されます。JWT が署名されている場合は、そのシグニチャを確認します。
このメソッドは JWT が有効な場合は 1 を返し、それ以外の場合は 0 を返します。さらに、複数の引数を出力として返します。
引数は以下のとおりです。
-
applicationName はクライアント・アプリケーションの名前です。
-
accessToken は検証される JWT です。
-
scope は、スペースで区切られたスコープのリストです。例えば、"scope1 scope2 scope3" のような形式をとります。
scope が指定されている場合は、このスコープを含むスコープ・クレームが JWT に含まれている必要があります。
-
aud は、このトークンを使用する対象者を指定します。トークンに関連付けられた aud プロパティがある場合 (通常、対象者はトークンの要求時に指定されているため)、aud はトークンの対象者と一致します。aud が指定されていない場合、対象者のチェックは行われません。
-
出力として返される jsonObject は、JWT のクレームを含むダイナミック・オブジェクトです。このダイナミック・オブジェクトには aud、exp、iss などのプロパティが含まれます。ダイナミック・オブジェクトの詳細は、"JSON の使用" を参照してください。
-
出力として返される securityParameters は、ヘッダから取得されたセキュリティ情報を含む多次元配列です。このセキュリティ情報は、シグニチャや復号化の検証で必要に応じて追加使用されます。
この配列には以下のノードがあります。
ノード 値 securityParameters("sigalg") シグニチャまたは MAC アルゴリズム。JWT が署名されている場合にのみ設定します。 securityParameters("keyalg") キー管理アルゴリズム securityParameters("encalg") コンテンツ暗号化アルゴリズム keyalg と encalg のノードは、両方が指定されるか、両方が Null になります。
-
出力として返される sc には、このメソッドが設定したステータス・コードが含まれます。
このメソッドが成功 (1) を返す場合は、jsonObject を検証し、必要に応じて含まれているクレームを使用して、要求されたリソースへのアクセスを許可するかどうかを決定します。 必要に応じて securityParameters を使用します。
Oauth 仕様では、アプリケーションは署名された JWT と署名されていない JWT の両方を受け入れることができるため、ValidateJWT メソッドは署名されていない JWT を拒否しません。ただし、多くの場合、署名されていない JWT を拒否して、アプリケーションにより厳しいセキュリティを実装することを強くお勧めします。メソッドから返された securityParameters 配列を調べることで、ValidateJWT に渡されたトークンが署名されていないかどうかを確認できます。securityParameters("sigalg") が設定されていない場合、トークンは署名されていません。例えば、以下のコードは、トークンが署名されていないかどうかを判断し、署名されていない場合は拒否します。
Set tInitialValidationPassed = ##class(%SYS.OAuth2.Validation).ValidateJWT(tClientName, tAccessToken, "", "", .tJsonObj,.tSecurityParams, .tValidateStatus)
// the “sigalg” subscript is set only if the JWT was signed
Set tIsTokenSigned = $Data(tSecurityParams("sigalg"))#2
If 'tIsTokenSigned {
$$$ThrowStatus($System.Status.Error($$$AccessDenied))
}
場所:このメソッドはクラス %SYS.OAuth2.AccessTokenOpens in a new tab にあります。
ClassMethod GetIntrospection(applicationName As %String,
accessToken As %String,
Output jsonObject As %RegisteredObject) As %Status
このメソッドはアクセス・トークンをイントロスペクション・エンドポイントへ送信し、クレームを含む応答を受信し、このエンドポイントが返したクレームを含むオブジェクト (jsonObject) を作成します。
要求は、client_id と client_secret が applicationName に関連付けられている、基本的な承認 HTTP ヘッダによって承認されます。
引数は以下のとおりです。
-
applicationName はクライアント・アプリケーションの名前です。
-
accessToken はアクセス・トークンです。
-
出力として返される jsonObject は、イントロスペクション・エンドポイントが返したクレームを含むダイナミック・オブジェクトです。ダイナミック・オブジェクトの詳細は、"JSON の使用" を参照してください。
サーバでイントロスペクション・エンドポイントが指定されていない場合や、[クライアント秘密鍵] が指定されていない場合は、このメソッドを使用できません。
このメソッドが成功 (1) を返す場合は、jsonObject を検証し、必要に応じて含まれているクレームを使用して、要求されたリソースへのアクセスを許可するかどうかを決定します。
バリエーション
このページでは、InterSystems IRIS リソース・サーバが承認サーバのイントロスペクション・エンドポイントを使用するシナリオについて主に説明します。このセクションでは、使用可能ないくつかのバリエーションについて説明します。
バリエーション:リソース・サーバによる Userinfo エンドポイントの呼び出し
リソース・サーバは Userinfo エンドポイントを呼び出すこともできます。そのためには、OAuth クライアントの場合と同様に、リソース・サーバのコードで GetUserinfo() メソッドを使用する必要があります。
バリエーション:リソース・サーバでエンドポイントを呼び出さない
InterSystems IRIS リソース・サーバが承認サーバのエンドポイントを使用しない場合は、このマシンで OAuth 2.0 構成を作成する必要はありません。
さらに、リソース・サーバが GetAccessTokenFromRequest() を使用する必要はありません。代わりに、リソース・サーバは HTTP 承認ヘッダからアクセス・トークンを直接取得し、必要に応じて使用することができます。