Skip to content

Commit

Permalink
Add functionality to reset passkeys
Browse files Browse the repository at this point in the history
* Upgrades to Rails 7.1
* Adds the missing mailer layout to Koi
  • Loading branch information
hasarindaKI committed Oct 27, 2023
1 parent e03f3ac commit 1e7d2e2
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 89 deletions.
160 changes: 95 additions & 65 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ PATH
katalyst-navigation
katalyst-tables
pagy
rails (>= 7.0)
rails (>= 7.1)
stimulus-rails
turbo-rails
view_component
Expand All @@ -27,75 +27,83 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
actioncable (7.1.1)
actionpack (= 7.1.1)
activesupport (= 7.1.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
zeitwerk (~> 2.6)
actionmailbox (7.1.1)
actionpack (= 7.1.1)
activejob (= 7.1.1)
activerecord (= 7.1.1)
activestorage (= 7.1.1)
activesupport (= 7.1.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8)
actionpack (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activesupport (= 7.0.8)
actionmailer (7.1.1)
actionpack (= 7.1.1)
actionview (= 7.1.1)
activejob (= 7.1.1)
activesupport (= 7.1.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.8)
actionview (= 7.0.8)
activesupport (= 7.0.8)
rack (~> 2.0, >= 2.2.4)
rails-dom-testing (~> 2.2)
actionpack (7.1.1)
actionview (= 7.1.1)
activesupport (= 7.1.1)
nokogiri (>= 1.8.5)
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8)
actionpack (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actiontext (7.1.1)
actionpack (= 7.1.1)
activerecord (= 7.1.1)
activestorage (= 7.1.1)
activesupport (= 7.1.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.8)
activesupport (= 7.0.8)
actionview (7.1.1)
activesupport (= 7.1.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_storage_validations (1.0.4)
activejob (>= 5.2.0)
activemodel (>= 5.2.0)
activestorage (>= 5.2.0)
activesupport (>= 5.2.0)
activejob (7.0.8)
activesupport (= 7.0.8)
activejob (7.1.1)
activesupport (= 7.1.1)
globalid (>= 0.3.6)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
activestorage (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activesupport (= 7.0.8)
activemodel (7.1.1)
activesupport (= 7.1.1)
activerecord (7.1.1)
activemodel (= 7.1.1)
activesupport (= 7.1.1)
timeout (>= 0.4.0)
activestorage (7.1.1)
actionpack (= 7.1.1)
activejob (= 7.1.1)
activerecord (= 7.1.1)
activesupport (= 7.1.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.8)
activesupport (7.1.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
Expand All @@ -111,6 +119,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.4)
bindata (2.4.15)
brakeman (6.0.1)
builder (3.2.4)
Expand All @@ -137,6 +146,8 @@ GEM
sass-embedded (~> 1.63)
date (3.3.3)
diff-lcs (1.5.0)
drb (2.1.1)
ruby2_keywords
erb_lint (0.5.0)
activesupport
better_html (>= 2.0.1)
Expand Down Expand Up @@ -175,6 +186,10 @@ GEM
importmap-rails (1.2.1)
actionpack (>= 6.0.0)
railties (>= 6.0.0)
io-console (0.6.0)
irb (1.8.3)
rdoc
reline (>= 0.3.8)
json (2.6.3)
jwt (2.7.1)
katalyst-basic-auth (0.4.0)
Expand Down Expand Up @@ -209,6 +224,7 @@ GEM
method_source (1.0.0)
mini_mime (1.1.5)
minitest (5.20.0)
mutex_m (0.1.2)
net-imap (0.4.0)
date
net-protocol
Expand All @@ -233,30 +249,37 @@ GEM
parser (3.2.2.4)
ast (~> 2.4.1)
racc
psych (5.1.1.1)
stringio
public_suffix (5.0.3)
puma (6.4.0)
nio4r (~> 2.0)
racc (1.7.1)
rack (2.2.8)
rack-session (1.0.1)
rack (< 3)
rack-test (2.1.0)
rack (>= 1.3)
rack_session_access (0.2.0)
builder (>= 2.0.0)
rack (>= 1.0.0)
rails (7.0.8)
actioncable (= 7.0.8)
actionmailbox (= 7.0.8)
actionmailer (= 7.0.8)
actionpack (= 7.0.8)
actiontext (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activemodel (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rackup (1.0.0)
rack (< 3)
webrick
rails (7.1.1)
actioncable (= 7.1.1)
actionmailbox (= 7.1.1)
actionmailer (= 7.1.1)
actionpack (= 7.1.1)
actiontext (= 7.1.1)
actionview (= 7.1.1)
activejob (= 7.1.1)
activemodel (= 7.1.1)
activerecord (= 7.1.1)
activestorage (= 7.1.1)
activesupport (= 7.1.1)
bundler (>= 1.15.0)
railties (= 7.0.8)
railties (= 7.1.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
Expand All @@ -268,22 +291,27 @@ GEM
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
method_source
railties (7.1.1)
actionpack (= 7.1.1)
activesupport (= 7.1.1)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.0.6)
rdoc (6.5.0)
psych (>= 4.0.0)
redis (5.0.7)
redis-client (>= 0.9.0)
redis-client (0.17.0)
connection_pool
redlock (2.0.4)
redis-client (>= 0.14.1, < 1.0.0)
regexp_parser (2.8.1)
reline (0.3.9)
io-console (~> 0.5)
rexml (3.2.6)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
Expand Down Expand Up @@ -340,6 +368,7 @@ GEM
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0)
ruby2_keywords (0.0.5)
safety_net_attestation (0.4.0)
jwt (~> 2.0)
sass-embedded (1.68.0-aarch64-linux-gnu)
Expand Down Expand Up @@ -368,6 +397,7 @@ GEM
sqlite3 (1.6.6-x86_64-linux)
stimulus-rails (1.2.2)
railties (>= 6.0.0)
stringio (3.0.8)
thor (1.3.0)
timeout (0.4.0)
tpm-key_attestation (0.12.0)
Expand Down
75 changes: 75 additions & 0 deletions app/controllers/admin/passkey_resets_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

module Admin
class PasskeyResetsController < ApplicationController
include Koi::Controller::HasWebauthn

skip_before_action :authenticate_admin, only: %i[new create edit update]
before_action :set_admin_user, only: %i[edit update]

layout "koi/login"

def new
render :new, locals: { admin_user: Admin::User.new }
end

def create
if (admin_user = Admin::User.find_by(email: passkey_reset_params[:email]))
# remove previous passkeys
admin_user.credentials.destroy_all

token = admin_user.generate_token_for(:passkey_reset_token)
PasskeyResetMailer.passkey_reset(user: admin_user, token:).deliver_now!
end

redirect_to new_admin_session_path, notice: "A passkey reset email sent, check your email."
end

def edit
return redirect_to new_admin_session_path, notice: "Reset link expired." if @admin_user.blank?

options = webauthn_relying_party.options_for_registration(
user: {
id: WebAuthn.generate_user_id,
name: @admin_user.email,
display_name: @admin_user.to_s,
},
exclude: @admin_user.credentials.map(&:external_id),
)

# Store the newly generated challenge somewhere so you can have it
# for the verification phase.
session[:creation_challenge] = options.challenge

render :edit, locals: { admin_user: @admin_user, options: }
end

def update
webauthn_credential = webauthn_relying_party.verify_registration(
JSON.parse(passkey_reset_params[:response]),
session.delete(:creation_challenge),
)

credential = @admin_user.credentials.build(
nickname: passkey_reset_params[:nickname],
public_key: webauthn_credential.public_key,
sign_count: webauthn_credential.sign_count,
external_id: webauthn_credential.id,
)

credential.save!

redirect_to new_admin_session_path, notice: "Please login using new passkey!"
end

private

def set_admin_user
@admin_user = Admin::User.find_by_token_for(:passkey_reset_token, params[:token])
end

def passkey_reset_params
params.require(:admin).permit(:email, :nickname, :response)
end
end
end
12 changes: 12 additions & 0 deletions app/mailers/admin/passkey_reset_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Admin
class PasskeyResetMailer < Koi::ApplicationMailer
def passkey_reset(user:, token:)
@user = user
@token = token

mail(to: @user.email, subject: "Reset your passkey")
end
end
end
2 changes: 1 addition & 1 deletion app/mailers/koi/application_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
module Koi
class ApplicationMailer < ActionMailer::Base
default from: "[email protected]"
layout "mailer"
layout "koi/mailer"
end
end
Loading

0 comments on commit 1e7d2e2

Please sign in to comment.