トークンを利用した認証・認可 API を実装するとき Authorization: Bearer ヘッダを使っていいのか調べた

  • 590
    いいね
  • 0
    コメント

TL;DR

  • HTTP でトークンを利用した認証・認可をする手法として RFC6750 がある
  • これに従って Authorization: Bearer ヘッダを使うとよい
  • 使い方について詳しくはこの記事の下のほうに書いた

要求

  • トークンを利用した認証・認可機構を持つ API を作りたい
  • クライアントがトークンを HTTP リクエストに含めて送信し、サーバはトークンを検証してリソースへのアクセスを許可したい
  • Authorization: Bearer トークン ヘッダでトークンを送る API あるよね、ああいうやつ

疑問

  • Authorization: Bearer ヘッダは OAuth と関係しているらしいけど、ログインに OAuth を使わない API でも使っていい?
  • Authorization 以外のヘッダでトークンを送る API にならったほうがいい?
    • 例:GitHub API v3Authorization: token トークン ヘッダ
    • 例:AWS Signature v4Authorization: AWS4-HMAC-SHA256 トークン他… ヘッダ
    • 例:Chatwork APIX-ChatWorkToken: トークン ヘッダ

Authorization ヘッダについて調べた

  • Authorization ヘッダの仕様は RFC 7235 - Hypertext Transfer Protocol (HTTP/1.1): Authentication で定義されている
  • Authorization: auth-scheme (token68 / auth-params) の形式で書け、と定められている
  • 各スキームの仕様については言及されていない
  • RFC7235 section 5.1 によれば、 auth-scheme の取り得る値は IANA で管理されている
  • Basic, Digest が代表的な登録済みスキーム、 Bearer も登録済み
  • GitHub や AWS のように独自のスキームを使うよりは Bearer スキームの仕様に則ったほうがよさそう?

Authorization ヘッダの Bearer スキームとは何か

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.

  • RFC6750 の要求仕様に従って Bearer スキームを使えばいい

RFC6750 に準拠した Bearer スキームを実装するには

正確なところは RFC6750 を参照してもらうとして、概略を以下に示す。わりと簡単。

  • トークンは任意の token68 文字列1とする
  • 保護されたリソースにアクセスするとき、クライアントは Authorization: Bearer トークン ヘッダをリクエストに含めて送信する
  • リクエストがアクセス要件を満たさないなら、サーバは WWW-Authenticate: Bearer パラメータ ヘッダを返さ なければならない
    • パラメータは1つ以上必要
      • 特に返したいパラメータがなければ最低限 realm="" を入れておけばいいと思われる
    • エラーの場合は特定の error パラメータとステータスコードを返す べきである(後述のレスポンス例を参照)
    • ただし、リクエストが認可のためのヘッダを含まない(つまり認可が必要であることをクライアントが知らない)なら error パラメータを含める べきではない
    • error_description パラメータにエラーを説明する文字列を含め てもよい
    • error_uri パラメータにエラーを説明するページへの URI を含め てもよい

リクエストがアクセス要件を満たさないときの典型的なレスポンス例は以下のようになる。

  • リクエストが 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" を含む
  • トークンのスコープが不十分な場合
    • (この記事ではスコープについて触れない。詳しくは RFC6750 section 3 を参照)
    • 403 Forbidden
    • ヘッダに WWW-Authenticate: Bearer error="insufficient_scope" を含む

空でない realm を一貫してパラメータに含めたほうが親切かもしれない。たとえば realm="token_required" とか。

リクエストがアクセス要件を満たすときのレスポンスの形式については特に指定されていない。

Bearer スキームでないトークン認証手法を選ぶべき状況はあるか

例えば Basic 認証とトークンによる認証の両方を同時に要求したい場合が考えられる。 Authorization ヘッダはリクエスト中に1つしか含められないため。(cf. RFC 7320 3.2.2

RFC 7325 2.1 によれば、アプリケーションは追加のヘッダを用いた認証を行なってもよい:

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 ヘッダを使うのがよさそう

  1. token68 は ASCII アルファベット、 ASCII 数字、 -, ., _, ~, +, / からなる文字列(末尾に0個以上の = があってもよい)。改行を含まない base64 文字列は正しい token68 文字列になる。