diff --git a/README.md b/README.md index db0bbc1..a935057 100755 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ ActionAuth.configure do |config| config.allow_user_deletion = true config.default_from_email = "from@example.com" config.magic_link_enabled = true + config.passkey_only = true # Allows sign in with only a passkey config.verify_email_on_sign_in = true config.webauthn_enabled = true 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 ✅ - Passkeys/Hardware Security Keys +✅ - Passkeys sign in without email/password + ✅ - Magic Links ⏳ - 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 ⏳ - Account Impersonation - - ## Usage ### Routes diff --git a/app/assets/javascripts/action_auth/application.js b/app/assets/javascripts/action_auth/application.js index 7feea74..10133ce 100644 --- a/app/assets/javascripts/action_auth/application.js +++ b/app/assets/javascripts/action_auth/application.js @@ -43,7 +43,9 @@ const Credential = { get: function (credentialOptions) { const self = this; - const webauthnUrl = document.querySelector('meta[name="webauthn_auth_url"]').getAttribute("content"); + const webauthnUrlTag = document.querySelector('meta[name="passkey_auth_url"]') || + document.querySelector('meta[name="webauthn_auth_url"]'); + const webauthnUrl = webauthnUrlTag.getAttribute("content"); WebAuthnJSON.get({ "publicKey": credentialOptions }).then(function (credential) { self.callback(webauthnUrl, credential, "/"); }); diff --git a/app/assets/stylesheets/action_auth/application.css b/app/assets/stylesheets/action_auth/application.css index 8a0db82..514259c 100755 --- a/app/assets/stylesheets/action_auth/application.css +++ b/app/assets/stylesheets/action_auth/application.css @@ -36,6 +36,7 @@ body { margin-right: 5px; } } + .container-fluid { -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); @@ -78,6 +79,11 @@ input[type="password"] { margin-bottom: 1rem !important; } +.mx-3 { + margin-left: 1rem !important; + margin-right: 1rem !important; +} + .btn { padding: 0.375rem 0.75rem; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; diff --git a/app/controllers/action_auth/sessions/passkeys_controller.rb b/app/controllers/action_auth/sessions/passkeys_controller.rb new file mode 100644 index 0000000..010e3aa --- /dev/null +++ b/app/controllers/action_auth/sessions/passkeys_controller.rb @@ -0,0 +1,24 @@ +module ActionAuth + module Sessions + class PasskeysController < ApplicationController + def new + get_options = WebAuthn::Credential.options_for_get + session[:current_challenge] = get_options.challenge + @options = get_options + end + + def create + webauthn_credential = WebAuthn::Credential.from_get(params) + credential = WebauthnCredential.find_by(external_id: webauthn_credential.id) + user = User.find_by(id: credential&.user_id) + if credential && user + session = user.sessions.create + cookies.signed.permanent[:session_token] = { value: session.id, httponly: true } + redirect_to main_app.root_path(format: :html), notice: "Signed in successfully" + else + redirect_to sign_in_path(format: :html), alert: "That passkey is incorrect" and return + end + end + end + end +end diff --git a/app/views/action_auth/magics/requests/new.html.erb b/app/views/action_auth/magics/requests/new.html.erb index b5b7509..71f69c2 100644 --- a/app/views/action_auth/magics/requests/new.html.erb +++ b/app/views/action_auth/magics/requests/new.html.erb @@ -1,4 +1,4 @@ -