Use a single challenge for U2F authentication.
1. According to the spec, either we have a single challenge with a number of `signRequests`, or a number of `signRequests`, each with it's own challenge. 2. Previously, we had both these - per-request challenges, as well as a single extra challenge. 3. This commit changes this so that the per-request challenges are removed, leaving only a single challenge, as per the v1.1 U2F API. 4. The existing implementation didn't work in Firefox, because the Firefox (extension) implementation is less flexible with regard to the inputs. 5. Fix teaspoon specs. 6. References: https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-javascript-api.html#h2_background
This commit is contained in:
parent
4b33c4c6d1
commit
3572582dd2
|
@ -6,8 +6,17 @@
|
|||
class @U2FAuthenticate
|
||||
constructor: (@container, u2fParams) ->
|
||||
@appId = u2fParams.app_id
|
||||
@challenges = u2fParams.challenges
|
||||
@signRequests = u2fParams.sign_requests
|
||||
@challenge = u2fParams.challenge
|
||||
|
||||
# The U2F Javascript API v1.1 requires a single challenge, with _no
|
||||
# challenges per-request_.
|
||||
#
|
||||
# The U2F Javascript API v1.0 requires a challenge per-request, which
|
||||
# is done by copying the single challenge into every request.
|
||||
#
|
||||
# In either case, we don't need the per-request challenges that the server
|
||||
# has generated, so we can remove them.
|
||||
@signRequests = u2fParams.sign_requests.map (request) -> _(request).omit('challenge')
|
||||
|
||||
start: () =>
|
||||
if U2FUtil.isU2FSupported()
|
||||
|
@ -16,7 +25,7 @@ class @U2FAuthenticate
|
|||
@renderNotSupported()
|
||||
|
||||
authenticate: () =>
|
||||
u2f.sign(@appId, @challenges, @signRequests, (response) =>
|
||||
u2f.sign(@appId, @challenge, @signRequests, (response) =>
|
||||
if response.errorCode
|
||||
error = new U2FError(response.errorCode)
|
||||
@renderError(error);
|
||||
|
|
|
@ -57,7 +57,7 @@ module AuthenticatesWithTwoFactor
|
|||
|
||||
# Authenticate using the response from a U2F (universal 2nd factor) device
|
||||
def authenticate_with_two_factor_via_u2f(user)
|
||||
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenges])
|
||||
if U2fRegistration.authenticate(user, u2f_app_id, user_params[:device_response], session[:challenge])
|
||||
# Remove any lingering user data from login
|
||||
session.delete(:otp_user_id)
|
||||
session.delete(:challenges)
|
||||
|
@ -77,9 +77,8 @@ module AuthenticatesWithTwoFactor
|
|||
|
||||
if key_handles.present?
|
||||
sign_requests = u2f.authentication_requests(key_handles)
|
||||
challenges = sign_requests.map(&:challenge)
|
||||
session[:challenges] = challenges
|
||||
gon.push(u2f: { challenges: challenges, app_id: u2f_app_id,
|
||||
session[:challenge] ||= u2f.challenge
|
||||
gon.push(u2f: { challenge: session[:challenge], app_id: u2f_app_id,
|
||||
sign_requests: sign_requests })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
#= require ./mock_u2f_device
|
||||
|
||||
describe 'U2FAuthenticate', ->
|
||||
U2FUtil.enableTestMode()
|
||||
fixture.load('u2f/authenticate')
|
||||
|
||||
beforeEach ->
|
||||
@u2fDevice = new MockU2FDevice
|
||||
@container = $("#js-authenticate-u2f")
|
||||
@component = new U2FAuthenticate(@container, {}, "token")
|
||||
@component = new U2FAuthenticate(@container, {sign_requests: []}, "token")
|
||||
@component.start()
|
||||
|
||||
it 'allows authenticating via a U2F device', ->
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#= require ./mock_u2f_device
|
||||
|
||||
describe 'U2FRegister', ->
|
||||
U2FUtil.enableTestMode()
|
||||
fixture.load('u2f/register')
|
||||
|
||||
beforeEach ->
|
||||
|
|
|
@ -18,8 +18,8 @@ class FakeU2fDevice
|
|||
|
||||
def respond_to_u2f_authentication
|
||||
app_id = @page.evaluate_script('gon.u2f.app_id')
|
||||
challenges = @page.evaluate_script('gon.u2f.challenges')
|
||||
json_response = u2f_device(app_id).sign_response(challenges[0])
|
||||
challenge = @page.evaluate_script('gon.u2f.challenge')
|
||||
json_response = u2f_device(app_id).sign_response(challenge)
|
||||
|
||||
@page.execute_script("
|
||||
u2f.sign = function(appId, challenges, signRequests, callback) {
|
||||
|
|
Loading…
Reference in New Issue