action_auth 1.3.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9adce01d4651e8af6f14f8738bb4f762512485d75640d9fd1993ef68fa6c37a
4
- data.tar.gz: 9b0c5e31a61b57efef137cb9429de5015390da6a01ce6ce1bad200a3b881ccbb
3
+ metadata.gz: f2082f44369afe3132a783d6bd8477b7df97188bf29c55791a131ed4b5cc8034
4
+ data.tar.gz: ca85a89d45d638a85bef5a9f18c5e881deea0d716feddc5ac33d49c687e0f0d7
5
5
  SHA512:
6
- metadata.gz: 132b6dad72a8a2d4531febde70f32cb3e793ab98a23d48567a9ec7c2e62655737e9c5c608f302e011c10018e787422c2d4205a1739feea3aeb7849e82ea19c82
7
- data.tar.gz: a4fed6bd6daf8ae5c2de6cdf3e4b46090a349a4426155d368d9ec94713e0b2e00288c4c199724253a9f96ac2722c0647e3382a2c1b0b23bdb196756a4d7b00c0
6
+ metadata.gz: 6409ba5c720feb68d07b4e9dc4a8fa1d234e990fdcfe3fe710410f3671ae4d044ff58784c0015a67dc07083a0b4b840fcbcdc2494191bcfb852208ede5c0fadf
7
+ data.tar.gz: b156d5b0c0e6edc056b5935c3f18ec5677ea925e3dcfe8979e13048e2db0526ebcfed8f91b33f6d1109daf87cef8f510b7367bf488740a5de9d5593a81f9adaf
data/README.md CHANGED
@@ -102,6 +102,7 @@ ActionAuth.configure do |config|
102
102
  config.allow_user_deletion = true
103
103
  config.default_from_email = "from@example.com"
104
104
  config.magic_link_enabled = true
105
+ config.passkey_only = true # Allows sign in with only a passkey
105
106
  config.verify_email_on_sign_in = true
106
107
  config.webauthn_enabled = true
107
108
  config.webauthn_origin = "http://localhost:3000" # or "https://example.com"
@@ -127,6 +128,8 @@ These are the planned features for ActionAuth. The ones that are checked off are
127
128
 
128
129
  ✅ - Passkeys/Hardware Security Keys
129
130
 
131
+ ✅ - Passkeys sign in without email/password
132
+
130
133
  ✅ - Magic Links
131
134
 
132
135
  ⏳ - OAuth with Google, Facebook, Github, Twitter, etc.
@@ -141,8 +144,6 @@ These are the planned features for ActionAuth. The ones that are checked off are
141
144
 
142
145
  ⏳ - Account Impersonation
143
146
 
144
-
145
-
146
147
  ## Usage
147
148
 
148
149
  ### Routes
@@ -43,7 +43,9 @@ const Credential = {
43
43
 
44
44
  get: function (credentialOptions) {
45
45
  const self = this;
46
- const webauthnUrl = document.querySelector('meta[name="webauthn_auth_url"]').getAttribute("content");
46
+ const webauthnUrlTag = document.querySelector('meta[name="passkey_auth_url"]') ||
47
+ document.querySelector('meta[name="webauthn_auth_url"]');
48
+ const webauthnUrl = webauthnUrlTag.getAttribute("content");
47
49
  WebAuthnJSON.get({ "publicKey": credentialOptions }).then(function (credential) {
48
50
  self.callback(webauthnUrl, credential, "/");
49
51
  });
@@ -36,6 +36,7 @@ body {
36
36
  margin-right: 5px;
37
37
  }
38
38
  }
39
+
39
40
  .container-fluid {
40
41
  -webkit-text-size-adjust: 100%;
41
42
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
@@ -78,6 +79,11 @@ input[type="password"] {
78
79
  margin-bottom: 1rem !important;
79
80
  }
80
81
 
82
+ .mx-3 {
83
+ margin-left: 1rem !important;
84
+ margin-right: 1rem !important;
85
+ }
86
+
81
87
  .btn {
82
88
  padding: 0.375rem 0.75rem;
83
89
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -0,0 +1,24 @@
1
+ module ActionAuth
2
+ module Sessions
3
+ class PasskeysController < ApplicationController
4
+ def new
5
+ get_options = WebAuthn::Credential.options_for_get
6
+ session[:current_challenge] = get_options.challenge
7
+ @options = get_options
8
+ end
9
+
10
+ def create
11
+ webauthn_credential = WebAuthn::Credential.from_get(params)
12
+ credential = WebauthnCredential.find_by(external_id: webauthn_credential.id)
13
+ user = User.find_by(id: credential&.user_id)
14
+ if credential && user
15
+ session = user.sessions.create
16
+ cookies.signed.permanent[:session_token] = { value: session.id, httponly: true }
17
+ redirect_to main_app.root_path(format: :html), notice: "Signed in successfully"
18
+ else
19
+ redirect_to sign_in_path(format: :html), alert: "That passkey is incorrect" and return
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,4 +1,4 @@
1
- <h1>Sign up</h1>
1
+ <h1>Request Magic Link</h1>
2
2
 
3
3
  <%= form_with(url: magics_requests_path) do |form| %>
4
4
  <div class="mb-3">
@@ -8,11 +8,16 @@
8
8
 
9
9
  <div class="mb-3">
10
10
  <%= form.submit "Request Magic Link", class: "btn btn-primary" %>
11
+ <span class="mx-3">or</span>
12
+ <%= link_to "Sign In", sign_in_path %>
13
+ <% if ActionAuth.configuration.passkey_only? %>
14
+ <span class="mx-3">or</span>
15
+ <%= link_to "Passkey", new_sessions_passkey_path %>
16
+ <% end %>
11
17
  </div>
12
18
  <% end %>
13
19
 
14
20
  <div class="mb-3">
15
- <%= link_to "Sign In", sign_in_path %> |
16
21
  <%= link_to "Sign Up", sign_up_path %> |
17
22
  <%= link_to "Reset Password", new_identity_password_reset_path %>
18
23
  <% if ActionAuth.configuration.verify_email_on_sign_in %>
@@ -39,6 +39,9 @@
39
39
  <% if ActionAuth.configuration.magic_link_enabled? %>
40
40
  <%= link_to "Magic Link", new_magics_requests_path %> |
41
41
  <% end %>
42
+ <% if ActionAuth.configuration.passkey_only? %>
43
+ <%= link_to "Passkey", new_sessions_passkey_path %> |
44
+ <% end %>
42
45
  <%= link_to "Reset Password", new_identity_password_reset_path %>
43
46
  <% if ActionAuth.configuration.verify_email_on_sign_in %>
44
47
  | <%= link_to "Verify Email", identity_email_verification_path %>
@@ -16,14 +16,19 @@
16
16
 
17
17
  <div class="mb-3">
18
18
  <%= form.submit "Sign in", class: "btn btn-primary" %>
19
+ <% if ActionAuth.configuration.magic_link_enabled? %>
20
+ <span class="mx-3">or</span>
21
+ <%= link_to "Magic Link", new_magics_requests_path %>
22
+ <% end %>
23
+ <% if ActionAuth.configuration.passkey_only? %>
24
+ <span class="mx-3">or</span>
25
+ <%= link_to "Passkey", new_sessions_passkey_path %>
26
+ <% end %>
19
27
  </div>
20
28
  <% end %>
21
29
 
22
30
  <div class="mb-3">
23
31
  <%= link_to "Sign Up", sign_up_path %> |
24
- <% if ActionAuth.configuration.magic_link_enabled? %>
25
- <%= link_to "Magic Link", new_magics_requests_path %> |
26
- <% end %>
27
32
  <%= link_to "Reset Password", new_identity_password_reset_path %>
28
33
  <% if ActionAuth.configuration.verify_email_on_sign_in %>
29
34
  | <%= link_to "Verify Email", identity_email_verification_path %>
@@ -0,0 +1,20 @@
1
+ <h2 class="action-auth--text-center">Use a passkey to sign in</h2>
2
+ <%= tag :meta, name: :passkey_auth_url, content: action_auth.sessions_passkeys_url %>
3
+
4
+ <%= content_tag :div,
5
+ id: "webauthn_credential_form",
6
+ data: {
7
+ controller: "credential-authenticator",
8
+ "credential-authenticator-options-value": @options
9
+ },
10
+ class: "action-auth--text-center" do %>
11
+
12
+ <div class="mb-3 action-auth--text-center">
13
+ Insert a USB key, if necessary, and tap it.
14
+ An account with a matching passkey is required.
15
+ </div>
16
+ <% end %>
17
+
18
+ <%= content_for :cancel_path do %>
19
+ <%= link_to "Cancel", action_auth.sign_in_path %>
20
+ <% end %>
data/config/routes.rb CHANGED
@@ -10,6 +10,11 @@ ActionAuth::Engine.routes.draw do
10
10
  resource :password_reset, only: [:new, :edit, :create, :update]
11
11
  end
12
12
  resource :password, only: [:edit, :update]
13
+ namespace :sessions do
14
+ if ActionAuth.configuration.webauthn_enabled? && ActionAuth.configuration.passkey_only?
15
+ resources :passkeys, only: [:new, :create]
16
+ end
17
+ end
13
18
  resources :sessions, only: [:index, :show, :destroy]
14
19
 
15
20
  if ActionAuth.configuration.allow_user_deletion?
@@ -14,6 +14,7 @@ module ActionAuth
14
14
  @allow_user_deletion = true
15
15
  @default_from_email = "from@example.com"
16
16
  @magic_link_enabled = true
17
+ @passkey_only = true
17
18
  @pwned_enabled = defined?(Pwned)
18
19
  @verify_email_on_sign_in = true
19
20
  @webauthn_enabled = defined?(WebAuthn)
@@ -29,6 +30,10 @@ module ActionAuth
29
30
  @magic_link_enabled == true
30
31
  end
31
32
 
33
+ def passkey_only?
34
+ webauthn_enabled? && @passkey_only == true
35
+ end
36
+
32
37
  def webauthn_enabled?
33
38
  @webauthn_enabled.respond_to?(:call) ? @webauthn_enabled.call : @webauthn_enabled
34
39
  end
@@ -1,3 +1,3 @@
1
1
  module ActionAuth
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: action_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Kimura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-13 00:00:00.000000000 Z
11
+ date: 2024-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -60,6 +60,7 @@ files:
60
60
  - app/controllers/action_auth/magics/sign_ins_controller.rb
61
61
  - app/controllers/action_auth/passwords_controller.rb
62
62
  - app/controllers/action_auth/registrations_controller.rb
63
+ - app/controllers/action_auth/sessions/passkeys_controller.rb
63
64
  - app/controllers/action_auth/sessions_controller.rb
64
65
  - app/controllers/action_auth/users_controller.rb
65
66
  - app/controllers/action_auth/webauthn_credential_authentications_controller.rb
@@ -81,6 +82,7 @@ files:
81
82
  - app/views/action_auth/registrations/new.html.erb
82
83
  - app/views/action_auth/sessions/index.html.erb
83
84
  - app/views/action_auth/sessions/new.html.erb
85
+ - app/views/action_auth/sessions/passkeys/new.html.erb
84
86
  - app/views/action_auth/user_mailer/email_verification.html.erb
85
87
  - app/views/action_auth/user_mailer/email_verification.text.erb
86
88
  - app/views/action_auth/user_mailer/magic_link.html.erb
@@ -125,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
127
  - !ruby/object:Gem::Version
126
128
  version: '0'
127
129
  requirements: []
128
- rubygems_version: 3.5.17
130
+ rubygems_version: 3.5.11
129
131
  signing_key:
130
132
  specification_version: 4
131
133
  summary: A simple Rails engine for authorization.