進捗は95%?OAuth 2.0 Draft 13の内容をざっくりまとめる

OAuth 2.0のDraft 13出ました。
draft-ietf-oauth-v2-13 - The OAuth 2.0 Authorization Framework

Facebookmixi Graph APIなどを使って開発されたことがある方は、OAuth 2.0 Draft 10の仕様はほぼ理解されていると思います。
Draft 10は単体である程度まとまった仕様として書かれていましたが、そのあとのDraft 11から構成の見直しなどが行われました。

もうそろそろ決まりそうだという噂があるので、今一度ざっくり最初からまとめ直していきます。
ただ、ClientやAuthorization Serverなど、基本的な説明は省略しています。
Draft 11以降に出てきた(と思われる)説明などを簡単にまとめたつもりです。

毎度のことながら、長いうえにこれは翻訳ではないので、厳密に調べたい方は原文を見てください。
あまりにも解釈間違っていそうな箇所があればご指摘をいただければと思います。

1. Introduction

既存のclient-server authenticationの問題と、OAuthだとどうなるかを説明しています。
詳細の説明は省略します。

1.1. Roles

登場人物と役割の説明です。
これもDraft 10までと変わりません。

  • resource owner
  • resource server
  • client
  • authorization server

詳細の説明は省略します。

1.2. Protocol Flow

Rolesとプロトコルフローですね。
ずっと前からありますけど、このAAみたいな説明って。。。
詳細の説明は省略します。

1.3. Access Token

Access Tokenの説明です。

前半は省略します。

大事なのは、後半の3,4行ぐらいですかね。
うまく一言で説明できませんが、一回Access Tokenに変換してResource Serverにアクセスすることで、Resouce Serverが色々な認証方法(例えば、basic認証と何と何と・・・)に対応しなくてもよくなり、Scopeなどの制限も可能になるということですね。
Access TokenはResource Serverのセキュリティ要件によって異なるフォーマット、構造、利用方法を持つことができるとあります。
7.1あたりで説明がありますが、この仕様ではAccess Tokenの詳細までは細かく定義されず、companion specificationsとして別で定義されていくことになります。

1.4. Authorization Grant

Authorization GrantはResource Owner/Server間の認可を抽象的に表す中間証明書的な一般用語です。(日本語おかしいな。。。)
Access Tokenを取得するために必要ですよと。ここでは、2種類のGrant Typeについての説明があります。

  • Authorization Code
  • implicit grant

Authorization Codeについて、ClientがResource OwnerのCredentialを扱うのではなく、Authorization Serverにユーザーを向けてそこで認証したあとにAuthorization Codeを受け取り、Access Tokenと交換します。
Authorization Codeを使うことにより、Clientが直接Resource OwnerのCredentialを扱うよりも安全ですね。

implicit grant ってのは、Authorization Codeを使わずに直接Access Tokenを返します。
少し前のDraftではUser-Agent Profileとか言われていたケースですね。呼び方が変わっています。

1.4.3. Resource Owner Password Credentials

Resource OwnerのIDやパスワードをauthorization grantとしてAccess Tokenを取得するために直接利用できます。
OAuth 1.0でいうxAuthの類です。basic認証と違うところは、最初にAccess Tokenに交換されるときだけ使いますよということですね。

1.4.4. Client Credentials

Resource Owner=clientの場合、Client Credentials(Client ID/Secret)をauthorization grantとして利用できます。
これは、2-legged OAuth とか言われていたフローに似ていますが、ここでも1回Access Tokenと交換したらOKだという点が違いますね。

1.4.5. Extensions

上記のgrant typesに加えて、OAuthと他のtrust frameworksをつなぐgrant typesを定義しても良いとあります。
MLなどで検討されている代表的なものは、SAMLとのつなぎですね。
下記の仕様では、SAML 2.0 bearer assertion grant typeが定義されていて、SAMLを使うシステムとOAuthを使うシステムを連携させることができます。

1.5. Refresh Token

Refresh Tokenの説明です。
詳細の説明は省略します。

2. Protocol Endpoints

このプロトコルで利用するエンドポイントは2つです。

  • Authorization endpoint
  • Token endpoint

とはいえ、上で説明したgrant typeの中にはこの2つのうち1つしか使わないものもあります。
Extension grant typeで他のframeworkとつなぐ場合などは他にエンドポイントが必要になるかもしれません。そういうのは別で定義されることになりますね。

2.1. Authorization Endpoint

Authorization Endpointの説明です。

  • ClientからResource Ownerをリダイレクトされ、最初に確認(認証)を行う。認証方法は仕様外
  • レスポンスがAccess Tokenを含む場合は、TSL 1.2必須で追加のトランスポートレイヤのメカニズムを利用してもよい
  • レスポンスがAccess Tokenを含まない場合は、TSL 1.2を使うべきで追加のトランスポートレイヤのメカニズムを利用してもよい
  • GETのサポートは必須、POSTをサポートしてもイイね!
  • 存在しないパラメータは省略扱いにしなければならない
  • 知らないパラメータは無視するべき
2.1.1. Redirection URI

詳細の説明は省略します。
ただ一点、オープンリダイレクタとして利用されないために、Authorization Serverは未登録や信頼しないURIにはリダイレクトさせずにResource Ownerにエラーを出すべき。
これは小さいことですが大事ですね。

2.2. Token Endpoint
  • Access Tokenを取得するためのエンドポイント
  • implict grant以外の全てのgrant typeで利用される
  • このURIはドキュメントなどに記載
  • トランスポート層のセキュリティメカニズムが必要。TLS 1.2が必須で、追加のトランスポートレイヤのメカニズムも利用して良い
  • セキュリティ要件を満たすClient認証を受け入れてよい
  • POSTのサポート必須
  • 存在しないパラメータは省略扱いにしなければならない
  • 知らないパラメータは無視するべき

3. Client Authentication

Crient CredentialはClientの特定/認証に用いられます。
Client Password Authenticationは共有秘密鍵を用いたClient認証です。

  • client_id : clientの識別子
  • client_secret : clientのパスワード

それ以外のClient Authenticationについても利用できるとありますが、細かく書かれていません。

4. Obtaining Authorization

やっとここまできた。。。ここに実際のリクエスト/レスポンスが書いてあります。
各grant type毎のAuthorization取得のフローの説明が書いてあります。

4.1. Authorization Code

Draft 10では"web server profile"として定義されていたフローです。

grant type : "Authorization Code" の対象であるClient

  • client credentialを安全に保存できる
  • ブラウザを用いたリダイレクトができる
  • Authorization Serverと直接通信が可能

フローは以下の通りです。

     +----------+
     | resource |
     |   owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)--- & Redirect URI ------>|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Client Credentials, --------'      |
     |         |          Authorization Code,                |
     | Client  |            & Redirect URI                   |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)


                     Figure 3: Authorization Code Flow

Authorization Requestは以下のパラメータを含む"application/x-www-form-urlencoded"形式のリクエストをauthorization endpoint URIに送信します。

  • response_type : "code"
  • client_id
  • redirect_uri
  • scope
  • state

サンプルリクエストはこちらです。

GET /authorize?response_type=code&client_id=s6BhdRkqt3&
         redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
     Host: server.example.com

Authorization Responseは以下のパラメータを含みます。

  • code
  • state

こちらも"application/x-www-form-urlencoded"形式です。
サンプルレスポンスはこちらです。

     HTTP/1.1 302 Found
     Location: https://client.example.com/cb?code=i1WsRn1uB1

エラーレスポンスは省略します。

Access Token Requestは以下のパラメータとClient Credentialを含む"application/x-www-form-urlencoded"形式のリクエストをtoken endpoint URIに送信します。

  • grant_type : "authorization_code"
  • code
  • redirect_uri
     POST /token HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded

     grant_type=authorization_code&client_id=s6BhdRkqt3&
     client_secret=gX1fBat3bV&code=i1WsRn1uB1&
     redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

このレスポンスは 5.1, 5.2あたりで説明されています。
成功するとAccess Token, Refresh Tokenなどが返されます。

     HTTP/1.1 200 OK
     Content-Type: application/json
     Cache-Control: no-store

     {
       "access_token":"SlAV32hkKG",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"8xLOxBtZp8",
       "example_parameter":"example-value"
     }

Draft 10の仕様と比べて、token_typeというパラメータが追加されています。
これがAccess Token Typesってもので、後で説明があります。
これはもっとも標準的なフローなので問題ないですね。

4.2. Implicit Grant

Draft 10では"user-agent profile"として定義されていたフローです。

grant type : "Implicit Grant" の対象であるClient

  • client secretを安全に保存できないJavaScriptやNativeのアプリケーション
  • ブラウザを用いたリダイレクトができる
  • フラグメント要素の値を扱える

フローは以下の通り。

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier     +---------------+
     |         -+----(A)--- & Redirect URI ----->|               |
     |  User-   |                                | Authorization |
     |  Agent  -|----(B)-- User authenticates -->|     Server    |
     |          |                                |               |
     |          |<---(C)---- Redirect URI ------<|               |
     |          |          with Access Token     +---------------+
     |          |            in Fragment
     |          |                                +---------------+
     |          |----(D)---- Redirect URI ------>|   Web Server  |
     |          |          without Fragment      |  with Client  |
     |          |                                |   Resource    |
     |     (F)  |<---(E)------- Script ---------<|               |
     |          |                                +---------------+
     +-|--------+
       |    |
      (A)  (G) Access Token
       |    |
       ^    v
     +---------+
     |         |
     |  Client |
     |         |
     +---------+


                       Figure 4: Implicit Grant Flow

Authorization Requestは以下のパラメータを含む"application/x-www-form-urlencoded"形式のリクエストをauthorization endpoint URIに送信します。

  • response_type : "token"
  • client_id
  • redirect_uri
  • scope
  • state

サンプルリクエストはこちらです

GET /authorize?response_type=token&client_id=s6BhdRkqt3&
         redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
     Host: server.example.com

この後、ユーザー認証/認可の取得を行い、リダイレクトのレスポンスにAccess Tokenを含みます。
Access Token Responseは以下のパラメータをフラグメントとして付加した"application/x-www-form-urlencoded"形式となります。

  • access_token
  • token_type
  • expires_in
  • scope
  • state
     HTTP/1.1 302 Found
     Location: http://example.com/rd#access_token=FJQbwq9&
               token_type=example&expires_in=3600

エラーレスポンスは省略します。

4.3. Resource Owner Password Credentials

ユーザーのID/PWを利用してAccess Tokenを取得するフローの説明です。
grant type : "Resource Owner Password Credentials" の対象であるClient

  • ユーザーのcredentialを取得できる
  • Authorization Serverと直接通信が可能

フローは以下の通りです。

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          v
          |
         (A) Password Credentials
          |
          v
     +---------+                                  +---------------+
     |         |          Client Credentials      |               |
     |         |>--(B)---- & Resource Owner ----->|               |
     | Client  |         Password Credentials     | Authorization |
     |         |                                  |     Server    |
     |         |<--(C)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+


            Figure 5: Resource Owner Password Credentials Flow

Authorization endpointを利用せずに、直接Token EndpointにAccess Tokenを要求します。
Access Token Requestは以下のパラメータとClient Credentialを含む"application/x-www-form-urlencoded"形式のリクエストをtoken endpoint URIに送信します。

  • grant_type : "password"
  • username
  • password
  • scope

サンプルリクエストはこちらです。

     POST /token HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded

     grant_type=password&client_id=s6BhdRkqt3&
     client_secret=47HDu8s&username=johndoe&password=A3ddj3w

Access Token ResponseはAuthorization Codeの場合と同様です。

     HTTP/1.1 200 OK
     Content-Type: application/json
     Cache-Control: no-store

     {
       "access_token":"SlAV32hkKG",
       "token_type":"example",
       "expires_in":3600,
       "refresh_token":"8xLOxBtZp8",
       "example_parameter":"example-value"
     }
4.4. Client Credentials

Client CredentialのみでAccess Tokenを取得するフローの説明です。
Draft 10では"Autonomous clients "として説明されていたフローの一つです。

フローは以下の通りです。

     +---------+                                  +---------------+
     |         |                                  |               |
     |         |>--(A)--- Client Credentials ---->| Authorization |
     | Client  |                                  |     Server    |
     |         |<--(B)---- Access Token ---------<|               |
     |         |    (w/ Optional Refresh Token)   |               |
     +---------+                                  +---------------+


                     Figure 6: Client Credentials Flow

Authorization endpointを利用せずに、直接Token EndpointにAccess Tokenを要求する。
Access Token Requestは以下のパラメータとClient Credentialを含む"application/x-www-form-urlencoded"形式のリクエストをtoken endpoint URIに送信します。

  • grant_type : "client_credentials"
  • scope
     POST /token HTTP/1.1
     Host: server.example.com
     Content-Type: application/x-www-form-urlencoded

     grant_type=client_credentials&client_id=s6BhdRkqt3&
     client_secret=47HDu8s

Access Token ResponseはAuthorization Code, Resource Owner Password Credentialsの場合と同様です。

4.5. Extensions

上記に含まれないフローをExtentionsとして利用可能です。
extension grant typeのときは、grant_typeパラメータに絶対URIを指定します。
必要に応じてパラメータを追加します。

サンプルはこちらです。

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=http%3A%2F%2Foauth.net%2Fgrant_type%2Fassertion%2F
saml%2F2.0%2Fbearer&assertion=PEFzc2VydGlvbiBJc3N1ZUluc3RhbnQ
[...omitted for brevity...]V0aG5TdGF0ZW1lbnQ-PC9Bc3NlcnRpb24-

こうやってExtensionとして新しいGrant Typeを受け入れられるようになっていれば、あとからユースケースと実装方法が出てきたときに「OAuth 2.0って○○のときつかえねーじゃん」って言われなくなりますね。

5. Issuing an Access Token

Token Endpointが返すAccess Token発行レスポンスの説明です。

5.1. Successful Response

成功レスポンスの説明です。
200 (OK) + JSONを返します。
詳細の説明は省略します。

5.2. Error Response

エラーレスポンスの説明です。
HTTP 400 (Bad Request)+JSONを返します。
詳細の説明は省略します。

6. Refreshing an Access Token

Access Tokenの更新方法の説明です。
リクエストパラメータは以下の3つとclient credentialです。

  • grant_type : "refresh_token"
  • refresh_token :
  • scope : 更新後のAccess Tokenに求めるScope

client credentialにclient_id/client_secretを用いた場合のサンプルです。

POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&client_id=s6BhdRkqt3&
client_secret=8eSEIpnqmM&refresh_token=n4E9O119d

レスポンスは5.1/5.2と同じです。
Authorization ServerはRefresh Tokenを更新しても良いし、そのままでも問題ありません。

7. Accessing Protected Resources

clientはresource serverにAccess Tokenを提出することで保護されたリソースにアクセスします。
resource serverはAccess TokenがExpireとScooeの有効性を必ず確認します。

Access Tokenの使い方はTypeに依存します。
一般的には、Access Token Typesの仕様のAuthentication Scemeに従ったHTTP "Authorization" Request Headerを使う必要があります。

あえて、Access Tokenの詳細まではこの仕様では定義しません。

7.1. Access Token Types

Access Token Typeは、clientが保護リソースにうまくアクセスするためのAccess Tokenの使い方をそのType特有の属性とともに提供します。
ここでは2つの例が示されています。

1つ目はtoken type : "bearer"です。
これが、最初から提案されていた"Token SecretなしのAccess Tokenのみのリクエスト"を送る際の「Access Tokenの使い方」ということになります。

GET /resource/1 HTTP/1.1
Host: example.com
Authorization: BEARER h480djs93hd8

詳細はこちらの仕様で定義されています。 draft-ietf-oauth-v2-bearer-02 - The OAuth 2.0 Authorization Framework: Bearer Token Usage
これもあとで読みましょう。

もう1つが、token type : "mac" です。
これは以前読んで紹介した内容です。
OAuth 2.0 draft 12で出てきたMAC Tokenとは - r-weblife

GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC token="h480djs93hd8",
                   timestamp="137131200",
                   nonce="dj83hs9s",
                   signature="kDZvddkndxvhGRXZhvuDjEWhGeE="

Access Token, Access Token SecretからSignatureを作成してリクエストを作成する方法が定義されています。
http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-02

"mac" tokenで署名作成に利用されるToken SecretはAccess TokenとともにClientに渡されるわけなので、リソースアクセス以外の部分も各Typesの仕様に含まれるということになります。

8. Extensibility

訳すと"拡張性"となりますが、このOAuth 2.0の仕様に書かれているリクエスト、レスポンスが全てのユースケースに対応しているというわけではありません。
基本的な流れや制約はこの仕様で定義されていますが、下記の項目については、拡張性を持たせることで、様々なユースケースに対応できるようにしていると思われます。

  • Access Token Types
  • New Endpoint Parameters
  • New Authorization Grant Types

といっても、自由すぎてはOAuth 1.0のときのようになってしまうため、説明があります。

8.1. Defining Access Token Types

Access Token Typesは2種類の定義方法があります。

(2)については、一般的な使われ方ではない"vendor-specific implementations"に限られるべきとあります。
一般的な使い方ならレジストリに登録して偉い人のお墨付きをもらってみんなで使いましょうよと。

(1)については、10.1で説明がありますが、ちゃんとレジストリに登録しなければならなく、type-nameは以下のABNFに従います。

type-name  = 1*name-char
name-char   = "-" / "." / "_" / DIGIT / ALPHA

Typeの定義が新しいHTTP authentication schemeを含むときは、それを特定できる名前にすべきですよと。
少し前に紹介したHTTP Authentication: MAC Authenticationはこれにあたりますね。

8.2. Defining New Endpoint Parameters

リクエスト/レスポンスパラメータも、2種類の定義方法があります。

Access Token Typesと同じ感じですね。
この仕様に書いてあるリクエスト/レスポンスパラメータについては、10.2で説明されていますが、全部レジストリに登録してあ(ることにな)ります。
以下のABNFに従い、"x_"のプレフィックスは使ってはいけませんよということです。

type-name  = 1*name-char
name-char   = "-" / "." / "_" / DIGIT / ALPHA

そして、Vendor-specific parameterとして、"x_"つきのパラメータも定義可能です。
OAuth 1.0時代のxAuthのような独自パラメータも定義可能なわけですが、よっぽど特別な使い方するとき以外は、IANA登録してみんなのヒーローになる方がいいですね!

8.3. Defining New Authorization Grant Types

4.5の"SAML 2.0 assertion grant type"のように、grant_typeパラメータに独自の絶対URIを指定することにより、新しいauthorization grant typesを定義することができます。
で、その新しいauthorization grant typesが追加でリクエスト/レスポンスパラメータを必要とする場合には、10.2のレジストリに登録しなければなりませんよと。

10. IANA Registration

10.1. The OAuth Access Token Type Registry

OAuth 2.0では、Access Token Typesのレジストリが用意されます。

IANAとIESGあたりのしくみはこちら。
[http://tools.ietf.org/html/rfc5226
新たなAccess Token Typesの登録リクエストは、まだTBDだけど(なんとか@ietf.org)というMLにリクエストを投げます。
14日以内にDesignated Expert達が合否を決めて、IANAに連絡。
21日過ぎても未決定のリクエストは、MLを使ってIESGの偉い人にアピールすることができます。

登録のときのテンプレートはこんな感じ。

  • Type name
  • Additional Token Endpoint Response Parameters
  • HTTP Authentication Scheme(s)
  • Change controller
  • Specification document(s)
10.2. The OAuth Parameters Registry

OAuth 2.0のパラメータレジストリも用意されます。
テンプレはこのような感じです。

  • Parameter name
  • Parameter usage location
  • Change controller
  • Specification document(s)

今まで説明してきたパラメータは初期登録されていますよと。

まとめ

むりやり3行でまとめると

  • 認可のパターンとして、4パターン+αが定義されている (Authorization Code,Implicit Grant,Resource Owner Password Credentials,Client Credentials,Extensions)
  • Access Token Typesはこの仕様では定義せずに、拡張性を持たせている。
  • パラメータ、Access Token Types、Grant Typesは基本的にIANAへの登録が必要

ってとこでしょうか。

なぜ95%と言ってるのか?

このMLのpptxファイルに書いてありました。

OAuth 2 - 95%

次回のIIWまでにはもう変更なしの状態まで持っていく感じでしょうかねぇ。

おわり

いやー、長かったですね。。。これでもだいぶ端折るように頑張ったつもりですが。
まぁ、翻訳するとしたら、Draft 10翻訳時のノウハウがある程度利用できそうです。

日本の企業から、新しいAccess Token TypesやGrant Typeが提案されたりすると面白いと思います。
ではまた!