Request#bearer_tokenでBearerトークンを抽出する
RailsでAPIを構築している場合、Authorizationヘッダーからbearerトークンを抽出するコードを書いたことがあるでしょう。Railsはこれをクリーンに行うための組み込みメソッドを提供するようになりました。
変更内容
ActionDispatch::RequestにAuthorizationヘッダーからトークンを抽出するbearer_tokenメソッドが追加されました:
# Authorization: Bearer my-secret-token
request.bearer_token
# => "my-secret-token"
なぜこれが重要か
Bearerトークンは、APIリクエストを認証する標準的な方法です。この変更前は、次のようなコードを書いていました:
class ApiController < ApplicationController
def authenticate
token = request.authorization.to_s.split(" ").last
# または
token = request.authorization&.gsub(/^Bearer /, "")
# または
token = request.headers["Authorization"]&.match(/Bearer (.+)/)&.[](1)
end
end
各アプローチにはエッジケースがあります。新しいメソッドはそれらすべてを処理します:
token = request.bearer_token
使い方
基本的なAPI認証
class ApiController < ApplicationController
before_action :authenticate
private
def authenticate
token = request.bearer_token
unless token && valid_token?(token)
render json: { error: "認証されていません" }, status: :unauthorized
end
end
def valid_token?(token)
ApiToken.find_by(token: token)&.active?
end
end
Deviseまたはカスタム認証と
class ApiController < ApplicationController
before_action :authenticate_user_from_token!
private
def authenticate_user_from_token!
token = request.bearer_token
return head :unauthorized unless token
@current_user = User.find_by(api_token: token)
head :unauthorized unless @current_user
end
end
処理されるエッジケース
メソッドは以下の場合にnilを返します:
# Authorizationヘッダーなし
request.bearer_token # => nil
# 異なる認証スキーム
# Authorization: Basic dXNlcjpwYXNz
request.bearer_token # => nil
# 空のヘッダー
# Authorization:
request.bearer_token # => nil
# トークンなしのBearer
# Authorization: Bearer
request.bearer_token # => nil
X-HTTP_AUTHORIZATIONヘッダー(一部のプロキシで使用)でも動作します:
# X-HTTP_AUTHORIZATION: Bearer my-token
request.bearer_token # => "my-token"
注意点
- メソッドはトークンを抽出するだけで、検証は依然としてあなたの責任です
- トークンは大文字と小文字を区別します。メソッドは正確なトークン値を保持します
- “Bearer”プレフィックスのマッチングは大文字と小文字を区別します(RFC 6750に従う)
まとめ
API認証コードのボイラープレートを排除する小さいながらも歓迎すべき追加です。Authorizationヘッダーを手動でパースしている場合は、よりクリーンで信頼性の高いコードのためにrequest.bearer_tokenに切り替えてください。