前回のエントリはこちらです。
OpenID Connect Core draft 01の内容をななめ読み
今日はOpenID Connect Artifact Binding 1.0のDraftを読んでみました。
これまでの経緯
を書くことを忘れていました。
- 去年からずーっとOAuth 2.0の策定が進んでいる
- そんな中、OpenIDをOAuth 2.0のフローに乗せたOpenID Connectが突然提案された
- 一方で、既存のOpenID Auth 2.0の問題である大量のリクエストパラメータをなんとかするためのArtifact Bindingも検討され、提案された
- OAuth 2.0との連携など、方向性はだいたい同じなのに別々に仕様策定が進んでいた2つの仕様だが、話し合いにより良い具合に一緒に進められることに
- 仕様のScopeをいくつかにわけて、仕様を書きなおし!
- 今回はCore, ABから。←イマココ Discovery, Dynamic Registration, UA Bindingはこれから。
- ソースはここ→ openid / ab — Bitbucket
では見ていきましょう。
注意ですが、これは翻訳ではないので、OpenID Auth 2.0、OAuth 2.0 Draft、OpenID Connect Core 1.0 Draftの用語がごちゃごちゃでごめんなさい。
Abstract
Terminology
OpenID Connect Core 1.0で登場したものに加えて、以下の用語も加えられています。
- Artifact : 大きなデータ(ここではAssertion)へのリファレンスとなる短い文字列
- Request File : OpenID Connect Core 1.0のリクエストパラメータのJSON構造体
- Request URI : OP(AuthZ Server)によってアクセス可能なRequest Fileの位置を示すURL
- Request Registration Endpoint : RP(Client)がOP(AuthZ Server)にRequest Fileを登録してRequest URIを取得するために、OP(AuthZ Server)が提供するHTTPSのエンドポイントURL
OpenID Auth 2.0ではGET/POSTパラメータで大量のパラメータがやりとりされます。
これが日本の携帯だときついとかいう話があるので、Request FileとそのポインタであるRequest URIを用いてパラメータをやりとりしてしまおうということですね。
Assertionもリダイレクトパラメータではなく、OAuth 2.0のAccess Tokenを取得するタイミングでやりとりすることでパラメータをおさえましょうと。
Request FileはClientが用意する場合、AuthZ Serverに登録する場合も考えられています。
詳しくはあとで説明があります。
Protocol Flows
- RP(Client)は全てのリクエストパラメータを含むJSON形式のRequest Fileを作成
- RP(Client)はRequest FileのURL(Request URI)を取得
- RP(Client)はHTTPSリダイレクトでOP(AuthZ Server)にリクエストを送る
- OP(AuthZ Server)はRequest Fileを取得
- OP(AuthZ Server)はエンドユーザーを認証
- OP(AuthZ Server)はエンドユーザーの同意/認可を取得
- OP(AuthZ Server)はエンドユーザーをRP(Client)に送り返す
- RP(Client)はArtifact(AuthZ code)を用いてAssertionを要求
- RP(Client)はレスポンスボディでAssertionを受け取る
- (オプション)RP(Client)はUserinfo Endpointにアクセス
- (オプション)RP(Client)はUserinfoのレスポンスを受け取る
メッセージを受け取る際は、OpenID Connect Core 1.0で定義されている検証を行いましょうと。
Client prepares a Request File
OpenID Connect Core 1.0の仕様に定義されているリクエストパラメータをJSONのオブジェクトとしてまとめておきます。
"scope"はもちろん"openid"を含み、"openid"の下にOpenID関連のパラメータを並べます。
ABのフローではOAuth 2.0のAuthZ CodeとしてArtifactを受け取るために、"response_type"は"code"にします。
Client Obtains the URL of the Request File
ABを利用するとき、RP(Client)はWebServerとして機能しています。
上で作成したRequest Fileを自分自身や管理下にあるサーバで保持し、そのURLを利用することができます。
また、オプションとして、OP(AuthZ Server)がこのファイルを登録させてURLを返すという形もありえます。
以前のABのSpecにはこのあたりも仕様として書かれていた記憶がありますので、今後追加されるか別途定義されるのではないでしょうか。
Client sends a request to Authorization Server via HTTPS redirect
RP(Client)はOP Endpoint(AuthZ ServerのUser AuthZ Endpoint)に以下のパラメータをつけてリダイレクトさせます。
- response_type : 必須。 "token"とありますがたぶん"code"ですこれ
- request_uri : 必須。上で取得したRequest FileのURIを指定
- immediate : オプション。OpenID Auth 2.0のimmediateモードを利用するかどうかのフラグ。この値はRequest Fileの値を上書く
- claimed_id : オプション。OpenID Auth 2.0のclaimed_idパラメータの値。この値はRequest Fileの値を上書く
- state : オプション。説明省略
UXの観点からOpenID Auth 2.0ではclaimed_idに"http://specs.openid.net/auth/2.0/identifier_select"ばっかりが利用されていますが、自分のOpenIDを指定した場合はここに値が入ってきますね。
あと、immediateとclimed_idの値を上書きできるのは素晴らしいですね。
上書きができない場合、例えばOpenIDを知っているユーザーとOPを選択したユーザー、初回アカウント登録時のsetupモードとアカウント再確認のためのimmediateモードのときなど、内容が微妙に異なるRequest Fileをたくさん用意する必要があります。
この仕様であればベースとなるRequest Fileを使いまわせるので、便利ですね。
Authorization Server fetches the Request File
OP(AuthZ Server)はrequest_uriパラメータに指定されたRequest Fileを取得して解析します。
Authorization Server Authenticates the End-User
Request Fileにエンドユーザーの識別子が指定されていた場合、AuthZ Serverはマッチするユーザーを認証しなければなりません。
細かいことですが、OpenID Auth 2.0でOPによってclaimed_idが指定された時の実装は微妙にばらばらなのではないかと思ったことがありましたがどうだったっけ・・・。
Authorization Server Obtains the End-User Consent/Authorization
この同意/認可を得るAuthZ Serverと上のユーザー認証を行うサーバーが別でも良いですよと。
まぁ、特におかしなことは言っていませんね。
Authorization Server Sends the End-User back to the Client
Positive or NegativeなAssertionと関連づけられたArtifact Codeを作成し、redirect_uriパラメータで指定されたRP Endpointにユーザーを戻します。
今のOAuthやOpenIDだと、Negative Assertionなんてイラネって思って自分とこのTOPページにもってっちゃうOP/SPもあると思うので、この辺は厳密に決まってるほうが良いですね。
End-user Grants Authorization
レスポンスはこんな感じ。
- code : 必須。Artifactの値
- state : リクエストで指定された値があれば必須
- server_id : OP(AuthZ Server)の識別子
End-User Denies Authorization or Invalid Request FIle
ユーザーが拒否した場合やRequest Fileが無効だった場合もレスポンスは返す。
Client requests Assertion using the Artifact ("code")
ABでは、Access Tokenを取得するタイミングでOpenIDのアサーションを要求します。
- grant_type : 必須 "authorization_code"
- code : 必須 受け取ったArtifact
- client_id : 必須 RPの識別子
- client_secret : オプション 説明省略
- secret_type : オプション 説明省略
Client receives Assertion in the response body
OP(AuthZ Server)はポジティブ/ネガティブなアサーションを返します。
Positive Assertion
Connect Core 1.0に書いてある内容と同じ。
Requesting Userinfo
あれ?
OpenID Connect Core 1.0ではこのリクエストがAccess Tokenを用いたリソースアクセスになっていたと思いますが、ここではArtifactを利用したリクエストになっていますね。
どっちがいいんだろうか。
Userinfo Endpointを属性APIとして何度も利用するならばAccess Token、アサーションの一部として扱うのであればArtifactでのリクエストになるのかもしれませんが、管理上、Token Endpoint以外でArtifactは扱いたくありませんね。
まとめ
User Agent Bindingについて
@_natさんから書いてみないかとお誘いをいただいているのでちょっと考え中。
Assertionの受け取り部分以外はこのABのSpecと同じでいけるかな。。。
次に読む仕様
むむ @oauthjp が必見といってるので、連休中に読んでみましょうか。 http://fb.me/UNTZ7MM5
http://twitter.com/ritou/status/35490592876269568
ということで、これを読みます。
draft-zeltsan-oauth-use-cases-01 - OAuth Use Cases