class Rack::U2f::AuthenticationMiddleware
Middleware to authenticate against registered u2f keys
Public Class Methods
new(app, config = nil)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 7 def initialize(app, config = nil) @app = app @config = config @after_sign_in_path = config[:after_sign_in_path] || '/' @u2f_register_path = config[:u2f_register_path] || '/_u2f_register' @store = config[:store] || raise('Please specify a U2F store such as Rack::U2f::RegistrationStore::RedisStore.new') @exclude_urls = config[:exclude_urls] || [] end
Public Instance Methods
call(env)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 16 def call(env) request = Rack::Request.new(env) return @app.call(env) if excluded?(request) return RegistrationServer.new(@config).call(env) if request.path == @u2f_register_path return @app.call(env) if authenticated?(request) return resp_auth_from_u2f(request) if request.params['u2f_auth'] challenge_page(request) end
Private Instance Methods
authenticated?(request)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 31 def authenticated?(request) request.session['u2f_authenticated'] end
challenge_page(request)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 63 def challenge_page(request) key_handles = @store.key_handles return resp_unregistered unless key_handles && !key_handles.empty? u2f = U2F::U2F.new(extract_app_id(request)) sign_requests = u2f.authentication_requests(key_handles) challenge = u2f.challenge request.session['challenge'] = challenge content = Mustache.render( CHALLENGE_TEMPLATE, app_id: u2f.app_id.to_json, challenge: challenge.to_json, sign_requests: sign_requests.to_json, u2fjs: U2FJS ) Rack::Response.new(content, 403) end
excluded?(request)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 27 def excluded?(request) @exclude_urls.any? { |exc| request.path =~ exc } end
resp_auth_from_u2f(request)
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 43 def resp_auth_from_u2f(request) u2f_response = U2F::SignResponse.load_from_json(request.params['u2f_auth']) registration = @store.get_registration(key_handle: u2f_response.key_handle) return unregistered unless registration begin u2f = U2F::U2F.new(extract_app_id(request)) u2f.authenticate!(request.session['challenge'], u2f_response, Base64.decode64(registration['public_key']), registration['counter']) rescue U2F::Error return resp_invalid ensure request.session.delete('challenge') end @store.update_registration(key_handle: u2f_response.key_handle, counter: u2f_response.counter) request.session['u2f_authenticated'] = true [302, { 'Location' => @after_sign_in_path }, []] end
resp_invalid()
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 39 def resp_invalid Rack::Response.new('Invalid Auth', 403) end
resp_unregistered()
click to toggle source
# File lib/rack/u2f/authentication_middleware.rb, line 35 def resp_unregistered Rack::Response.new('Unregistered Device', 403) end