Repository navigation
api_keys 0.8.0: config.require_bearer_scheme - #78
Merged
Merged
Conversation
When true, the authentication header is accepted only as "Bearer <token>". A bare token, another scheme or a lone "Bearer" gets the ordinary 401 invalid_token, is never looked up, and never falls back to the query parameter. It applies to whichever header config.header names. The default, false, keeps accepting a bare token as before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TFgkk7hfVmggDZz6BvW815
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
config.require_bearer_schememakes the authentication header accept one credential shape only:Bearer <token>. One opt-in setting, no migration, no generator. The default keeps accepting a bare token exactly as every earlier version did.Why
Since 0.1.0 the header has accepted two shapes:
Authorization: Bearer ak_…and, as a fallback, the bareAuthorization: ak_…. That fallback is convenient for curl, but a public API should parse one credential shape only. Two shapes mean two things to document, to test and to support forever, and a header such asBasic …orToken …was handed to the key lookup as if it were a token. ReplyBrain's public API asked for the strict shape; any app with a public API wants the same.What changed
Added
config.require_bearer_scheme(Boolean, defaultfalse).When
true, the header named byconfig.headeris accepted only when it matchesBearer <token>: the scheme in any case (bearer,BEARER), followed by one or more spaces or tabs, then the token. Everything else is refused:false(default)trueBearer ak_…(any case, spaces or tabs)ak_…(bare token)invalid_tokenBasic …,Token …invalid_token, never looked upBeareraloneinvalid_token, never looked upconfig.query_paramsetA refused header is answered exactly like any wrong key: the ordinary 401
invalid_tokenthroughrender_unauthorized, with no hint that the shape was the problem. It is never looked up, so it costs no database query or bcrypt comparison. The header was present, so a refused header never falls back toconfig.query_param. The setting applies to whichever headerconfig.headernames, not onlyAuthorization.Like the other boolean settings, the writer accepts only
trueorfalseand raisesArgumentErrorotherwise.Initializer template:
rails g api_keys:installwrites the commented setting underconfig.header, recommended for public APIs.README: a new section, "Require the
Bearerscheme".Changed
Authorizationheader, instead of "exclusively as HTTP Authentication Bearer tokens", which the bare-token fallback contradicted.Security
MALFORMED_CREDENTIALsentinel that 0.7.0 introduced for oversized and invalid UTF-8 headers, so it takes the same constant-shape failure path and adds no new answer an attacker could distinguish.Compatibility
false: nothing changes for any app that does not set it.config.debug_logging = truethe gem logs "Refused a header without the Bearer scheme." for each refusal.Upgrade notes
No migration and no generator. Update the gem:
To require the scheme, add one line to
config/initializers/api_keys.rb:The 0.7.0 upgrade notes still apply to apps coming from 0.6.x or earlier.
Tests
test/services/authenticator_test.rb: a bare token authenticates by default; with the setting, a bare token is an invalid token and is never looked up; the Bearer scheme still authenticates in any case and spacing; a refused header does not fall back to the query parameter; the setting applies to a customconfig.header.test/controllers/authentication_test.rb: through a controller, a bare token gets the ordinary 401invalid_tokenanswer.🤖 Generated with Claude Code
https://claude.ai/code/session_01TFgkk7hfVmggDZz6BvW815