Class: Rubino::API::Middleware::Auth
- Inherits:
-
Object
- Object
- Rubino::API::Middleware::Auth
- Defined in:
- lib/rubino/api/middleware/auth.rb
Overview
Bearer-token auth middleware. Sits between JsonParser and the router so unauthorized requests never reach an operation; raises UnauthorizedError which ErrorHandler (one layer up) maps to a 401 JSON response.
Token comparison uses Rack::Utils.secure_compare to avoid timing leaks. SKIP_PATHS allows unauthenticated access to liveness/metrics endpoints so external probes don’t need to carry the API key.
Constant Summary collapse
- SKIP_PATHS =
%w[/v1/health /v1/metrics].freeze
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, api_key:) ⇒ Auth
constructor
A new instance of Auth.
Constructor Details
#initialize(app, api_key:) ⇒ Auth
Returns a new instance of Auth.
18 19 20 21 |
# File 'lib/rubino/api/middleware/auth.rb', line 18 def initialize(app, api_key:) @app = app @api_key = api_key end |
Instance Method Details
#call(env) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/rubino/api/middleware/auth.rb', line 23 def call(env) return @app.call(env) if SKIP_PATHS.include?(env["PATH_INFO"]) header = env["HTTP_AUTHORIZATION"].to_s # RFC 6750: scheme is case-insensitive, separated from the token by a # single space. Match explicitly so a raw token without the "Bearer " # prefix is rejected instead of being silently accepted (which is what # String#sub would do when the pattern doesn't match). match = header.match(/\ABearer (.*)\z/i) raise UnauthorizedError, "missing bearer scheme" if match.nil? token = match[1] raise UnauthorizedError, "missing bearer token" if token.empty? raise UnauthorizedError, "invalid bearer token" unless Rack::Utils.secure_compare(token, @api_key) @app.call(env) end |