OAuth 2.0のbearer tokenの最新仕様を調べたらあまり変わってなかった

追記:最新仕様はRFC化されています。
The OAuth 2.0 Authorization Framework: Bearer Token Usage(日本語)

こんばんは、ritouです。
OAuth 2.0にはWGで議論され日々更新されているDraft仕様がたくさんあるわけですが、今回はOAuth 2.0のリソースアクセスの象徴ともいえる"bearer token"の最新仕様を確認します。
"OAuth 2.0ではリソースアクセス時に署名がいらなくなった"というような話を聞いたことがある人も多いと思いますが、それが"bearer token"と呼ばれるToken Typeになります。
最初はOAuth 2.0の本体の仕様に含まれていたのですが、途中で関連仕様として独立しています。

最新の仕様はこちらです。
draft-ietf-oauth-v2-bearer-04 - The OAuth 2.0 Authorization Framework: Bearer Token Usage

の前に、現時点のOAuth 2.0実装でよく採用されているOAuth 2.0 Draft 10時点の仕様を確認しておきます。

bearer token@OAuth 2.0 Draft 10

仕様はこの辺にあります。
draft-ietf-oauth-v2-10 - The OAuth 2.0 Authorization Framework
The OAuth 2.0 Protocol(日本語)
まずはリクエストから。

以下の3つの指定方法が定義されています。

  • Authorizationリクエストヘッダ
  • URIクエリパラメータ
  • Form-Encodedボディパラメータ

Resource ServerはAuthorizationリクエストヘッダをサポート必須(MUST)、それ以外の指定方法は(MAY)。
ClientはAuthorizationリクエストヘッダが利用できない場合に限り、他の指定方法を利用すべき。
1つのリクエスト内で2つ以上のメソッドを利用してはいけない。とあります。

指定方法は以下の通りです。
Authorizationリクエストヘッダでは認証スキーマが"OAuth"で、その後にTokenを指定します。

GET /resource HTTP/1.1
Host: server.example.com
Authorization: OAuth vF9dft4qmT

URIクエリパラメータのときは、oauth_tokenパラメータを利用します。

GET /resource?oauth_token=vF9dft4qmT HTTP/1.1
Host: server.example.com

Form-Encodedボディパラメータのときも、oauth_tokenパラメータを利用します。

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

oauth_token=vF9dft4qmT

レスポンスは以下のようになります。

  • realm
  • error : エラーの内容
  • error-desc : エラーの追加情報など
  • error-uri : エラーの内容についてのWebページのURI
  • scope : 必要なScope

サンプルはこのような感じです。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: OAuth realm='Example Service',
error='expired-token'

mixiの開発者向けドキュメントにもAuthorizationリクエストヘッダを使う場合とクエリパラメータの指定方法が書いてありますね。
認証認可手順(新方式) << mixi Developer Center (ミクシィ デベロッパーセンター)

それでは現時点の仕様でどのように代わっているかを確認します。

bearer tokens@Draft 4

ここからが今回のメインの内容です。
フローに変更はありません。

3種類の指定方法も同じです。
それぞれについて、差分を説明します。

Authorizationリクエストヘッダの場合、認証スキーマが"Bearer"となります。

GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer vF9dft4qmT

Form-Encodedボディパラメータを利用するの場合、パラメータ名に"bearer_token"を指定します。

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

bearer_token=vF9dft4qmT

URIクエリパラメータを利用する場合も、パラメータ名に"bearer_token"を指定します。

GET /resource?bearer_token=vF9dft4qmT HTTP/1.1
Host: server.example.com

優先順位は、AuthZ Header > Form-Encoded > URI Queryのように書いていますね。

続いてレスポンスです。
こちらも、"OAuth"から"Bearer"に変わっています。

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example"

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example"
error="invalid_token",
error_description="The access token expired"

上に書いていませんが、エラーコードの内容について、Draft 10のときは"expired_token"があったのですが、"invalid_token"に含まれています。
あれ?ほとんど差分ないですね。

Summary of Recommendations

本当は、Security Considerationsをちゃんと読んだ方がいいのですが、今回はどう実装すべきなのかが書いてある部分だけ抜き出します。

  • Safeguard bearer tokens : お漏らし禁止
  • Validate SSL certificate chains : DNSハイジャックされてTokenを持っていかれないように!
  • Always use TLS (https) :
  • Don't store bearer tokens in cookies : Cookieの値は信用しない!
  • Issue short-lived bearer tokens : 1時間以下の短い有効期限にして漏れたときのインパクトをおさえろ!
  • Don't pass bearer tokens in page URLs : URLのパラメータなどに使うとブラウザ周りで漏れるかも!

まとめ

全然仕様は変わっていなかったですね。
"OAuth" → "Bearer", "oauth_token" → "bearer token"の変更ぐらいならすぐに対応できますね。
ここ大事だけど書かなくていいの?みたいなツッコみがある方ば @ritou までどうぞ。

ではまた。