Add http authorization methods to Roda.
This is an external plugin. Install it by adding the gem to your gemfile:
gem 'roda-http-auth'
Configure your Roda application to use this plugin:
plugin :http_auth
You can pass global options, in this context they'll be shared between all
http_auth
calls.
plugin :http_auth, authenticator: ->(user, pass) { [user, pass] == %w[foo bar] },
realm: 'Restricted Area', # default
schemes: %w[basic] # default
Call http_auth
inside the routes you want to authenticate the user, it will halt
the request with an empty response with status 401 if the authenticator is false.
You can provide an unauthorized
block to be invoked whenever the user is
unathorized, it's executed in the context of the instance:
plugin :http_auth, unauthorized: -> { view('401.html') }
# ...
r.root do
http_auth {|u, p| [u, p] == %w[foo bar] }
"If you can see this you were authorized! \
Otherwise you'll be served with the 401.html.erb template"
end
Basic authorization is the default method:
# Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
http_auth { |user, pass| [user, pass] == ['Aladdin', 'open sesame'] }
By default authorization schemes are whitelisted, so if you want to use one that is not basic auth you must configure it:
plugin :http_auth, schemes: %w[bearer]
You can also whitelist schemes for a specific route:
http_auth(schemes: %w[bearer]) { |token| token == '4t0k3n' }
When the Bearer
scheme is passed, if whitelisted, the token is passed to
the authenticator:
# Authorization: Bearer 4t0k3n
http_auth { |token| token == '4t0k3n' }
For schemes that require formatted params authorization header, like Digest
,
the scheme and the parsed params are passed to the authenticator:
# Request
Authorization: Digest username="Mufasa",
realm="[email protected]",
uri="/dir/index.html",
algorithm=MD5,
nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v",
nc=00000001,
cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ",
qop=auth,
response="8ca523f5e9506fed4657c9700eebdbec",
opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"
http_auth { |s, p| [s, p['username']] == ['digest', 'Mufasa'] }
To avoid having your 401 responses intercepted by warden, you need to configure the unauthenticated callback that is called just before the request is halted:
plugin :http_auth, unauthorized: -> { env['warden'].custom_failure! }
The header sent when the user is unauthorized can be configured via
unauthorized_headers
and realm
options, globally or locally:
unauthorized_headers: ->(opts) do
{ 'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm]) }
end, # default
realm: "Restricted Area", # default
bundle exec ruby spec/*_spec.rb
Bug reports and pull requests are welcome on GitHub at https://github.com/badosu/roda-http-auth.
The gem is available as open source under the terms of the MIT License.