Reputation: 462
I have two warden strategies in a Rails API app, for basic authentication and for token authentication.
initializers/warden.rb
Warden::Strategies.add(:auth_token, AuthTokenStrategy)
Warden::Strategies.add(:basic_auth, BasicAuthStrategy)
config/application.rb
config.middleware.insert_after ActionDispatch::Callbacks, Warden::Manager do |manager|
manager.default_strategies :auth_token, :basic_auth
manager.failure_app = UnauthorizedController
end
And both strategies implements #valid?
class BasicAuthStrategy < ::Warden::Strategies::Base
def valid?
auth.provided? && auth.basic?
end
...
end
and
class AuthTokenStrategy < ::Warden::Strategies::Base
def valid?
auth.provided? && !auth.basic? && headers['HTTP_AUTHORIZATION'].start_with?('Bearear')
end
...
end
I imagine making a request with token, warden tries BasicAuthStrategy and then it tries AuthTokenStrategy mas it ends up after the first. It ignores one strategy. Why?
PS: I'm not using devise.
Upvotes: 1
Views: 1038
Reputation: 31
First I will assume that auth.provided?
and auth.basic?
are defined and working correctly. The sample you provided is not showing what the authenticate!
method looks like so I'll put in some pseudo-code.
class AuthTokenStrategy < ::Warden::Strategies::Base
def valid?
request.headers['HTTP_AUTHORIZATION'].start_with?('Bearear')
end
def authenticate!
bearer_token = request.headers['HTTP_AUTHORIZATION'].split(' ')
if user = User.find_by(bearer_token: auth_token)
success!(user)
end
end
end
class BasicAuthStrategy < ::Warden::Strategies::Base
def valid?
not request.headers['HTTP_AUTHORIZATION'].nil?
end
def authenticate!
auth_token = request.headers['HTTP_AUTHORIZATION']
if user = User.find_by(auth_token: auth_token)
success!(user)
end
end
end
Warden::Strategies.add(:auth_token, AuthTokenStrategy)
Warden::Strategies.add(:basic_auth, BasicAuthStrategy)
Rails.application.config.middleware.use Warden::Manager do |manager|
manager.default_strategies %i[auth_token basic_auth]
# manager.failure_app = lambda { |env|
# SessionsController.action(:failure).call(env)
#}
end
It is worth noting that in your case the valid?
definition may be optional. Warden will stop running strategies when one returns success!
.
Upvotes: 1