Extract Bearer Tokens with Request#bearer_token

railsapiauthentication

If you’re building APIs with Rails, you’ve probably written code to extract bearer tokens from the Authorization header. Rails now provides a built-in method to do this cleanly.

What Changed

ActionDispatch::Request now includes a bearer_token method that extracts the token from the Authorization header:

# Authorization: Bearer my-secret-token
request.bearer_token
# => "my-secret-token"

Why This Matters

Bearer tokens are the standard way to authenticate API requests. Before this change, you’d write something like:

class ApiController < ApplicationController
  def authenticate
    token = request.authorization.to_s.split(" ").last
    # or
    token = request.authorization&.gsub(/^Bearer /, "")
    # or
    token = request.headers["Authorization"]&.match(/Bearer (.+)/)&.[](1)
  end
end

Each approach has edge cases. The new method handles them all:

token = request.bearer_token

How to Use It

Basic API authentication

class ApiController < ApplicationController
  before_action :authenticate

  private

  def authenticate
    token = request.bearer_token

    unless token && valid_token?(token)
      render json: { error: "Unauthorized" }, status: :unauthorized
    end
  end

  def valid_token?(token)
    ApiToken.find_by(token: token)&.active?
  end
end

With Devise or custom authentication

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

Edge cases handled

The method returns nil in these cases:

# No Authorization header
request.bearer_token # => nil

# Different auth scheme
# Authorization: Basic dXNlcjpwYXNz
request.bearer_token # => nil

# Empty header
# Authorization:
request.bearer_token # => nil

# Bearer with no token
# Authorization: Bearer
request.bearer_token # => nil

It also works with the X-HTTP_AUTHORIZATION header (used by some proxies):

# X-HTTP_AUTHORIZATION: Bearer my-token
request.bearer_token # => "my-token"

Things to Watch Out For

  • The method only extracts the token; validation is still your responsibility
  • Tokens are case-sensitive; the method preserves the exact token value
  • The “Bearer” prefix matching is case-sensitive (per RFC 6750)

Wrapping Up

A small but welcome addition that eliminates boilerplate in API authentication code. If you’re manually parsing Authorization headers, switch to request.bearer_token for cleaner, more reliable code.

See the commit and PR #56474 for details.