lib/roda/plugins/http_auth.rb in roda-http-auth-0.1.2 vs lib/roda/plugins/http_auth.rb in roda-http-auth-0.2.0

- old
+ new

@@ -3,70 +3,64 @@ module Roda::RodaPlugins module HttpAuth DEFAULTS = { realm: "Restricted Area", - unauthorized_headers: proc do |opts| - {'Content-Type' => 'text/plain', - 'Content-Length' => '0', - 'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm])} + unauthorized_headers: ->(opts) do + { 'WWW-Authenticate' => ('Basic realm="%s"' % opts[:realm]) } end, - bad_request_headers: proc do |opts| - {'Content-Type' => 'text/plain', 'Content-Length' => '0'} - end, + unauthorized: ->(r) {}, schemes: %w[basic] } def self.configure(app, opts={}) plugin_opts = (app.opts[:http_auth] ||= DEFAULTS) app.opts[:http_auth] = plugin_opts.merge(opts) app.opts[:http_auth].freeze end - module RequestMethods + module InstanceMethods def http_auth(opts={}, &authenticator) - auth_opts = roda_class.opts[:http_auth].merge(opts) + auth_opts = request.roda_class.opts[:http_auth].merge(opts) authenticator ||= auth_opts[:authenticator] raise "Must provide an authenticator block" if authenticator.nil? - begin - auth = Rack::Auth::Basic::Request.new(env) + auth = Rack::Auth::Basic::Request.new(env) - unless auth.provided? && auth_opts[:schemes].include?(auth.scheme) - auth_opts[:unauthorized].call(self) if auth_opts[:unauthorized] - halt [401, auth_opts[:unauthorized_headers].call(auth_opts), []] - end + unless auth.provided? && auth_opts[:schemes].include?(auth.scheme) + unauthorized(auth_opts) + end - credentials = if auth.basic? - auth.credentials - elsif auth.scheme == 'bearer' - [env['HTTP_AUTHORIZATION'].strip.split(' ').last] - else - [auth.scheme, _extract_credentials] - end + credentials = if auth.basic? + auth.credentials + elsif auth.scheme == 'bearer' + [env['HTTP_AUTHORIZATION'].split(' ', 2).last] + else + http_auth = env['HTTP_AUTHORIZATION'].split(' ', 2) + .last - if authenticator.call(*credentials) - env['REMOTE_USER'] = auth.username - else - opts[:unauthorized].call(self) if auth_opts[:unauthorized] - halt [401, auth_opts[:unauthorized_headers].call(auth_opts), []] - end - rescue StandardError - halt [400, auth_opts[:bad_request_headers].call(auth_opts), []] + creds = !http_auth.include?('=') ? http_auth : + Rack::Auth::Digest::Params.parse(http_auth) + + [auth.scheme, creds] + end + + if authenticator.call(*credentials) + env['REMOTE_USER'] = auth.username + else + unauthorized(auth_opts) end end - def _extract_credentials - authorization = env['HTTP_AUTHORIZATION'].split(' ', 2).last - parts = authorization.split(',') + private - return parts.first if parts.one? && !parts.first.include?('=') + def unauthorized(opts) + response.status = 401 + response.headers.merge!(opts[:unauthorized_headers].call(opts)) - key_values = parts.map {|p| p.strip.split(/\=\"?/) } - .map {|k, v| [k, v.chomp('"').gsub(/\\\"/, '"')] } - - Hash[key_values] + request.block_result(instance_exec(request, &opts[:unauthorized])) + request.halt response.finish end end end register_plugin(:http_auth, HttpAuth)