Skip to content

Commit

Permalink
Add webauthn_modify_email feature for emailing when a WebAuthn authen…
Browse files Browse the repository at this point in the history
…ticator is added or removed
  • Loading branch information
jeremyevans committed Jul 5, 2024
1 parent b968e8c commit 1275004
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
=== master

* Add webauthn_modify_email feature for emailing when a WebAuthn authenticator is added or removed (jeremyevans)

* Add account_from_id method for retrieving an account using the account id and optional status id (janko) (#431)

* Add otp_modify_email feature for emailing when TOTP authentication is setup or disabled (jeremyevans)

* Add otp_lockout_email feature for emailing when TOTP authentication is locked out or unlocked (jeremyevans)
Expand Down
2 changes: 2 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ HTML and JSON API for all supported features.
* WebAuthn Login (Passwordless login via WebAuthn)
* WebAuthn Verify Account (Passwordless WebAuthn Setup)
* WebAuthn Autofill (Autofill WebAuthn credentials on login)
* WebAuthn Modify Email (Email when WebAuthn authenticator aded or removed)
* OTP (Multifactor authentication via TOTP)
* OTP Modify Email (Email when TOTP authentication setup or disabled)
* OTP Unlock (Unlock TOTP authentication after lockout)
Expand Down Expand Up @@ -954,6 +955,7 @@ view the appropriate file in the doc directory.
* {WebAuthn}[rdoc-ref:doc/webauthn.rdoc]
* {WebAuthn Autofill}[rdoc-ref:doc/webauthn_autofill.rdoc]
* {WebAuthn Login}[rdoc-ref:doc/webauthn_login.rdoc]
* {WebAuthn Modify Email}[rdoc-ref:doc/webauthn_modify_email.rdoc]
* {WebAuthn Verify Account}[rdoc-ref:doc/webauthn_verify_account.rdoc]

=== Calling Rodauth in the Routing Tree
Expand Down
2 changes: 1 addition & 1 deletion demo-site/rodauth_demo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class App < Roda
:disallow_password_reuse, :password_grace_period, :active_sessions, :jwt,
:verify_login_change, :change_password_notify, :confirm_password,
:email_auth
enable :webauthn, :webauthn_login if ENV["RODAUTH_WEBAUTHN"]
enable :webauthn, :webauthn_login, :webauthn_modify_email if ENV["RODAUTH_WEBAUTHN"]
enable :webauthn_verify_account if ENV["RODAUTH_WEBAUTHN_VERIFY_ACCOUNT"]
enable :webauthn_autofill if ENV["RODAUTH_WEBAUTHN_AUTOFILL"]
max_invalid_logins 2
Expand Down
19 changes: 19 additions & 0 deletions doc/webauthn_modify_email.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
= Documentation for WebAuthn Modify Email Feature

The webauthn_modify_email feature emails users when a WebAuthn authenticator is added to or removed from their account.

The webauthn_modify_email feature depends on the webauthn and email_base features.

== Auth Value Methods

webauthn_authenticator_added_email_body :: Body to use for the email notifying user that a WebAuthn authenticator has been added to their account.
webauthn_authenticator_added_email_subject :: Subject to use for the email notifying user that a WebAuthn authenticator has been added to their account.
webauthn_authenticator_removed_email_body :: Body to use for the email notifying user that a WebAuthn authenticator has been removed from their account.
webauthn_authenticator_removed_email_subject :: Subject to use for the email notifying user that a WebAuthn authenticator has been removed from their account.

== Auth Methods

create_webauthn_authenticator_added_email :: A Mail::Message for the email notifying user that a WebAuthn authenticator has been added to their account.
create_webauthn_authenticator_removed_email :: A Mail::Message for the email notifying user that a WebAuthn authenticator has been removed from their account.
send_webauthn_authenticator_added_email :: Send the email notifying user that a WebAuthn authenticator has been added to their account.
send_webauthn_authenticator_removed_email :: Send the email notifying user that a WebAuthn authenticator has been removed from their account.
23 changes: 23 additions & 0 deletions lib/rodauth/features/webauthn_modify_email.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen-string-literal: true

module Rodauth
Feature.define(:webauthn_modify_email, :WebauthnModifyEmail) do
depends :webauthn, :email_base

loaded_templates %w'webauthn-authenticator-added-email webauthn-authenticator-removed-email'
email :webauthn_authenticator_added, 'WebAuthn Authenticator Added', :translatable=>true
email :webauthn_authenticator_removed, 'WebAuthn Authenticator Removed', :translatable=>true

private

def after_webauthn_setup
super
send_webauthn_authenticator_added_email
end

def after_webauthn_remove
super
send_webauthn_authenticator_removed_email
end
end
end
63 changes: 63 additions & 0 deletions spec/webauthn_modify_email_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require_relative 'spec_helper'

begin
require 'webauthn/fake_client'
rescue LoadError
else
describe 'Rodauth webauthn feature' do
it "should email when a webauth authenticator is added or removed" do
rodauth do
enable :login, :logout, :webauthn_modify_email
hmac_secret '123'
two_factor_modifications_require_password? false
webauthn_remove_redirect '/foo'
end
first_request = nil
roda do |r|
first_request ||= r
r.rodauth
r.get('foo'){view :content=>"WebAuthn Removed"}
rodauth.require_authentication
rodauth.require_two_factor_setup
view :content=>"With WebAuthn"
end

login
origin = first_request.base_url

webauthn_client = WebAuthn::FakeClient.new(origin)
challenge = JSON.parse(page.find('#webauthn-setup-form')['data-credential-options'])['challenge']
fill_in 'webauthn_setup', :with=>webauthn_client.create(challenge: challenge).to_json
click_button 'Setup WebAuthn Authentication'
page.find('#notice_flash').text.must_equal 'WebAuthn authentication is now setup'
email = email_sent
email.subject.must_equal "WebAuthn Authenticator Added"
email.body.to_s.must_equal <<EMAIL
Someone (hopefully you) has added a WebAuthn authenticator to the
account associated to this email address. There are now 1 WebAuthn
authenticator(s) with access to the account.
EMAIL

logout
login

challenge = JSON.parse(page.find('#webauthn-auth-form')['data-credential-options'])['challenge']
fill_in 'webauthn_auth', :with=>webauthn_client.get(challenge: challenge).to_json
click_button 'Authenticate Using WebAuthn'
page.find('#notice_flash').text.must_equal 'You have been multifactor authenticated'
page.current_path.must_equal '/'

visit '/webauthn-remove'
choose(/(?<=name="webauthn_remove" id=")webauthn-remove-[^"]*/.match(page.body)[0])
click_button 'Remove WebAuthn Authenticator'
page.find('#notice_flash').text.must_equal "WebAuthn authenticator has been removed"
email = email_sent
email.subject.must_equal "WebAuthn Authenticator Removed"
email.body.to_s.must_equal <<EMAIL
Someone (hopefully you) has removed a WebAuthn authenticator from the
account associated to this email address. There are now 0 WebAuthn
authenticator(s) with access to the account.
EMAIL
end
end
end
3 changes: 3 additions & 0 deletions templates/webauthn-authenticator-added-email.str
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Someone (hopefully you) has added a WebAuthn authenticator to the
account associated to this email address. There are now #{rodauth.account_webauthn_ids.length} WebAuthn
authenticator(s) with access to the account.
3 changes: 3 additions & 0 deletions templates/webauthn-authenticator-removed-email.str
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Someone (hopefully you) has removed a WebAuthn authenticator from the
account associated to this email address. There are now #{rodauth.account_webauthn_ids.length} WebAuthn
authenticator(s) with access to the account.
1 change: 1 addition & 0 deletions www/pages/documentation.erb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<li><a href="rdoc/files/doc/webauthn_rdoc.html">WebAuthn</a>: Adds support for multifactor authentication via WebAuthn.</li>
<li><a href="rdoc/files/doc/webauthn_autofill_rdoc.html">WebAuthn Autofill</a>: Enables autofill UI for WebAuthn credentials on login.</li>
<li><a href="rdoc/files/doc/webauthn_login_rdoc.html">WebAuthn Login</a>: Adds support for passwordless login via WebAuthn.</li>
<li><a href="rdoc/files/doc/webauthn_modify_email_rdoc.html">WebAuthn Modify Email</a>: Emails user when a WebAuthn authenticator is added to or removed from their account.</li>
<li><a href="rdoc/files/doc/webauthn_verify_account_rdoc.html">WebAuthn Verify Account</a>: Adds support for passwordless WebAuthn setup during account verification.</li>
</ul>

Expand Down
1 change: 1 addition & 0 deletions www/pages/why.erb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<li>WebAuthn Login (Passwordless login via WebAuthn)</li>
<li>WebAuthn Verify Account (Passwordless WebAuthn Setup)</li>
<li>WebAuthn Autofill (Autofill WebAuthn credentials on login)</li>
<li>WebAuthn Modify Email (Email when WebAuthn authenticator added or removed)</li>
<li>OTP (Multifactor authentication via TOTP)</li>
<li>OTP Modify Email (Email when TOTP authentication setup or disabled)</li>
<li>OTP Unlock (Unlock TOTP authentication after lockout)</li>
Expand Down

0 comments on commit 1275004

Please sign in to comment.