unmagic-passkeys 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +9 -0
- data/LICENSE +21 -0
- data/NOTICE +9 -0
- data/README.md +151 -0
- data/app/assets/javascripts/unmagic/passkeys/passkey.js +236 -0
- data/app/assets/javascripts/unmagic/passkeys/webauthn.js +83 -0
- data/app/controllers/unmagic/passkeys/challenges_controller.rb +49 -0
- data/app/models/unmagic/passkeys/credential.rb +103 -0
- data/config/importmap.rb +5 -0
- data/config/routes.rb +2 -0
- data/lib/generators/unmagic/passkeys/install_generator.rb +51 -0
- data/lib/generators/unmagic/passkeys/templates/POST_INSTALL +19 -0
- data/lib/generators/unmagic/passkeys/templates/create_unmagic_passkeys_credentials.rb.tt +19 -0
- data/lib/unmagic/passkeys/engine.rb +78 -0
- data/lib/unmagic/passkeys/form_helper.rb +128 -0
- data/lib/unmagic/passkeys/holder.rb +143 -0
- data/lib/unmagic/passkeys/request.rb +77 -0
- data/lib/unmagic/passkeys/version.rb +5 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/assertion_response.rb +88 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/attestation.rb +73 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/attestation_response.rb +71 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/attestation_verifiers/none.rb +24 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/data.rb +174 -0
- data/lib/unmagic/passkeys/web_authn/authenticator/response.rb +141 -0
- data/lib/unmagic/passkeys/web_authn/cbor_decoder.rb +269 -0
- data/lib/unmagic/passkeys/web_authn/cose_key.rb +183 -0
- data/lib/unmagic/passkeys/web_authn/current.rb +19 -0
- data/lib/unmagic/passkeys/web_authn/public_key_credential/creation_options.rb +109 -0
- data/lib/unmagic/passkeys/web_authn/public_key_credential/options.rb +80 -0
- data/lib/unmagic/passkeys/web_authn/public_key_credential/request_options.rb +55 -0
- data/lib/unmagic/passkeys/web_authn/public_key_credential.rb +153 -0
- data/lib/unmagic/passkeys/web_authn/relying_party.rb +50 -0
- data/lib/unmagic/passkeys/web_authn.rb +84 -0
- data/lib/unmagic/passkeys.rb +41 -0
- metadata +152 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# = Action Pack WebAuthn
|
|
2
|
+
#
|
|
3
|
+
# Provides a pure-Ruby implementation of the WebAuthn (Web Authentication)
|
|
4
|
+
# specification for passkey registration and authentication. This module
|
|
5
|
+
# is the top-level namespace for all WebAuthn components and provides
|
|
6
|
+
# shared utilities used across ceremonies.
|
|
7
|
+
#
|
|
8
|
+
# == Components
|
|
9
|
+
#
|
|
10
|
+
# [Unmagic::Passkeys::WebAuthn::RelyingParty]
|
|
11
|
+
# Identifies your application to authenticators.
|
|
12
|
+
#
|
|
13
|
+
# [Unmagic::Passkeys::WebAuthn::PublicKeyCredential]
|
|
14
|
+
# Orchestrates registration and authentication ceremonies.
|
|
15
|
+
#
|
|
16
|
+
# [Unmagic::Passkeys::WebAuthn::Authenticator]
|
|
17
|
+
# Parses and validates authenticator responses.
|
|
18
|
+
#
|
|
19
|
+
# [Unmagic::Passkeys::WebAuthn::CborDecoder]
|
|
20
|
+
# Decodes CBOR-encoded data from authenticators.
|
|
21
|
+
#
|
|
22
|
+
# [Unmagic::Passkeys::WebAuthn::CoseKey]
|
|
23
|
+
# Parses COSE public keys into OpenSSL key objects.
|
|
24
|
+
#
|
|
25
|
+
# == Extending Attestation Formats
|
|
26
|
+
#
|
|
27
|
+
# By default only the "none" attestation format is supported. Register
|
|
28
|
+
# additional verifiers with:
|
|
29
|
+
#
|
|
30
|
+
# Unmagic::Passkeys::WebAuthn.register_attestation_verifier("packed", MyPackedVerifier.new)
|
|
31
|
+
#
|
|
32
|
+
module Unmagic::Passkeys::WebAuthn
|
|
33
|
+
class InvalidResponseError < StandardError; end
|
|
34
|
+
class InvalidCborError < StandardError; end
|
|
35
|
+
class InvalidKeyError < StandardError; end
|
|
36
|
+
class UnsupportedKeyTypeError < StandardError; end
|
|
37
|
+
class InvalidOptionsError < StandardError; end
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
# Returns a new RelyingParty configured from the current request context.
|
|
41
|
+
def relying_party
|
|
42
|
+
RelyingParty.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Returns the MessageVerifier used to sign and verify WebAuthn challenges.
|
|
46
|
+
def challenge_verifier
|
|
47
|
+
Rails.application.message_verifier("action_pack.webauthn.challenge")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the registry of attestation format verifiers, keyed by format
|
|
51
|
+
# string (e.g., "none", "packed"). Only "none" is registered by default.
|
|
52
|
+
def attestation_verifiers
|
|
53
|
+
@attestation_verifiers ||= {
|
|
54
|
+
"none" => Authenticator::AttestationVerifiers::None.new
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Registers a custom attestation verifier for the given +format+.
|
|
59
|
+
# The +verifier+ must respond to +verify!(attestation, client_data_json:)+.
|
|
60
|
+
def register_attestation_verifier(format, verifier)
|
|
61
|
+
attestation_verifiers[format.to_s] = verifier
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Implicit namespaces for the ceremony files required below (no Zeitwerk in lib/).
|
|
66
|
+
module Authenticator
|
|
67
|
+
module AttestationVerifiers; end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
require_relative "web_authn/current"
|
|
72
|
+
require_relative "web_authn/relying_party"
|
|
73
|
+
require_relative "web_authn/cbor_decoder"
|
|
74
|
+
require_relative "web_authn/cose_key"
|
|
75
|
+
require_relative "web_authn/public_key_credential"
|
|
76
|
+
require_relative "web_authn/public_key_credential/options"
|
|
77
|
+
require_relative "web_authn/public_key_credential/creation_options"
|
|
78
|
+
require_relative "web_authn/public_key_credential/request_options"
|
|
79
|
+
require_relative "web_authn/authenticator/response"
|
|
80
|
+
require_relative "web_authn/authenticator/data"
|
|
81
|
+
require_relative "web_authn/authenticator/attestation"
|
|
82
|
+
require_relative "web_authn/authenticator/attestation_verifiers/none"
|
|
83
|
+
require_relative "web_authn/authenticator/attestation_response"
|
|
84
|
+
require_relative "web_authn/authenticator/assertion_response"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support"
|
|
4
|
+
require "active_support/all"
|
|
5
|
+
require "active_model"
|
|
6
|
+
require "openssl"
|
|
7
|
+
require "base64"
|
|
8
|
+
require "json"
|
|
9
|
+
require "digest"
|
|
10
|
+
|
|
11
|
+
require "unmagic/passkeys/version"
|
|
12
|
+
require "unmagic/passkeys/web_authn"
|
|
13
|
+
require "unmagic/passkeys/holder"
|
|
14
|
+
require "unmagic/passkeys/request"
|
|
15
|
+
require "unmagic/passkeys/form_helper"
|
|
16
|
+
require "unmagic/passkeys/engine" if defined?(::Rails::Engine)
|
|
17
|
+
|
|
18
|
+
module Unmagic
|
|
19
|
+
# Passkey (WebAuthn) authentication for Rails. The module methods are thin delegators to the
|
|
20
|
+
# +Unmagic::Passkeys::Credential+ Active Record model so host code reads as
|
|
21
|
+
# +Unmagic::Passkeys.authenticate(params)+.
|
|
22
|
+
module Passkeys
|
|
23
|
+
class << self
|
|
24
|
+
def registration_options(**options)
|
|
25
|
+
Credential.registration_options(**options)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def register(passkey, **attributes)
|
|
29
|
+
Credential.register(passkey, **attributes)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def authentication_options(**options)
|
|
33
|
+
Credential.authentication_options(**options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def authenticate(passkey)
|
|
37
|
+
Credential.authenticate(passkey)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: unmagic-passkeys
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Keith Pitt
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-26 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: activerecord
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '7.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '7.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: actionpack
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '7.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '7.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: actionview
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '7.1'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '7.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: activesupport
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '7.1'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '7.1'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: railties
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '7.1'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '7.1'
|
|
83
|
+
description: A Rails engine that adds passkey registration and authentication backed
|
|
84
|
+
by Active Record. Self-contained, pure-Ruby WebAuthn ceremonies (CBOR, COSE, attestation
|
|
85
|
+
and assertion verification) with stateless signed challenges — no external gems.
|
|
86
|
+
email:
|
|
87
|
+
- keith@unreasonable-magic.com
|
|
88
|
+
executables: []
|
|
89
|
+
extensions: []
|
|
90
|
+
extra_rdoc_files: []
|
|
91
|
+
files:
|
|
92
|
+
- CHANGELOG.md
|
|
93
|
+
- LICENSE
|
|
94
|
+
- NOTICE
|
|
95
|
+
- README.md
|
|
96
|
+
- app/assets/javascripts/unmagic/passkeys/passkey.js
|
|
97
|
+
- app/assets/javascripts/unmagic/passkeys/webauthn.js
|
|
98
|
+
- app/controllers/unmagic/passkeys/challenges_controller.rb
|
|
99
|
+
- app/models/unmagic/passkeys/credential.rb
|
|
100
|
+
- config/importmap.rb
|
|
101
|
+
- config/routes.rb
|
|
102
|
+
- lib/generators/unmagic/passkeys/install_generator.rb
|
|
103
|
+
- lib/generators/unmagic/passkeys/templates/POST_INSTALL
|
|
104
|
+
- lib/generators/unmagic/passkeys/templates/create_unmagic_passkeys_credentials.rb.tt
|
|
105
|
+
- lib/unmagic/passkeys.rb
|
|
106
|
+
- lib/unmagic/passkeys/engine.rb
|
|
107
|
+
- lib/unmagic/passkeys/form_helper.rb
|
|
108
|
+
- lib/unmagic/passkeys/holder.rb
|
|
109
|
+
- lib/unmagic/passkeys/request.rb
|
|
110
|
+
- lib/unmagic/passkeys/version.rb
|
|
111
|
+
- lib/unmagic/passkeys/web_authn.rb
|
|
112
|
+
- lib/unmagic/passkeys/web_authn/authenticator/assertion_response.rb
|
|
113
|
+
- lib/unmagic/passkeys/web_authn/authenticator/attestation.rb
|
|
114
|
+
- lib/unmagic/passkeys/web_authn/authenticator/attestation_response.rb
|
|
115
|
+
- lib/unmagic/passkeys/web_authn/authenticator/attestation_verifiers/none.rb
|
|
116
|
+
- lib/unmagic/passkeys/web_authn/authenticator/data.rb
|
|
117
|
+
- lib/unmagic/passkeys/web_authn/authenticator/response.rb
|
|
118
|
+
- lib/unmagic/passkeys/web_authn/cbor_decoder.rb
|
|
119
|
+
- lib/unmagic/passkeys/web_authn/cose_key.rb
|
|
120
|
+
- lib/unmagic/passkeys/web_authn/current.rb
|
|
121
|
+
- lib/unmagic/passkeys/web_authn/public_key_credential.rb
|
|
122
|
+
- lib/unmagic/passkeys/web_authn/public_key_credential/creation_options.rb
|
|
123
|
+
- lib/unmagic/passkeys/web_authn/public_key_credential/options.rb
|
|
124
|
+
- lib/unmagic/passkeys/web_authn/public_key_credential/request_options.rb
|
|
125
|
+
- lib/unmagic/passkeys/web_authn/relying_party.rb
|
|
126
|
+
homepage: https://github.com/unreasonable-magic/unmagic-passkeys
|
|
127
|
+
licenses:
|
|
128
|
+
- MIT
|
|
129
|
+
metadata:
|
|
130
|
+
homepage_uri: https://github.com/unreasonable-magic/unmagic-passkeys
|
|
131
|
+
source_code_uri: https://github.com/unreasonable-magic/unmagic-passkeys
|
|
132
|
+
changelog_uri: https://github.com/unreasonable-magic/unmagic-passkeys/blob/main/CHANGELOG.md
|
|
133
|
+
post_install_message:
|
|
134
|
+
rdoc_options: []
|
|
135
|
+
require_paths:
|
|
136
|
+
- lib
|
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
138
|
+
requirements:
|
|
139
|
+
- - ">="
|
|
140
|
+
- !ruby/object:Gem::Version
|
|
141
|
+
version: '3.2'
|
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
|
+
requirements:
|
|
144
|
+
- - ">="
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '0'
|
|
147
|
+
requirements: []
|
|
148
|
+
rubygems_version: 3.5.22
|
|
149
|
+
signing_key:
|
|
150
|
+
specification_version: 4
|
|
151
|
+
summary: Passkey (WebAuthn) authentication for Rails, with no external dependencies
|
|
152
|
+
test_files: []
|