Module: TwoFactorAuth
- Defined in:
- app/models/two_factor_auth/registration_response.rb,
lib/two_factor_auth.rb,
lib/two_factor_auth/engine.rb,
lib/two_factor_auth/version.rb,
app/models/two_factor_auth/client_data.rb,
app/models/two_factor_auth/registration.rb,
app/models/two_factor_auth/registration_request.rb,
app/helpers/two_factor_auth/registrations_helper.rb,
app/models/two_factor_auth/registration_verifier.rb,
lib/generators/two_factor_auth/install_generator.rb,
app/models/two_factor_auth/authentication_request.rb,
app/helpers/two_factor_auth/authentications_helper.rb,
app/models/two_factor_auth/authentication_response.rb,
app/models/two_factor_auth/authentication_verifier.rb,
app/models/two_factor_auth/authentication_client_data.rb,
app/controllers/two_factor_auth/registrations_controller.rb,
app/controllers/two_factor_auth/trusted_facets_controller.rb,
app/controllers/two_factor_auth/authentications_controller.rb,
app/controllers/two_factor_auth/two_factor_auth_controller.rb
Overview
See FIDO U2F “Raw Message Formats” documentation, section 4.3 “Registration Response Message: Success”
Defined Under Namespace
Modules: AuthenticationsHelper, Generators, RegistrationsHelper
Classes: AuthenticationClientData, AuthenticationRequest, AuthenticationResponse, AuthenticationVerifier, AuthenticationsController, CantGenerateRandomNumbers, ClientData, Engine, InvalidFacetDomain, InvalidFacetListDomain, InvalidPublicKey, InvalidTrustedFacetListUrl, Registration, RegistrationRequest, RegistrationResponse, RegistrationVerifier, RegistrationsController, TrustedFacetsController, TwoFactorAuthController, TwoFactorAuthError
Constant Summary
collapse
- U2F_VERSION =
'U2F_V2'
- VERSION =
"0.2.0"
Class Method Summary
collapse
Class Method Details
.app_id_or_facet_list ⇒ Object
We send clients the facet domain (web origin) if there are no facets, (typical for local dev), otherwise the full facet list (prohibits http)
48
49
50
51
52
53
54
|
# File 'lib/two_factor_auth.rb', line 48
def self.app_id_or_facet_list
if facets.empty?
facet_domain
else
"#{facet_domain}/two_factor_auth/trusted_facets"
end
end
|
.decode_pubkey(raw) ⇒ Object
89
90
91
92
93
94
95
|
# File 'lib/two_factor_auth.rb', line 89
def self.decode_pubkey raw
bn = OpenSSL::BN.new(raw, 2)
group = OpenSSL::PKey::EC::Group.new('prime256v1')
point = OpenSSL::PKey::EC::Point.new(group, bn)
rescue OpenSSL::PKey::EC::Point::Error => e
raise InvalidPublicKey, "Invalid public key: #{e.message}"
end
|
.facet_domain ⇒ Object
31
32
33
|
# File 'lib/two_factor_auth.rb', line 31
def self.facet_domain
@facet_domain
end
|
.facet_domain=(facet_domain) ⇒ Object
20
21
22
23
24
25
26
27
28
29
|
# File 'lib/two_factor_auth.rb', line 20
def self.facet_domain= facet_domain
if facet_domain =~ /\.dev(:\d+)?\/?$/
raise InvalidFacetDomain, "Facet domain needs a real TLD, not .dev. Edit /etc/hosts to make a custom hostname"
end
if facet_domain == "https://www.example.com"
raise InvalidFacetDomain, "You need to cusomize the facet_domain in config/initializers/two_factor_auth.rb"
end
@facet_domain = facet_domain.sub(/\/$/, '')
end
|
.facets ⇒ Object
67
68
69
|
# File 'lib/two_factor_auth.rb', line 67
def self.facets
@facets ||= []
end
|
.facets=(facets) ⇒ Object
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/two_factor_auth.rb', line 56
def self.facets= facets
facets ||= []
if !facets.empty? and facet_domain !~ /\Ahttps:/
raise InvalidFacetDomain, "U2F requires HTTPS to use facet lists"
end
if facets.any? { |f| f !~ /\Ahttps:/ }
raise InvalidFacetListDomain, "URLs in the facet list must all be HTTPS"
end
@facets = facets
end
|
.pubkey_valid?(raw) ⇒ Boolean
97
98
99
100
101
102
|
# File 'lib/two_factor_auth.rb', line 97
def self.pubkey_valid? raw
pk = decode_pubkey raw
pk.on_curve?
rescue InvalidPublicKey
false
end
|
.random_encoded_challenge ⇒ Object
82
83
84
85
86
87
|
# File 'lib/two_factor_auth.rb', line 82
def self.random_encoded_challenge
random = OpenSSL::Random.pseudo_bytes(32)
TwoFactorAuth::websafe_base64_encode(random)
rescue OpenSSL::Random::RandomError
raise CantGenerateRandomNumbers, "Not enough entropy to generate secure challenges"
end
|
.trusted_facet_list_url ⇒ Object
42
43
44
|
# File 'lib/two_factor_auth.rb', line 42
def self.trusted_facet_list_url
@trusted_facet_list_url or app_id_or_facet_list
end
|
.trusted_facet_list_url=(url) ⇒ Object
35
36
37
38
39
40
|
# File 'lib/two_factor_auth.rb', line 35
def self.trusted_facet_list_url= url
if url !~ /\Ahttps:/
raise InvalidTrustedFacetListUrl, "U2F requires HTTPS for facet urls"
end
@trusted_facet_list_url = url
end
|
.websafe_base64_decode(encoded) ⇒ Object
76
77
78
79
80
|
# File 'lib/two_factor_auth.rb', line 76
def self.websafe_base64_decode encoded
padded = encoded.ljust((encoded.length/4.0).ceil * 4, '=')
Base64.urlsafe_decode64(padded)
end
|
.websafe_base64_encode(str) ⇒ Object
71
72
73
74
|
# File 'lib/two_factor_auth.rb', line 71
def self.websafe_base64_encode str
Base64.urlsafe_encode64(str).sub(/=+$/,'')
end
|