web_authn 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/web_authn/attestation_object.rb +33 -0
- data/lib/web_authn/attested_credential_data.rb +49 -0
- data/lib/web_authn/authenticator_data/flags.rb +30 -0
- data/lib/web_authn/authenticator_data.rb +44 -1
- data/lib/web_authn/client_data_json.rb +19 -0
- data/lib/web_authn/context/authentication.rb +54 -0
- data/lib/web_authn/context/registration.rb +23 -0
- data/lib/web_authn/context.rb +43 -0
- data/lib/web_authn.rb +18 -1
- data/samples/authentication_response.rb +46 -0
- data/samples/concept.rb +34 -0
- data/samples/registration_response.rb +37 -0
- data/web_authn.gemspec +4 -2
- metadata +44 -12
- data/bin/console +0 -14
- data/bin/setup +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd0d84bc14a9f6773426c3c509b379268f26b36ee5555fd8c3603a45cc677221
|
4
|
+
data.tar.gz: 124bfe151246e6380a59984f95784f6f39671038ddf98aed99dd8d4b8b59233f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 811e1addfca6f94a181bb59dc02fd1bde4ac6c5692e5a1ed5903eb8b7063db5409061ab2880e3425be6f940aac2394d90d1223dea6d4c0a1262560388ba2fa38
|
7
|
+
data.tar.gz: faf55e02e28045d0cd1a767170bf20f606a9329bd6c351f8d81ea974e6c78d0e08d4d02bd2e714431cddc3ff3fd0651106325487e8c257da3fecc2072ebcf356
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.1
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class AttestationObject
|
3
|
+
attr_accessor :format, :attestation_statement, :authenticator_data
|
4
|
+
alias_method :fmt, :format
|
5
|
+
alias_method :att_stmt, :attestation_statement
|
6
|
+
alias_method :auth_data, :authenticator_data
|
7
|
+
|
8
|
+
%i(credential_id rp_id_hash flags public_key sign_count).each do |method|
|
9
|
+
delegate method, to: :authenticator_data
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(attrs)
|
13
|
+
self.format = attrs[:fmt]
|
14
|
+
self.attestation_statement = case format
|
15
|
+
when 'none'
|
16
|
+
nil
|
17
|
+
when 'packed', 'tpm', 'android-key', 'android-safetynet', 'fido-u2f'
|
18
|
+
raise "Unsupported Attestation Format: #{attestation_object[:fmt]}"
|
19
|
+
else
|
20
|
+
raise 'Unknown Attestation Format'
|
21
|
+
end
|
22
|
+
self.authenticator_data = AuthenticatorData.decode attrs[:authData]
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def decode(encoded_attestation_object)
|
27
|
+
new CBOR.decode(
|
28
|
+
Base64.urlsafe_decode64 encoded_attestation_object
|
29
|
+
).with_indifferent_access
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class AttestedCredentialData
|
3
|
+
attr_accessor :aaguid, :credential_id, :public_key
|
4
|
+
|
5
|
+
def initialize(aaguid:, credential_id:, public_key:)
|
6
|
+
self.aaguid = aaguid
|
7
|
+
self.credential_id = credential_id
|
8
|
+
self.public_key = public_key
|
9
|
+
end
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def decode(attested_credential_data)
|
13
|
+
length = (
|
14
|
+
((attested_credential_data.getbyte(16) << 8) & 0xFF) +
|
15
|
+
(attested_credential_data.getbyte(17) & 0xFF)
|
16
|
+
)
|
17
|
+
aaguid,
|
18
|
+
credential_id,
|
19
|
+
_encoded_cose_key_ = [
|
20
|
+
attested_credential_data.byteslice(0...16),
|
21
|
+
attested_credential_data.byteslice(18...(18 + length)),
|
22
|
+
attested_credential_data.byteslice((18 + length)..-1),
|
23
|
+
]
|
24
|
+
cose_key = COSE::Key::EC2.from_cbor(_encoded_cose_key_)
|
25
|
+
crv = case cose_key.curve
|
26
|
+
when 1
|
27
|
+
:'P-256'
|
28
|
+
when 2
|
29
|
+
:'P-384'
|
30
|
+
when 3
|
31
|
+
:'P-521'
|
32
|
+
else
|
33
|
+
raise 'Non-supported EC curve'
|
34
|
+
end
|
35
|
+
jwk = JSON::JWK.new(
|
36
|
+
kty: :EC,
|
37
|
+
crv: crv,
|
38
|
+
x: Base64.urlsafe_encode64(cose_key.x_coordinate, padding: false),
|
39
|
+
y: Base64.urlsafe_encode64(cose_key.y_coordinate, padding: false),
|
40
|
+
)
|
41
|
+
new(
|
42
|
+
aaguid: Base64.urlsafe_encode64(aaguid, padding: false),
|
43
|
+
credential_id: Base64.urlsafe_encode64(credential_id, padding: false),
|
44
|
+
public_key: jwk.to_key
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class AuthenticatorData
|
3
|
+
class Flags
|
4
|
+
_flags_ = [:up, :uv, :at, :ex]
|
5
|
+
attr_accessor *_flags_
|
6
|
+
_flags_.each do |flag|
|
7
|
+
alias_method :"#{flag}?", flag
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(up:, uv:, at:, ex:)
|
11
|
+
self.up = up
|
12
|
+
self.uv = uv
|
13
|
+
self.at = at
|
14
|
+
self.ex = ex
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def decode(input)
|
19
|
+
bit_array = input.getbyte(0)
|
20
|
+
new(
|
21
|
+
up: bit_array[0] == 1,
|
22
|
+
uv: bit_array[2] == 1,
|
23
|
+
at: bit_array[6] == 1,
|
24
|
+
ex: bit_array[7] == 1
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,4 +1,47 @@
|
|
1
1
|
module WebAuthn
|
2
|
-
class
|
2
|
+
class AuthenticatorData
|
3
|
+
attr_accessor :rp_id_hash, :flags, :sign_count, :attested_credential_data
|
4
|
+
|
5
|
+
%i(credential_id public_key).each do |method|
|
6
|
+
delegate method, to: :attested_credential_data, allow_nil: true
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(rp_id_hash:, flags:, sign_count:, attested_credential_data: nil)
|
10
|
+
self.rp_id_hash = rp_id_hash
|
11
|
+
self.flags = flags
|
12
|
+
self.sign_count = sign_count
|
13
|
+
self.attested_credential_data = attested_credential_data
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def decode(auth_data)
|
18
|
+
rp_id_hash,
|
19
|
+
_flags_,
|
20
|
+
sign_count = [
|
21
|
+
auth_data.byteslice(0...32),
|
22
|
+
auth_data.byteslice(32),
|
23
|
+
auth_data.byteslice(33...37)
|
24
|
+
]
|
25
|
+
flags = Flags.decode(_flags_)
|
26
|
+
attested_credential_data = if flags.at?
|
27
|
+
if flags.ex?
|
28
|
+
raise 'Extension Data Not Supported Yet'
|
29
|
+
else
|
30
|
+
AttestedCredentialData.decode auth_data.byteslice(37..-1)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
new(
|
37
|
+
rp_id_hash: Base64.urlsafe_encode64(rp_id_hash, padding: false),
|
38
|
+
flags: flags,
|
39
|
+
sign_count: sign_count.unpack('N1').first,
|
40
|
+
attested_credential_data: attested_credential_data
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
3
44
|
end
|
4
45
|
end
|
46
|
+
|
47
|
+
require 'web_authn/authenticator_data/flags'
|
@@ -1,4 +1,23 @@
|
|
1
1
|
module WebAuthn
|
2
2
|
class ClientDataJSON
|
3
|
+
attr_accessor :type, :origin, :challenge, :raw
|
4
|
+
|
5
|
+
def initialize(attrs = {})
|
6
|
+
self.type = attrs[:type]
|
7
|
+
self.origin = attrs[:origin]
|
8
|
+
self.challenge = attrs[:challenge]
|
9
|
+
self.raw = attrs[:raw]
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def decode(encoded_client_data_json)
|
14
|
+
raw_client_data_json = Base64.urlsafe_decode64 encoded_client_data_json
|
15
|
+
new JSON.parse(
|
16
|
+
raw_client_data_json
|
17
|
+
).merge(
|
18
|
+
raw: raw_client_data_json
|
19
|
+
).with_indifferent_access
|
20
|
+
end
|
21
|
+
end
|
3
22
|
end
|
4
23
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class Context
|
3
|
+
class Authentication < Context
|
4
|
+
attr_accessor :authenticator_data
|
5
|
+
|
6
|
+
# TODO: will need more methods, or let developers access deep methods by themselves.
|
7
|
+
%i(rp_id_hash flags sign_count).each do |method|
|
8
|
+
delegate method, to: :authenticator_data
|
9
|
+
end
|
10
|
+
|
11
|
+
def authentication?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify!(encoded_authenticator_data, public_key:, sign_count:, signature:)
|
16
|
+
raw_authenticator_data = Base64.urlsafe_decode64 encoded_authenticator_data
|
17
|
+
self.authenticator_data = AuthenticatorData.decode(
|
18
|
+
raw_authenticator_data
|
19
|
+
)
|
20
|
+
verify_sign_count!(sign_count, authenticator_data.sign_count)
|
21
|
+
verify_signature!(raw_authenticator_data, client_data_json.raw, public_key, signature)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def verify_sign_count!(before, current)
|
28
|
+
if before == 0 && current == 0
|
29
|
+
self # NOTE: no counter supported on the authenticator
|
30
|
+
elsif before < current
|
31
|
+
self
|
32
|
+
else
|
33
|
+
raise 'Invalid Sign Count'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def verify_signature!(raw_authenticator_data, raw_client_data_json, public_key, signature)
|
38
|
+
signature_base_string = [
|
39
|
+
raw_authenticator_data,
|
40
|
+
OpenSSL::Digest::SHA256.digest(raw_client_data_json)
|
41
|
+
].join
|
42
|
+
result = public_key.dsa_verify_asn1(
|
43
|
+
OpenSSL::Digest::SHA256.digest(signature_base_string),
|
44
|
+
Base64.urlsafe_decode64(signature)
|
45
|
+
)
|
46
|
+
if result
|
47
|
+
self
|
48
|
+
else
|
49
|
+
raise 'Invalid Signature'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class Context
|
3
|
+
class Registration < Context
|
4
|
+
attr_accessor :attestation_object
|
5
|
+
|
6
|
+
# TODO: will need more methods, or let developers access deep methods by themselves.
|
7
|
+
%i(credential_id rp_id_hash flags public_key sign_count).each do |method|
|
8
|
+
delegate method, to: :attestation_object
|
9
|
+
end
|
10
|
+
|
11
|
+
def registration?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def verify!(encoded_attestation_object)
|
16
|
+
self.attestation_object = AttestationObject.decode(
|
17
|
+
encoded_attestation_object
|
18
|
+
)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module WebAuthn
|
2
|
+
class Context
|
3
|
+
attr_accessor :client_data_json
|
4
|
+
|
5
|
+
def initialize(client_data_json)
|
6
|
+
self.client_data_json = client_data_json
|
7
|
+
end
|
8
|
+
|
9
|
+
def verify_session!(origin:, challenge:)
|
10
|
+
raise 'Invalid Client Data JSON Origin' unless client_data_json.origin == origin
|
11
|
+
raise 'Invalid Client Data JSON Session' unless client_data_json.challenge == challenge
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def registration?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def authentication?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def for(encoded_client_data_json, origin:, challenge:)
|
25
|
+
client_data_json = ClientDataJSON.decode encoded_client_data_json
|
26
|
+
|
27
|
+
context = case client_data_json.type
|
28
|
+
when 'webauthn.create'
|
29
|
+
Registration.new(client_data_json)
|
30
|
+
when 'webauthn.get'
|
31
|
+
Authentication.new(client_data_json)
|
32
|
+
else
|
33
|
+
raise 'Unknown Client Data JSON Type'
|
34
|
+
end
|
35
|
+
|
36
|
+
context.verify_session!(origin: origin, challenge: challenge)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
require 'web_authn/context/authentication'
|
43
|
+
require 'web_authn/context/registration'
|
data/lib/web_authn.rb
CHANGED
@@ -1,7 +1,24 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext'
|
3
|
+
require 'cbor'
|
4
|
+
require 'cose'
|
5
|
+
require 'cose/key/ec2'
|
6
|
+
require 'json/jwt'
|
7
|
+
|
1
8
|
module WebAuthn
|
2
|
-
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def context_for(encoded_client_data_json, origin:, challenge:)
|
12
|
+
Context.for(
|
13
|
+
encoded_client_data_json,
|
14
|
+
origin: origin,
|
15
|
+
challenge: challenge
|
16
|
+
)
|
17
|
+
end
|
3
18
|
end
|
4
19
|
|
5
20
|
require 'web_authn/attestation_object'
|
21
|
+
require 'web_authn/attested_credential_data'
|
6
22
|
require 'web_authn/authenticator_data'
|
7
23
|
require 'web_authn/client_data_json'
|
24
|
+
require 'web_authn/context'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'web_authn'
|
2
|
+
|
3
|
+
authenticator_data = 'MsuA3KzDw1JGLLAfO_4wLebzcS8w_SDs0Zw7pbhYlJUBAAAAOw'
|
4
|
+
|
5
|
+
signature = 'MEUCIQDXp8Wqzz3ZYV7avKvH3R3XQhW7xPYb5Cq2nx3gpflDGwIgPN0tSy2mmgpI06IIKmjrIUxCvL4Rfc53mFXfVd_yL58'
|
6
|
+
sign_count = 0
|
7
|
+
|
8
|
+
client_data_json = 'eyJjaGFsbGVuZ2UiOiJjbUZ1Wkc5dExYTjBjbWx1WnkxblpXNWxjbUYwWldRdFlua3RjbkF0YzJWeWRtVnkiLCJvcmlnaW4iOiJodHRwczovL3dlYi1hdXRobi5zZWxmLWlzc3VlZC5hcHAiLCJ0eXBlIjoid2ViYXV0aG4uZ2V0In0'
|
9
|
+
|
10
|
+
origin = 'https://web-authn.self-issued.app'
|
11
|
+
challenge = 'cmFuZG9tLXN0cmluZy1nZW5lcmF0ZWQtYnktcnAtc2VydmVy'
|
12
|
+
|
13
|
+
public_key = OpenSSL::PKey::EC.new <<-PEM
|
14
|
+
-----BEGIN PUBLIC KEY-----
|
15
|
+
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMpNU/8TjYoyN8FlhZ+YsOMAvyfQ4
|
16
|
+
i6/JN0/DPXuZMoxLvdb1vjh7vPUt2Osw3Bq+0NZsx3U/8kmpFuwsZhTi9A==
|
17
|
+
-----END PUBLIC KEY-----
|
18
|
+
PEM
|
19
|
+
|
20
|
+
context = WebAuthn.context_for(
|
21
|
+
client_data_json,
|
22
|
+
origin: origin,
|
23
|
+
challenge: challenge,
|
24
|
+
)
|
25
|
+
raise unless context.authentication?
|
26
|
+
|
27
|
+
context.verify!(
|
28
|
+
authenticator_data,
|
29
|
+
public_key: public_key,
|
30
|
+
sign_count: sign_count,
|
31
|
+
signature: signature
|
32
|
+
)
|
33
|
+
|
34
|
+
puts <<-OUT
|
35
|
+
# RP ID Hash
|
36
|
+
#{context.rp_id_hash}
|
37
|
+
|
38
|
+
# Flags
|
39
|
+
up: #{context.flags.up}
|
40
|
+
uv: #{context.flags.uv}
|
41
|
+
at: #{context.flags.at}
|
42
|
+
ex: #{context.flags.ex}
|
43
|
+
|
44
|
+
# Sign Count
|
45
|
+
#{context.sign_count}
|
46
|
+
OUT
|
data/samples/concept.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# Common
|
2
|
+
context = WebAuthn.context_for(
|
3
|
+
client_data_json,
|
4
|
+
origin: request.base_url,
|
5
|
+
challenge: session[:challenge],
|
6
|
+
)
|
7
|
+
|
8
|
+
# Registration
|
9
|
+
raise unless context.registration?
|
10
|
+
|
11
|
+
context.verify!(params[:attestation_object])
|
12
|
+
current_account.fido_authenticators.create(
|
13
|
+
credential_id: context.credential_id,
|
14
|
+
public_key: context.public_key.to_pem,
|
15
|
+
sign_count: context.sign_count
|
16
|
+
)
|
17
|
+
|
18
|
+
# Authentication
|
19
|
+
raise unless context.authentication?
|
20
|
+
|
21
|
+
fido_authentiator = FIDO::Authenticatior.find_by(credential_id: params[:credential_id])
|
22
|
+
raise unless fido_authentiator.present?
|
23
|
+
|
24
|
+
context.verify!(
|
25
|
+
authenticator_data,
|
26
|
+
public_key: fido_authentiator.public_key,
|
27
|
+
sign_count: fido_authentiator.sign_count,
|
28
|
+
signature: params[:signature]
|
29
|
+
)
|
30
|
+
|
31
|
+
fido_authentiator.update!(
|
32
|
+
sign_count: context.sign_count
|
33
|
+
)
|
34
|
+
authenticate authenticator.user
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'web_authn'
|
2
|
+
|
3
|
+
attestation_object = 'o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjEMsuA3KzDw1JGLLAfO_4wLebzcS8w_SDs0Zw7pbhYlJVBAAAAMAAAAAAAAAAAAAAAAAAAAAAAQM1zXqvmYeVH9o2q1YcBZDSlkhvVs_2RjnKESVUktkQwQnYcU8jdo-duNLKrIOZNg0g4RCm0UMDZxtdXhR2bCu2lAQIDJiABIVggDMGhDLXoZit2uSMLyL-_emlFrGzlH7b2KpKpgYNzPRYiWCAl795OxcS2QimEnC9Jl_pNG3Gy_9O6m3_GbZdGsk90aw'
|
4
|
+
|
5
|
+
client_data_json = 'eyJjaGFsbGVuZ2UiOiJjbUZ1Wkc5dExYTjBjbWx1WnkxblpXNWxjbUYwWldRdFlua3RjbkF0YzJWeWRtVnkiLCJuZXdfa2V5c19tYXlfYmVfYWRkZWRfaGVyZSI6ImRvIG5vdCBjb21wYXJlIGNsaWVudERhdGFKU09OIGFnYWluc3QgYSB0ZW1wbGF0ZS4gU2VlIGh0dHBzOi8vZ29vLmdsL3lhYlBleCIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViLWF1dGhuLnNlbGYtaXNzdWVkLmFwcCIsInR5cGUiOiJ3ZWJhdXRobi5jcmVhdGUifQ'
|
6
|
+
|
7
|
+
origin = 'https://web-authn.self-issued.app'
|
8
|
+
challenge = 'cmFuZG9tLXN0cmluZy1nZW5lcmF0ZWQtYnktcnAtc2VydmVy'
|
9
|
+
|
10
|
+
context = WebAuthn.context_for(
|
11
|
+
client_data_json,
|
12
|
+
origin: origin,
|
13
|
+
challenge: challenge
|
14
|
+
)
|
15
|
+
raise unless context.registration?
|
16
|
+
|
17
|
+
context.verify! attestation_object
|
18
|
+
|
19
|
+
puts <<-OUT
|
20
|
+
# RP ID Hash
|
21
|
+
#{context.rp_id_hash}
|
22
|
+
|
23
|
+
# Flags
|
24
|
+
up: #{context.flags.up}
|
25
|
+
uv: #{context.flags.uv}
|
26
|
+
at: #{context.flags.at}
|
27
|
+
ex: #{context.flags.ex}
|
28
|
+
|
29
|
+
# Credential ID
|
30
|
+
#{context.credential_id}
|
31
|
+
|
32
|
+
# Public Key
|
33
|
+
#{context.public_key.to_pem}
|
34
|
+
|
35
|
+
# Sign Count
|
36
|
+
#{context.sign_count}
|
37
|
+
OUT
|
data/web_authn.gemspec
CHANGED
@@ -12,8 +12,10 @@ Gem::Specification.new do |gem|
|
|
12
12
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
13
13
|
gem.require_paths = ['lib']
|
14
14
|
gem.required_ruby_version = '>= 2.3'
|
15
|
-
gem.add_runtime_dependency '
|
16
|
-
gem.add_runtime_dependency 'cbor'
|
15
|
+
gem.add_runtime_dependency 'activesupport'
|
16
|
+
gem.add_runtime_dependency 'cbor'
|
17
|
+
gem.add_runtime_dependency 'cose'
|
18
|
+
gem.add_runtime_dependency 'json-jwt'
|
17
19
|
gem.add_development_dependency 'rake', '~> 10.0'
|
18
20
|
gem.add_development_dependency 'simplecov'
|
19
21
|
gem.add_development_dependency 'rspec'
|
metadata
CHANGED
@@ -1,43 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web_authn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nov matake
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: cbor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: cose
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json-jwt
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
34
62
|
type: :runtime
|
35
63
|
prerelease: false
|
36
64
|
version_requirements: !ruby/object:Gem::Requirement
|
37
65
|
requirements:
|
38
66
|
- - ">="
|
39
67
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0
|
68
|
+
version: '0'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: rake
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,9 +125,7 @@ dependencies:
|
|
97
125
|
description: W3C WebAuthn (a.k.a. FIDO2) RP library in Ruby
|
98
126
|
email:
|
99
127
|
- nov@matake.jp
|
100
|
-
executables:
|
101
|
-
- console
|
102
|
-
- setup
|
128
|
+
executables: []
|
103
129
|
extensions: []
|
104
130
|
extra_rdoc_files: []
|
105
131
|
files:
|
@@ -111,12 +137,18 @@ files:
|
|
111
137
|
- README.md
|
112
138
|
- Rakefile
|
113
139
|
- VERSION
|
114
|
-
- bin/console
|
115
|
-
- bin/setup
|
116
140
|
- lib/web_authn.rb
|
117
141
|
- lib/web_authn/attestation_object.rb
|
142
|
+
- lib/web_authn/attested_credential_data.rb
|
118
143
|
- lib/web_authn/authenticator_data.rb
|
144
|
+
- lib/web_authn/authenticator_data/flags.rb
|
119
145
|
- lib/web_authn/client_data_json.rb
|
146
|
+
- lib/web_authn/context.rb
|
147
|
+
- lib/web_authn/context/authentication.rb
|
148
|
+
- lib/web_authn/context/registration.rb
|
149
|
+
- samples/authentication_response.rb
|
150
|
+
- samples/concept.rb
|
151
|
+
- samples/registration_response.rb
|
120
152
|
- spec/spec_helper.rb
|
121
153
|
- spec/web_authn_spec.rb
|
122
154
|
- web_authn.gemspec
|
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "web_authn"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|