Rails API の HttpAuthentication/Token の実装を読む
Leaner Technologies の @corocn です。
Rails の HttpAuthentication/Token 周りを改めて読んだのでメモです。
この記事を読むと分かること
Rails で API の保護にトークンを利用する場合において、次のメソッドの使い分けが理解できる。
- authenticate_or_request_with_http_token
- authenticate_with_http_token
結論
トークン検証失敗時にレンダリングされる内容やステータスコードについて、特にこだわりがない場合は、authenticate_or_request_with_http_token を利用する。
レスポンスを詳細にカスタマイズしたい場合は、authenticate_with_http_token を利用し、レスポンスは自前で作成する。
モチベーション
Rails API モードを利用し、API を トークンベースの認可の仕組みで保護するケースを考えた。標準で提供されているメソッドがいくつかあり、どれを使えばいいかわかりにくいので、整理したい。
サンプルには authenticate_or_request_with_http_token を使った例が載っている。この例ではブロック内でトークンの検証を行っているようだ。
HttpAuthentication::Token
Controller から利用できるメソッドは以下で把握できる。
- authenticate_or_request_with_http_token
- authenticate_with_http_token
- request_http_token_authentication
同じような単語の長めのメソッドでちょっと混乱する。
authenticate_or_request_with_http_token
基本的にはこのメソッドを利用すれば良い。
authenticate_or_request_with_http_token の中で、authenticate_with_http_token または request_http_token_authentication を呼び出すようになっている。
authenticate_or_request_with_http_token は block を受け取ることができ、authenticate_with_http_token が渡されて実行される。
authenticate_with_http_token の返り値が true で判定されれば処理はそこで終わり、request_http_token_authentication は呼ばれない。
authenticate_with_http_token
次のようなリクエストヘッダーを前提とする。
Authorization: Bearer <Token>
ここから 実際にリクエストされたトークンを抜き出す処理を token_and_options が担当している。Bearer の部分は Authorization: Bearer または Authorization: Token に標準で対応している。
トークンが存在する場合、そのトークンを第1引数として、渡された block が評価される。つまり authenticate_or_request_with_http_token の block 内でトークンの検証を行い、OKであれば true を返せば良い。
ここまでで、サンプルで把握した挙動と一致することは確認できた。
request_http_token_authentication
authenticate_with_http_token の返り値が false のとき、つまり トークンの検証に失敗した時に呼び出される。
Token.authentication_request を呼び出している。
authentication_request では、message が引数で渡ってこない場合は、固定の "HTTP Token: Access denied." を ステータスコード 401: unauthorized で返す。
また、レスポンスヘッダーに WWW-Authenticate を追加し、認証方式に関する情報を提供する。
参考
本記事とは切り口が異なるが、以下の記事でも似たようなまとめになっている。
執筆時点のバージョン: Ruby on Rails 7.0.4 であり、挙動は変更される可能性がある。
Discussion