TL;DR
- HTTP でトークンを利用した認証・認可をする手法として RFC 6750 がある
- OAuth に限らず、トークンを利用して認証・認可する機構の一部として
Authorization: Bearer
ヘッダを使うことができる - 使い方について詳しくはこの記事の下のほうに書いた
要求
- トークンを利用した認証・認可機構を持つ API を作りたい
- クライアントがトークンを HTTP リクエストに含めて送信し、サーバはトークンを検証してリソースへのアクセスを許可したい
-
Authorization: Bearer トークン
ヘッダでトークンを送る API あるよね、ああいうやつ
疑問
-
Authorization: Bearer
ヘッダは OAuth と関係しているらしいけど、ログインに OAuth を使わない API でも使っていい? -
Authorization
以外のヘッダでトークンを送る API にならったほうがいい?- 例:GitHub API v3は
Authorization: token トークン
ヘッダ - 例:AWS Signature v4 は
Authorization: AWS4-HMAC-SHA256 トークン他…
ヘッダ - 例:Chatwork API は
X-ChatWorkToken: トークン
ヘッダ
- 例:GitHub API v3は
Authorization ヘッダについて調べた
-
Authorization
ヘッダの仕様は RFC 7235 - Hypertext Transfer Protocol (HTTP/1.1): Authentication で定義されている -
Authorization: auth-scheme (token68 / auth-params)
の形式で書け、と定められている - 各スキームの仕様については言及されていない
-
RFC 7235 section 5.1 によれば、
auth-scheme
の取り得る値は IANA で管理されている -
Basic
,Digest
が代表的な登録済みスキーム、Bearer
も登録済み - GitHub や AWS のように独自のスキームを使うよりは
Bearer
スキームの仕様に則ったほうがよさそう?
Authorization ヘッダの Bearer スキームとは何か
- Bearer スキームは RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage で定義されている
- RFC 6750 は OAuth 2.0 の認可機構として設計されたものだが、 OAuth に限らず汎用的な HTTP 認可に使ってよいと書いてある
While designed for use with access tokens
resulting from OAuth 2.0 authorization [RFC6749] flows to access
OAuth protected resources, this specification actually defines a
general HTTP authorization method that can be used with bearer tokens
from any source to access any resources protected by those bearer
tokens. The Bearer authentication scheme is intended primarily for
server authentication using the WWW-Authenticate and Authorization
HTTP headers but does not preclude its use for proxy authentication.
- RFC 6750 の要求仕様に従って Bearer スキームを使えばいい
RFC 6750 に準拠した Bearer スキームを実装するには
正確なところは RFC 6750 を参照してもらうとして、概略を以下に示す。わりと簡単。
- トークンは任意の token68 文字列1とする
- 保護されたリソースにアクセスするとき、クライアントは
Authorization: Bearer トークン
ヘッダをリクエストに含めて送信する - リクエストがアクセス要件を満たさないなら、サーバは
WWW-Authenticate: Bearer パラメータ
ヘッダを返さ なければならない- パラメータは1つ以上必要
- 特に返したいパラメータがなければ最低限
realm=""
を入れておけばいいと思われる
- 特に返したいパラメータがなければ最低限
- エラーの場合は適切なステータスコードと特定の値の
error
パラメータを返す べきである(値のバリエーションは後述のレスポンス例を参照) - ただし、リクエストが認可のためのヘッダを含まない(つまり認可が必要であることをクライアントが知らない)なら
error
パラメータを含める べきではない -
error_description
パラメータにエラーを説明する文字列を含め てもよい -
error_uri
パラメータにエラーを説明するページへの URI を含め てもよい
- パラメータは1つ以上必要
- (リクエストがアクセス要件を満たすときのレスポンスの形式については特に指定されていない)
リクエストがアクセス要件を満たさないときの典型的なレスポンス例は以下のようになる。
- リクエストが Authorization ヘッダを含まない場合
- 401 Unauthorized
- ヘッダに
WWW-Authenticate: Bearer realm="適当なrealm"
を含む
- リクエストパラメータが不正な場合
- 400 Bad Request
- ヘッダに
WWW-Authenticate: Bearer error="invalid_request"
を含む
- トークンが失効や破損などの理由で不正な場合
- 401 Unauthorized
- ヘッダに
WWW-Authenticate: Bearer error="invalid_token"
を含む
- トークンのスコープが不十分な場合
- (この記事ではスコープについて触れない。詳しくは RFC 6750 section 3 を参照)
- 403 Forbidden
- ヘッダに
WWW-Authenticate: Bearer error="insufficient_scope"
を含む
空でない realm を一貫してパラメータに含めたほうが親切かもしれない。たとえば realm="token_required"
とか。
Bearer スキームでないトークン認証手法を選ぶべき状況はあるか
例えば Basic 認証とトークンによる認証の両方を同時に要求したい場合が考えられる。 Authorization
ヘッダはリクエスト中に1つしか含められないため。(RFC 7230 section 3.2.2 を参照)
RFC 7235 section 2.1 によれば、アプリケーションは HTTP 以外の仕組みによる認証を併せて利用してもよいし、追加の HTTP ヘッダを用いた認証を行なってもよい:
HTTP does not restrict applications to this simple challenge-response
framework for access authentication. Additional mechanisms can be
used, such as authentication at the transport level or via message
encapsulation, and with additional header fields specifying
authentication information. However, such additional mechanisms are
not defined by this specification.
まとめ
-
Authorization: Bearer
ヘッダの仕様は RFC6750 で定められている - OAuth の仕様の一部だが、 OAuth に限らず一般的な HTTP 認可の手段として使える
- 仕様に準拠するためにはサーバは特定のレスポンスを返さ なければならない
- といってもヘッダひとつ含めるだけなので簡単
- 特に事情がなければ RFC6750 に従って
Authorization: Bearer
ヘッダを使うのがよさそう
-
token68 は ASCII アルファベット、 ASCII 数字、
-
,.
,_
,~
,+
,/
からなる文字列(末尾に0個以上の=
があってもよい)。改行を含まない任意の base64 文字列は正しい token68 文字列になる。 ↩