booth 0.0.1 → 0.0.2
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE.md +1 -2
- data/README.md +37 -6
- data/app/assets/images/booth/browsers/README.md +1 -2
- data/app/assets/images/booth/browsers/chrome.svg +1 -1
- data/app/assets/images/booth/browsers/edge.svg +1 -1
- data/app/assets/images/booth/browsers/firefox.svg +1 -1
- data/app/assets/images/booth/browsers/opera.svg +1 -1
- data/app/assets/images/booth/browsers/safari.svg +1 -1
- data/app/assets/images/booth/fido/passkey_mark_a.svg +10 -0
- data/app/assets/images/booth/fido/passkey_mark_a_black.svg +32 -0
- data/app/assets/images/booth/fido/passkey_mark_a_reverse.svg +33 -0
- data/app/assets/images/booth/fido/passkey_mark_a_white.svg +32 -0
- data/app/assets/images/booth/fido/passkey_mark_b_black.svg +1 -0
- data/app/assets/images/booth/platforms/android.svg +1 -6
- data/app/assets/images/booth/platforms/apple.svg +1 -6
- data/app/assets/images/booth/platforms/linux.svg +1 -6
- data/app/assets/images/booth/platforms/windows.svg +1 -6
- data/app/assets/javascripts/booth/authentication.js +29 -0
- data/app/assets/javascripts/booth/authentication.js.map +1 -0
- data/app/assets/javascripts/booth/error.js +38 -0
- data/app/assets/javascripts/booth/error.js.map +1 -0
- data/app/assets/javascripts/booth/form.js +78 -0
- data/app/assets/javascripts/booth/form.js.map +1 -0
- data/app/assets/javascripts/booth/gui.js +53 -0
- data/app/assets/javascripts/booth/gui.js.map +1 -0
- data/app/assets/javascripts/booth/registration.js +29 -0
- data/app/assets/javascripts/booth/registration.js.map +1 -0
- data/app/assets/javascripts/booth/setup.js +14 -0
- data/app/assets/javascripts/booth/verification.js +49 -0
- data/app/assets/javascripts/booth/verification.js.map +1 -0
- data/app/assets/javascripts/declarations/authentication.d.ts +6 -0
- data/app/assets/javascripts/declarations/error.d.ts +36 -0
- data/app/assets/javascripts/declarations/form.d.ts +8 -0
- data/app/assets/javascripts/declarations/gui.d.ts +4 -0
- data/app/assets/javascripts/declarations/registration.d.ts +6 -0
- data/app/assets/javascripts/declarations/setup.d.ts +3 -0
- data/app/assets/javascripts/declarations/verification.d.ts +6 -0
- data/app/assets/javascripts/src/authentication.ts +41 -0
- data/app/assets/javascripts/src/error.ts +35 -0
- data/app/assets/javascripts/src/form.ts +90 -0
- data/app/assets/javascripts/src/gui.ts +59 -0
- data/app/assets/javascripts/src/registration.ts +44 -0
- data/app/assets/javascripts/src/verification.ts +61 -0
- data/app/assets/stylesheets/booth/booth.css +3 -0
- data/config/importmap.rb +11 -0
- data/config/locales/de.yml +14 -38
- data/config/locales/en.yml +17 -36
- data/data/combined_aaguid.json +1 -0
- data/lib/booth/adminland/credentials/create.rb +10 -12
- data/lib/booth/adminland/credentials/index.rb +31 -0
- data/lib/booth/adminland/onboardings/create.rb +24 -15
- data/lib/booth/adminland/onboardings/destroy.rb +8 -4
- data/lib/booth/adminland/onboardings/find.rb +52 -45
- data/lib/booth/adminland/onboardings/find_unconsumed.rb +61 -0
- data/lib/booth/adminland/onboardings/index.rb +6 -3
- data/lib/booth/adminland/periodic_cleanup.rb +7 -2
- data/lib/booth/adminland.rb +17 -18
- data/lib/booth/coercers/domain.rb +11 -0
- data/lib/booth/coercers/request.rb +51 -0
- data/lib/booth/coercers/scope.rb +11 -0
- data/lib/booth/comparisons/domain.rb +38 -0
- data/lib/booth/comparisons/scope.rb +38 -0
- data/lib/booth/concerns/action.rb +25 -13
- data/lib/booth/concerns/transition.rb +5 -2
- data/lib/booth/configuration.rb +14 -73
- data/lib/booth/configure.rb +3 -10
- data/lib/booth/{audits/register → core/audit}/completed_onboarding.rb +8 -6
- data/lib/booth/core/audit/credential_created.rb +24 -0
- data/lib/booth/core/audit/logout.rb +24 -0
- data/lib/booth/core/authenticators/confirm.rb +30 -0
- data/lib/booth/core/authenticators/step.rb +24 -0
- data/lib/booth/core/cooldowns/distance_of_time.rb +50 -0
- data/lib/booth/core/cooldowns/strategies/exponential.rb +88 -0
- data/lib/booth/core/cooldowns/strategies/global.rb +66 -0
- data/lib/booth/core/cooldowns/strategies/result.rb +27 -0
- data/lib/booth/core/credentials/create.rb +32 -0
- data/lib/booth/core/credentials/find_by_username.rb +63 -0
- data/lib/booth/core/credentials/index.rb +15 -0
- data/lib/booth/core/credentials/webauth_challenge.rb +37 -0
- data/lib/booth/core/geolocation.rb +25 -0
- data/lib/booth/core/onboardings/find.rb +92 -0
- data/lib/booth/core/onboardings/step.rb +19 -0
- data/lib/booth/core/remotes/get.rb +45 -0
- data/lib/booth/core/remotes/respond.rb +82 -0
- data/lib/booth/core/remotes/set_for_login.rb +31 -0
- data/lib/booth/core/sessions/create_and_login.rb +63 -0
- data/lib/booth/core/sessions/historical_locations.rb +22 -0
- data/lib/booth/core/sessions/index.rb +66 -0
- data/lib/booth/core/sessions/revoke.rb +59 -0
- data/lib/booth/core/sessions/revoke_all_others.rb +49 -0
- data/lib/booth/core/sessions/to_passport.rb +35 -0
- data/lib/booth/core/webauth/authentication_verification.rb +76 -0
- data/lib/booth/core/webauth/options_for_create.rb +56 -0
- data/lib/booth/core/webauth/options_for_get.rb +30 -0
- data/lib/booth/core/webauth/provider.rb +36 -0
- data/lib/booth/core/webauth/registration_verification.rb +100 -0
- data/lib/booth/credential.rb +35 -0
- data/lib/booth/engine.rb +15 -4
- data/lib/booth/errors.rb +2 -0
- data/lib/booth/hooks/after_fetch.rb +14 -6
- data/lib/booth/hooks/before_logout.rb +5 -3
- data/lib/booth/hooks/serialize_from_session.rb +13 -5
- data/lib/booth/hooks/serialize_into_session.rb +6 -3
- data/lib/booth/logging.rb +13 -42
- data/lib/booth/models/application_record.rb +3 -0
- data/lib/booth/models/audit.rb +10 -11
- data/lib/booth/models/authenticator.rb +6 -9
- data/lib/booth/models/credential.rb +17 -20
- data/lib/booth/models/onboarding.rb +16 -39
- data/lib/booth/models/{contest.rb → remote.rb} +13 -14
- data/lib/booth/models/remotes/scopes/recently_created.rb +26 -0
- data/lib/booth/models/remotes/scopes/recently_responded.rb +35 -0
- data/lib/booth/models/session.rb +15 -10
- data/lib/booth/models/user_agent.rb +2 -0
- data/lib/booth/request.rb +43 -22
- data/lib/booth/requests/agent.rb +3 -1
- data/lib/booth/requests/authentication.rb +15 -5
- data/lib/booth/requests/ip.rb +4 -2
- data/lib/booth/requests/return_path.rb +4 -2
- data/lib/booth/requests/session.rb +6 -4
- data/lib/booth/requests/storage.rb +5 -31
- data/lib/booth/requests/storages/login.rb +35 -29
- data/lib/booth/requests/storages/registration.rb +2 -0
- data/lib/booth/requests/storages/webauth.rb +3 -0
- data/lib/booth/requests/sudo.rb +6 -50
- data/lib/booth/routes/userland.rb +13 -59
- data/lib/booth/syntaxes/domain.rb +46 -0
- data/lib/booth/syntaxes/email.rb +11 -8
- data/lib/booth/syntaxes/ip.rb +6 -4
- data/lib/booth/syntaxes/remote_code.rb +60 -0
- data/lib/booth/syntaxes/scope.rb +7 -3
- data/lib/booth/syntaxes/secret_key.rb +8 -6
- data/lib/booth/syntaxes/username.rb +23 -10
- data/lib/booth/syntaxes/uuid.rb +3 -1
- data/lib/booth/test.rb +27 -22
- data/lib/booth/testing/incorporation_test_case.rb +29 -0
- data/lib/booth/testing/shortcuts.rb +77 -0
- data/lib/booth/testing/support/assert_all_partials_were_covered.rb +69 -0
- data/lib/booth/testing/support/assert_logged_in.rb +68 -0
- data/lib/booth/{test → testing}/support/assert_logged_out.rb +7 -4
- data/lib/booth/testing/support/assert_partial.rb +56 -0
- data/lib/booth/{test → testing}/support/force_login.rb +10 -4
- data/lib/booth/{test → testing}/support/get_session_value.rb +8 -6
- data/lib/booth/testing/support/scenario.rb +23 -0
- data/lib/booth/testing/support/shortcuts/create_and_onboard.rb +56 -0
- data/lib/booth/testing/support/shortcuts/login_with_passkey.rb +55 -0
- data/lib/booth/testing/support/shortcuts/register_new_passkey.rb +51 -0
- data/lib/booth/testing/support/soft_reset_session.rb +24 -0
- data/lib/booth/testing/support/virtual_authenticators/create.rb +34 -0
- data/lib/booth/testing/support/virtual_authenticators/destroy.rb +20 -0
- data/lib/booth/testing/support/virtual_authenticators/enable.rb +24 -0
- data/lib/booth/testing/support/virtual_authenticators/load.rb +38 -0
- data/lib/booth/testing/support/virtual_authenticators/manager.rb +124 -0
- data/lib/booth/testing/support/visit.rb +62 -0
- data/lib/booth/testing/userland/login_remotely.rb +100 -0
- data/lib/booth/testing/userland/onboarding_first_time.rb +81 -0
- data/lib/booth/testing/userland/onboarding_to_reset_passkeys.rb +129 -0
- data/lib/booth/testing/userland/registration_with_passkey.rb +93 -0
- data/lib/booth/testing/userland/registration_without_passkey.rb +101 -0
- data/lib/booth/testing/userland/sessions_manage_behavior.rb +68 -0
- data/lib/booth/testing/userland/sessions_revoke_all_others.rb +17 -0
- data/lib/booth/testing/userland/sessions_revoke_one.rb +17 -0
- data/lib/booth/testing/userland.rb +36 -0
- data/lib/booth/to_struct.rb +9 -2
- data/lib/booth/userland/extract_flash_messages.rb +10 -3
- data/lib/booth/userland/logins/create.rb +8 -6
- data/lib/booth/userland/logins/destroy.rb +23 -6
- data/lib/booth/userland/logins/new.rb +23 -25
- data/lib/booth/userland/logins/transitions/create/choose_username.rb +62 -27
- data/lib/booth/userland/logins/transitions/create/skip_remotes.rb +18 -14
- data/lib/booth/userland/logins/transitions/create/webauth_authentication_initiation.rb +54 -48
- data/lib/booth/userland/logins/transitions/create/webauth_authentication_verification.rb +62 -58
- data/lib/booth/userland/logins/transitions/new/already_logged_in.rb +4 -3
- data/lib/booth/userland/logins/transitions/new/fallible.rb +4 -0
- data/lib/booth/userland/logins/transitions/new/{mode_username_and_password.rb → missing_authenticators.rb} +5 -4
- data/lib/booth/userland/logins/transitions/new/mode_username_and_webauth.rb +6 -4
- data/lib/booth/userland/logins/transitions/new/no_username_chosen.rb +3 -1
- data/lib/booth/userland/logins/transitions/new/remote_session_available.rb +20 -13
- data/lib/booth/userland/logins/transitions/new/timed_out.rb +3 -1
- data/lib/booth/userland/onboardings/show.rb +65 -39
- data/lib/booth/userland/onboardings/update.rb +46 -38
- data/lib/booth/userland/registrations/create.rb +51 -20
- data/lib/booth/userland/registrations/new.rb +6 -7
- data/lib/booth/userland/remotes/show.rb +56 -0
- data/lib/booth/userland/{personal_contests → remotes}/update.rb +5 -3
- data/lib/booth/userland/sessions/destroy_one_or_other.rb +3 -16
- data/lib/booth/userland/sessions/index.rb +4 -2
- data/lib/booth/userland/sessions/show.rb +5 -6
- data/lib/booth/userland/sessions/transitions/destroy/enter_webauth.rb +8 -6
- data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_initiation.rb +8 -6
- data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_verification.rb +7 -5
- data/lib/booth/userland/sessions/transitions/show/enter_webauth.rb +8 -6
- data/lib/booth/userland/webauths/create.rb +20 -17
- data/lib/booth/userland/webauths/destroy.rb +6 -16
- data/lib/booth/userland/webauths/guards/sudo.rb +10 -5
- data/lib/booth/userland/webauths/index.rb +4 -2
- data/lib/booth/userland/webauths/new.rb +7 -22
- data/lib/booth/userland/webauths/sudo.rb +3 -1
- data/lib/booth/userland/webauths/transitions/create/authentication_initiation.rb +8 -11
- data/lib/booth/userland/webauths/transitions/create/authentication_verification.rb +11 -13
- data/lib/booth/userland/webauths/transitions/create/choose_nickname.rb +8 -5
- data/lib/booth/userland/webauths/transitions/create/registration_initiation.rb +15 -14
- data/lib/booth/userland/webauths/transitions/create/registration_verification.rb +34 -28
- data/lib/booth/userland/webauths/transitions/create/reset.rb +2 -0
- data/lib/booth/userland/webauths/transitions/new/step.rb +3 -1
- data/lib/booth/userland/webauths/transitions/sudo/authentication_initiation.rb +5 -10
- data/lib/booth/userland/webauths/transitions/sudo/authentication_verification.rb +4 -2
- data/lib/booth/userland.rb +53 -109
- data/lib/booth/version.rb +3 -1
- data/lib/booth.rb +6 -236
- data/lib/generators/booth/migration/migration_generator.rb +2 -1
- data/lib/generators/booth/migration/templates/add_credential_to_users.erb +6 -4
- data/lib/generators/booth/migration/templates/create_booth_tables.erb +61 -72
- metadata +124 -571
- data/app/assets/config/booth_manifest.js +0 -15
- data/app/assets/images/booth/browsers/internet_explorer.svg +0 -1
- data/app/assets/javascripts/booth/all.js +0 -162
- data/app/assets/javascripts/booth/all.js.map +0 -1
- data/app/assets/javascripts/booth/booth.ts +0 -194
- data/app/assets/javascripts/booth/webauthn-json.ts +0 -99
- data/lib/booth/adminland/recoveries/consume.rb +0 -70
- data/lib/booth/audits/register/added_otp.rb +0 -22
- data/lib/booth/audits/register/changed_otp.rb +0 -22
- data/lib/booth/audits/register/correct_otp.rb +0 -42
- data/lib/booth/audits/register/correct_password.rb +0 -43
- data/lib/booth/audits/register/logout.rb +0 -22
- data/lib/booth/audits/register/requested_password_reset.rb +0 -22
- data/lib/booth/audits/register/wrong_otp.rb +0 -22
- data/lib/booth/audits/register/wrong_password.rb +0 -25
- data/lib/booth/authenticators/confirm.rb +0 -34
- data/lib/booth/authenticators/credential_mode_after_confirmation.rb +0 -25
- data/lib/booth/authenticators/step.rb +0 -19
- data/lib/booth/contests/get.rb +0 -36
- data/lib/booth/contests/respond.rb +0 -78
- data/lib/booth/contests/set_for_login.rb +0 -28
- data/lib/booth/cooldowns/distance_of_time.rb +0 -46
- data/lib/booth/cooldowns/otp.rb +0 -22
- data/lib/booth/cooldowns/password.rb +0 -44
- data/lib/booth/cooldowns/password_reset.rb +0 -24
- data/lib/booth/cooldowns/strategies/exponential.rb +0 -82
- data/lib/booth/cooldowns/strategies/global.rb +0 -62
- data/lib/booth/cooldowns/strategies/result.rb +0 -22
- data/lib/booth/credentials/create.rb +0 -28
- data/lib/booth/credentials/create_with_onboarding.rb +0 -26
- data/lib/booth/credentials/find_by_username.rb +0 -45
- data/lib/booth/credentials/mode.rb +0 -69
- data/lib/booth/credentials/modes/otp_addable.rb +0 -23
- data/lib/booth/credentials/modes/otp_changeable.rb +0 -23
- data/lib/booth/credentials/modes/otp_manageable.rb +0 -17
- data/lib/booth/credentials/modes/otp_removable.rb +0 -23
- data/lib/booth/credentials/modes/password_addable.rb +0 -29
- data/lib/booth/credentials/modes/password_changeable.rb +0 -31
- data/lib/booth/credentials/modes/password_manageable.rb +0 -17
- data/lib/booth/credentials/modes/password_removable.rb +0 -24
- data/lib/booth/credentials/modes/password_removal_requires_user_verifiable_webauth.rb +0 -16
- data/lib/booth/credentials/modes/webauth_addable.rb +0 -26
- data/lib/booth/credentials/modes/webauth_manageable.rb +0 -16
- data/lib/booth/credentials/modes/webauth_removable.rb +0 -25
- data/lib/booth/credentials/otp_authentication.rb +0 -59
- data/lib/booth/credentials/password_authentication.rb +0 -72
- data/lib/booth/credentials/webauth_challenge.rb +0 -28
- data/lib/booth/geolocation.rb +0 -20
- data/lib/booth/logger.rb +0 -41
- data/lib/booth/method_object.rb +0 -73
- data/lib/booth/mode.rb +0 -22
- data/lib/booth/models/concerns/modeable.rb +0 -50
- data/lib/booth/models/concerns/otpable.rb +0 -37
- data/lib/booth/models/concerns/passwordable.rb +0 -58
- data/lib/booth/models/contests/scopes/recently_created.rb +0 -23
- data/lib/booth/models/contests/scopes/recently_responded.rb +0 -32
- data/lib/booth/models/password_reset.rb +0 -41
- data/lib/booth/models/recovery.rb +0 -32
- data/lib/booth/models/registration.rb +0 -10
- data/lib/booth/modes/base.rb +0 -25
- data/lib/booth/modes/username_and_password.rb +0 -7
- data/lib/booth/modes/username_and_webauth.rb +0 -7
- data/lib/booth/modes/username_password_and_otp.rb +0 -7
- data/lib/booth/modes/username_password_and_webauth.rb +0 -7
- data/lib/booth/onboardings/find.rb +0 -35
- data/lib/booth/onboardings/propagate_to_credential.rb +0 -63
- data/lib/booth/onboardings/step.rb +0 -68
- data/lib/booth/password_resets/create.rb +0 -57
- data/lib/booth/password_resets/find.rb +0 -36
- data/lib/booth/password_resets/propagate_to_credential.rb +0 -36
- data/lib/booth/password_resets/step.rb +0 -18
- data/lib/booth/recoveries/create.rb +0 -45
- data/lib/booth/requests/storages/otp.rb +0 -54
- data/lib/booth/requests/storages/password.rb +0 -49
- data/lib/booth/requests/storages/password_reset.rb +0 -35
- data/lib/booth/requests/storages/recovery.rb +0 -35
- data/lib/booth/sessions/create_and_login.rb +0 -46
- data/lib/booth/sessions/historical_locations.rb +0 -18
- data/lib/booth/sessions/index.rb +0 -59
- data/lib/booth/sessions/revoke.rb +0 -51
- data/lib/booth/sessions/revoke_all_others.rb +0 -43
- data/lib/booth/sessions/to_passport.rb +0 -51
- data/lib/booth/syntaxes/contest_code.rb +0 -58
- data/lib/booth/syntaxes/otp.rb +0 -57
- data/lib/booth/syntaxes/scope_comparison.rb +0 -28
- data/lib/booth/test/helpers.rb +0 -63
- data/lib/booth/test/support/assert_all_partials_were_covered.rb +0 -63
- data/lib/booth/test/support/assert_logged_in.rb +0 -49
- data/lib/booth/test/support/assert_partial.rb +0 -29
- data/lib/booth/test/support/otp_code_from_session.rb +0 -30
- data/lib/booth/test/support/soft_reset_session.rb +0 -22
- data/lib/booth/test/userland/logins/missing_authenticators.rb +0 -72
- data/lib/booth/test/userland/logins/missing_onboarding.rb +0 -35
- data/lib/booth/test/userland/logins/username_and_password.rb +0 -40
- data/lib/booth/test/userland/logins/username_and_webauth.rb +0 -75
- data/lib/booth/test/userland/logins/username_password_and_otp.rb +0 -45
- data/lib/booth/test/userland/logins/username_password_and_webauth.rb +0 -86
- data/lib/booth/test/userland/onboardings/already_logged_in.rb +0 -64
- data/lib/booth/test/userland/onboardings/otp.rb +0 -63
- data/lib/booth/test/userland/onboardings/password.rb +0 -49
- data/lib/booth/test/userland/onboardings/timeout.rb +0 -47
- data/lib/booth/test/userland/otps/manage.rb +0 -86
- data/lib/booth/test/userland/password_resets/reset.rb +0 -102
- data/lib/booth/test/userland.rb +0 -38
- data/lib/booth/test/webauthn/disable.rb +0 -17
- data/lib/booth/test/webauthn/enable.rb +0 -19
- data/lib/booth/test/webauthn/virtual_authenticators/create.rb +0 -38
- data/lib/booth/test/webauthn/virtual_authenticators/destroy.rb +0 -20
- data/lib/booth/userland/logins/transitions/create/enter_otp.rb +0 -70
- data/lib/booth/userland/logins/transitions/create/verify_password.rb +0 -70
- data/lib/booth/userland/logins/transitions/new/mode_first_time.rb +0 -20
- data/lib/booth/userland/logins/transitions/new/mode_username_password_and_otp.rb +0 -24
- data/lib/booth/userland/logins/transitions/new/mode_username_password_and_webauth.rb +0 -24
- data/lib/booth/userland/onboardings/transitions/update/choose_mode.rb +0 -58
- data/lib/booth/userland/onboardings/transitions/update/choose_password.rb +0 -41
- data/lib/booth/userland/onboardings/transitions/update/choose_webauth_nickname.rb +0 -50
- data/lib/booth/userland/onboardings/transitions/update/confirm_otp.rb +0 -58
- data/lib/booth/userland/onboardings/transitions/update/confirm_password.rb +0 -49
- data/lib/booth/userland/onboardings/transitions/update/register_otp.rb +0 -31
- data/lib/booth/userland/onboardings/transitions/update/reset_otp.rb +0 -40
- data/lib/booth/userland/onboardings/transitions/update/reset_password.rb +0 -35
- data/lib/booth/userland/onboardings/transitions/update/reset_webauth.rb +0 -46
- data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_initiation.rb +0 -40
- data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_verification.rb +0 -59
- data/lib/booth/userland/onboardings/transitions/update/webauth_registration_initiation.rb +0 -46
- data/lib/booth/userland/onboardings/transitions/update/webauth_registration_verification.rb +0 -56
- data/lib/booth/userland/otps/destroy.rb +0 -42
- data/lib/booth/userland/otps/edit.rb +0 -72
- data/lib/booth/userland/otps/guards/manageable.rb +0 -21
- data/lib/booth/userland/otps/guards/sudo.rb +0 -23
- data/lib/booth/userland/otps/show.rb +0 -36
- data/lib/booth/userland/otps/sudo.rb +0 -51
- data/lib/booth/userland/otps/transitions/update/confirm.rb +0 -84
- data/lib/booth/userland/otps/transitions/update/register.rb +0 -40
- data/lib/booth/userland/otps/transitions/update/reset.rb +0 -31
- data/lib/booth/userland/otps/update.rb +0 -34
- data/lib/booth/userland/password_resets/create.rb +0 -73
- data/lib/booth/userland/password_resets/guards/logged_out.rb +0 -21
- data/lib/booth/userland/password_resets/new.rb +0 -57
- data/lib/booth/userland/password_resets/show.rb +0 -77
- data/lib/booth/userland/password_resets/transitions/update/choose_password.rb +0 -48
- data/lib/booth/userland/password_resets/transitions/update/confirm_password.rb +0 -54
- data/lib/booth/userland/password_resets/transitions/update/reset_password.rb +0 -29
- data/lib/booth/userland/password_resets/update.rb +0 -65
- data/lib/booth/userland/passwords/destroy.rb +0 -41
- data/lib/booth/userland/passwords/edit.rb +0 -54
- data/lib/booth/userland/passwords/guards/manageable.rb +0 -21
- data/lib/booth/userland/passwords/guards/removable.rb +0 -21
- data/lib/booth/userland/passwords/guards/sudo.rb +0 -21
- data/lib/booth/userland/passwords/remove.rb +0 -34
- data/lib/booth/userland/passwords/show.rb +0 -32
- data/lib/booth/userland/passwords/sudo.rb +0 -55
- data/lib/booth/userland/passwords/transitions/remove/step.rb +0 -27
- data/lib/booth/userland/passwords/transitions/update/choose_password.rb +0 -62
- data/lib/booth/userland/passwords/transitions/update/confirm_password.rb +0 -82
- data/lib/booth/userland/passwords/update.rb +0 -33
- data/lib/booth/userland/personal_contests/show.rb +0 -60
- data/lib/booth/userland/recoveries/create.rb +0 -48
- data/lib/booth/userland/recoveries/new.rb +0 -35
- data/lib/booth/userland/sessions/transitions/destroy/enter_password.rb +0 -50
- data/lib/booth/userland/sessions/transitions/destroy/verify_password.rb +0 -83
- data/lib/booth/userland/webauths/guards/manageable.rb +0 -21
- data/lib/booth/webauth/authentication_verification.rb +0 -68
- data/lib/booth/webauth/demand_user_verification.rb +0 -29
- data/lib/booth/webauth/options_for_create.rb +0 -46
- data/lib/booth/webauth/options_for_get.rb +0 -29
- data/lib/generators/booth/migration/templates/create_booth_mode_types.erb +0 -20
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Passwords
|
|
4
|
-
module Transitions
|
|
5
|
-
module Update
|
|
6
|
-
class ChoosePassword
|
|
7
|
-
include ::Booth::Concerns::Transition
|
|
8
|
-
|
|
9
|
-
def self.applicable?(params:)
|
|
10
|
-
params.dig(:password, :new_password)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
do_check_sudo
|
|
15
|
-
.on_success { do_check_password }
|
|
16
|
-
.on_success { do_remember_password }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def do_check_sudo
|
|
22
|
-
return Tron.success :still_has_sudo if sudo.password?
|
|
23
|
-
|
|
24
|
-
Tron.failure :missing_sudo, public_message: I18n.t('booth.password_change_timeout',
|
|
25
|
-
lifespan_minutes: (sudo.lifespan / 60))
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def do_check_password
|
|
29
|
-
@dummy_credential = ::Booth::Models::Credential.new(
|
|
30
|
-
password: password_param,
|
|
31
|
-
username: :dummy,
|
|
32
|
-
allowed_modes: [:first_time]
|
|
33
|
-
)
|
|
34
|
-
return Tron.success :password_is_acceptable if @dummy_credential.valid?
|
|
35
|
-
|
|
36
|
-
debug { 'The newly chosen password is not acceptable' }
|
|
37
|
-
Tron.failure :invalid_password, public_message: @dummy_credential.errors.full_messages.to_sentence
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def do_remember_password
|
|
41
|
-
storage.password_digest = @dummy_credential.password_digest
|
|
42
|
-
|
|
43
|
-
Tron.success :remembered_password
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def password_param
|
|
47
|
-
params.require(:password).permit(:new_password)[:new_password]
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def storage
|
|
51
|
-
request.storage.password
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def sudo
|
|
55
|
-
request.sudo
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Passwords
|
|
4
|
-
module Transitions
|
|
5
|
-
module Update
|
|
6
|
-
class ConfirmPassword
|
|
7
|
-
include ::Booth::Concerns::Transition
|
|
8
|
-
|
|
9
|
-
def self.applicable?(params:)
|
|
10
|
-
params.dig(:password, :password)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
do_check_sudo
|
|
15
|
-
.on_success { do_compare_password }
|
|
16
|
-
.on_success { do_update_credential }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
|
-
def do_check_sudo
|
|
22
|
-
return Tron.success :still_has_sudo if sudo.password?
|
|
23
|
-
|
|
24
|
-
Tron.failure :missing_sudo, public_message: I18n.t('booth.password_change_timeout',
|
|
25
|
-
lifespan_minutes: (sudo.lifespan / 60))
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def do_compare_password
|
|
29
|
-
@dummy_credential = ::Booth::Models::Credential.new(
|
|
30
|
-
password_digest: storage.password_digest,
|
|
31
|
-
password_confirmation: password_param,
|
|
32
|
-
username: :dummy,
|
|
33
|
-
allowed_modes: [:first_time]
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
if @dummy_credential.valid?
|
|
37
|
-
debug { 'The password confirmation was typed in correctly' }
|
|
38
|
-
return Tron.success :passwords_match
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
debug { 'The password confirmation did not match' }
|
|
42
|
-
Tron.failure :passwords_dont_match, public_message: @dummy_credential.errors.full_messages.to_sentence
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def do_update_credential
|
|
46
|
-
credential = ::Booth::Models::Credential.find(authentication.credential_id)
|
|
47
|
-
|
|
48
|
-
if credential.update(password: password_param)
|
|
49
|
-
debug { "Successfully updated password of credential with ID #{credential.id}" }
|
|
50
|
-
storage.reset
|
|
51
|
-
storage.password_recently_changed!
|
|
52
|
-
|
|
53
|
-
# Prolong sudo to give the user more time to revoke all other sessions.
|
|
54
|
-
sudo.password!
|
|
55
|
-
return Tron.success :password_updated
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
debug { "Could not persist new password for credential with ID #{credential.id}" }
|
|
59
|
-
Tron.failure :persistence_failed, public_message: credential.errors.full_messages.to_sentence
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def password_param
|
|
63
|
-
params.require(:password).permit(:password)[:password]
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def storage
|
|
67
|
-
request.storage.password
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def authentication
|
|
71
|
-
request.authentication
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def sudo
|
|
75
|
-
request.sudo
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Passwords
|
|
4
|
-
class Update
|
|
5
|
-
include ::Booth::Concerns::Action
|
|
6
|
-
|
|
7
|
-
def call
|
|
8
|
-
request.must_be_patch!
|
|
9
|
-
request.must_be_logged_in!
|
|
10
|
-
|
|
11
|
-
::Booth::Userland::Passwords::Guards::Manageable.call(credential:) { return _1 }
|
|
12
|
-
::Booth::Userland::Passwords::Guards::Sudo.call(request:, credential:) { return _1 }
|
|
13
|
-
|
|
14
|
-
do_transition
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
def credential
|
|
20
|
-
@credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def transitions
|
|
24
|
-
[
|
|
25
|
-
::Booth::Userland::Passwords::Transitions::Update::ChoosePassword,
|
|
26
|
-
# TODO: Add ResetPassword so that you can change your mind when confirming
|
|
27
|
-
::Booth::Userland::Passwords::Transitions::Update::ConfirmPassword,
|
|
28
|
-
]
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module PersonalContests
|
|
4
|
-
class Show
|
|
5
|
-
include ::Booth::Concerns::Action
|
|
6
|
-
|
|
7
|
-
def call
|
|
8
|
-
request.must_be_get!
|
|
9
|
-
request.must_be_html!
|
|
10
|
-
request.must_be_logged_in!
|
|
11
|
-
|
|
12
|
-
debug { 'You want to receive your personal contest...' }
|
|
13
|
-
|
|
14
|
-
if contest.failure?
|
|
15
|
-
debug { "This credential doesn't have any contest right now." }
|
|
16
|
-
return Tron.success :not_contested, step: :not_contested
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
if contest.recently_responded
|
|
20
|
-
debug { 'The current contest has already been responded to' }
|
|
21
|
-
return Tron.success :contest_responded, step: :contest_solved
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
step = case contest.reason
|
|
25
|
-
when :login then :remote_login
|
|
26
|
-
when :support then :support_authentication
|
|
27
|
-
else raise "Unknown contest reason: #{contest.reason}"
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
debug { 'You have a contest to respond to' }
|
|
31
|
-
Tron.success :you_are_contested,
|
|
32
|
-
ip: contest.ip,
|
|
33
|
-
agent: contest.agent.presence,
|
|
34
|
-
location: contest.location.presence,
|
|
35
|
-
browser_name: contest.browser_name,
|
|
36
|
-
platform_name: contest.platform_name,
|
|
37
|
-
browser_image_path: contest.browser_image_path,
|
|
38
|
-
platform_image_path: contest.platform_image_path,
|
|
39
|
-
step:
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
def credential
|
|
45
|
-
return @credential if defined?(@credential)
|
|
46
|
-
|
|
47
|
-
id = request.authentication.credential_id
|
|
48
|
-
@credential = ::Booth::Models::Credential.find_by(id:)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def contest
|
|
52
|
-
return unless credential
|
|
53
|
-
return @contest if defined?(@contest)
|
|
54
|
-
|
|
55
|
-
@contest = ::Booth::Contests::Get.call(credential_id: credential.id)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Recoveries
|
|
4
|
-
class Create
|
|
5
|
-
include ::Booth::Concerns::Action
|
|
6
|
-
|
|
7
|
-
def call
|
|
8
|
-
request.must_be_post!
|
|
9
|
-
|
|
10
|
-
do_remember_email
|
|
11
|
-
.on_success { do_create_password_reset }
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
private
|
|
15
|
-
|
|
16
|
-
delegate :username, to: :storage, private: true
|
|
17
|
-
|
|
18
|
-
def do_remember_email
|
|
19
|
-
storage.email = ::Booth::Syntaxes::Email.call(email_param).normalized_invalid_email
|
|
20
|
-
|
|
21
|
-
Tron.success :remembered_email
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def do_create_password_reset
|
|
25
|
-
creation = ::Booth::Recoveries::Create.call(
|
|
26
|
-
scope:,
|
|
27
|
-
email: email_param,
|
|
28
|
-
ip: request.ip
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
creation.on_success do
|
|
32
|
-
storage.email = nil
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
creation
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def storage
|
|
39
|
-
request.storage.recovery
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def email_param
|
|
43
|
-
params.require(:recovery).permit(:email)[:email]
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Recoveries
|
|
4
|
-
class New
|
|
5
|
-
include ::Booth::Concerns::Action
|
|
6
|
-
|
|
7
|
-
def call
|
|
8
|
-
request.must_be_get!
|
|
9
|
-
request.must_be_html!
|
|
10
|
-
|
|
11
|
-
if already_logged_in?
|
|
12
|
-
call_already_logged_in
|
|
13
|
-
else
|
|
14
|
-
Tron.failure :enter_email, step: :enter_email, email: storage.email
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def call_already_logged_in
|
|
21
|
-
debug { "Looks like you're already logged in" }
|
|
22
|
-
Tron.success :logged_in, step: :already_logged_in
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def already_logged_in?
|
|
26
|
-
request.authentication.logged_in?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def storage
|
|
30
|
-
request.storage.recovery
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Sessions
|
|
4
|
-
module Transitions
|
|
5
|
-
module Destroy
|
|
6
|
-
class EnterPassword
|
|
7
|
-
include ::Booth::Concerns::Transition
|
|
8
|
-
|
|
9
|
-
def self.applicable?(params:)
|
|
10
|
-
!params[:revocation]
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
if sudo.password?
|
|
15
|
-
if session_id_param
|
|
16
|
-
debug { 'Having password sudo, revoking the desired session...' }
|
|
17
|
-
return ::Booth::Sessions::Revoke.call credential_id: authentication.credential_id,
|
|
18
|
-
session_id: session_id_param
|
|
19
|
-
else
|
|
20
|
-
debug { 'Having password sudo, revoking all other sessions...' }
|
|
21
|
-
return ::Booth::Sessions::RevokeAllOthers.call credential_id: authentication.credential_id,
|
|
22
|
-
surviving_session_id: authentication.session_id
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
if session_id_param
|
|
27
|
-
Tron.failure :need_sudo_to_destroy_session,
|
|
28
|
-
step: :enter_password_to_destroy,
|
|
29
|
-
session_id: session_id_param
|
|
30
|
-
else
|
|
31
|
-
Tron.failure :need_sudo_to_destroy_all_other_sessions,
|
|
32
|
-
step: :enter_password_to_destroy_all_others
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def session_id_param
|
|
37
|
-
# If params[:id] is a UUID, then it's an ID for a `Booth::Models::Session` in the DB.
|
|
38
|
-
# If params[:id] is something else, then it's just a WebAuth Ceremony argument.
|
|
39
|
-
::Booth::Syntaxes::Uuid.call(request.params[:id], raise_if_invalid: false).uuid
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
delegate :authentication, to: :request
|
|
43
|
-
|
|
44
|
-
delegate :sudo, to: :request
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Sessions
|
|
4
|
-
module Transitions
|
|
5
|
-
module Destroy
|
|
6
|
-
class VerifyPassword
|
|
7
|
-
include ::Booth::Concerns::Transition
|
|
8
|
-
|
|
9
|
-
def self.applicable?(params:)
|
|
10
|
-
params.dig(:revocation, :password)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call
|
|
14
|
-
do_find_credential
|
|
15
|
-
.on_success { do_revoke_sessions }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
def do_find_credential
|
|
21
|
-
@credential = ::Booth::Models::Credential.find_by(id: authentication.credential_id)
|
|
22
|
-
return Tron.success :found_credential if @credential
|
|
23
|
-
|
|
24
|
-
Tron.failure :missing_credential
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def do_revoke_sessions
|
|
28
|
-
checking = ::Booth::Credentials::PasswordAuthentication.call(
|
|
29
|
-
credential: @credential,
|
|
30
|
-
password: password_param,
|
|
31
|
-
ip: request.ip,
|
|
32
|
-
agent: request.agent
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
if checking.success?
|
|
36
|
-
if session_id_param
|
|
37
|
-
debug { 'Having password sudo, revoking the desired session...' }
|
|
38
|
-
return ::Booth::Sessions::Revoke.call credential_id: authentication.credential_id,
|
|
39
|
-
session_id: session_id_param
|
|
40
|
-
else
|
|
41
|
-
debug { 'Having password sudo, revoking all other sessions...' }
|
|
42
|
-
return ::Booth::Sessions::RevokeAllOthers.call credential_id: authentication.credential_id,
|
|
43
|
-
surviving_session_id: authentication.session_id
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
public_message = checking.public_message if checking.respond_to?(:public_message)
|
|
48
|
-
|
|
49
|
-
if session_id_param
|
|
50
|
-
Tron.failure :need_sudo_to_destroy_session,
|
|
51
|
-
step: :enter_password_to_destroy,
|
|
52
|
-
session_id: session_id_param,
|
|
53
|
-
public_message: public_message
|
|
54
|
-
else
|
|
55
|
-
Tron.failure :need_sudo_to_destroy_all_other_sessions,
|
|
56
|
-
step: :enter_password_to_destroy_all_others,
|
|
57
|
-
public_message: public_message
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def session_id_param
|
|
62
|
-
# If params[:id] is a UUID, then it's an ID for a `Booth::Models::Session` in the DB.
|
|
63
|
-
# If params[:id] is something else, then it's just a WebAuth Ceremony argument.
|
|
64
|
-
::Booth::Syntaxes::Uuid.call(request.params[:id], raise_if_invalid: false).uuid
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def password_param
|
|
68
|
-
request.params.require(:revocation).permit(:password)[:password]
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def authentication
|
|
72
|
-
request.authentication
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def sudo
|
|
76
|
-
request.sudo
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Userland
|
|
3
|
-
module Webauths
|
|
4
|
-
module Guards
|
|
5
|
-
class Manageable
|
|
6
|
-
include ::Booth::Logging
|
|
7
|
-
include ::Booth::MethodObject
|
|
8
|
-
|
|
9
|
-
option :credential
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
return if ::Booth::Credentials::Modes::WebauthManageable.call(credential)
|
|
13
|
-
|
|
14
|
-
debug { 'Webauth is not relevant to this credential' }
|
|
15
|
-
yield Tron.failure :webauth_not_configurable, public_message: I18n.t('booth.webauth_unavailable')
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Webauth
|
|
3
|
-
class AuthenticationVerification
|
|
4
|
-
include ::Booth::MethodObject
|
|
5
|
-
include ::Booth::Logging
|
|
6
|
-
|
|
7
|
-
option :request
|
|
8
|
-
option :credential_id
|
|
9
|
-
option :challenge
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
raise 'this authenticator doesnt match the credential' if credential_id != authenticator.credential_id
|
|
13
|
-
|
|
14
|
-
debug do
|
|
15
|
-
"Verifying using challenge #{challenge.inspect} and public key #{authenticator.public_key.inspect} and sign count #{authenticator.sign_count.inspect}"
|
|
16
|
-
end
|
|
17
|
-
webauth.verify(
|
|
18
|
-
challenge,
|
|
19
|
-
public_key: authenticator.public_key,
|
|
20
|
-
sign_count: authenticator.sign_count
|
|
21
|
-
)
|
|
22
|
-
debug { 'Response successfully verified' }
|
|
23
|
-
|
|
24
|
-
authenticator.update!(sign_count: webauth.sign_count)
|
|
25
|
-
sudo.webauth!
|
|
26
|
-
|
|
27
|
-
Tron.success :webauth_authentication_verification_successful,
|
|
28
|
-
credential: authenticator.credential,
|
|
29
|
-
public_json: {},
|
|
30
|
-
http_status: :created
|
|
31
|
-
rescue WebAuthn::SignCountVerificationError => e
|
|
32
|
-
# TODO
|
|
33
|
-
raise 'implement me, counter differed, not too bad?'
|
|
34
|
-
rescue WebAuthn::Error => e
|
|
35
|
-
debug { "Response verification failed: #{e.message}" }
|
|
36
|
-
# TODO: Audit but don't throttle?
|
|
37
|
-
Tron.failure :webauth_failed, public_json: {},
|
|
38
|
-
public_message: "Verification failed: #{e.message}",
|
|
39
|
-
http_status: :unprocessable_entity
|
|
40
|
-
rescue RuntimeError => e
|
|
41
|
-
# This happens e.g. if the param[:id] does not match the param[:rawId]
|
|
42
|
-
raise
|
|
43
|
-
ensure
|
|
44
|
-
sudo.webauthn_challenge = nil
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
delegate :sudo, to: :request
|
|
50
|
-
|
|
51
|
-
def webauth
|
|
52
|
-
# The route `/things/123` overrides the `param[:id]` with 123.
|
|
53
|
-
# But thankfully, webauth also sends the rawId, which is identical to the id.
|
|
54
|
-
# So we override `param[:id]` back to what the webauth JS client sent in.
|
|
55
|
-
# If we don't do this, the webauth ruby library will raise a RuntimeError,
|
|
56
|
-
# complaining that the `id` does not match the `rawId`.
|
|
57
|
-
params_with_correct_id = request.params.dup.merge(id: request.params[:rawId])
|
|
58
|
-
::WebAuthn::Credential.from_get(params_with_correct_id)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def authenticator
|
|
62
|
-
device_id = Base64.strict_encode64(webauth.raw_id)
|
|
63
|
-
@authenticator ||= ::Booth::Models::Authenticator.where(credential_id:)
|
|
64
|
-
.find_by!(device_id:)
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Webauth
|
|
3
|
-
class DemandUserVerification
|
|
4
|
-
include ::Booth::MethodObject
|
|
5
|
-
|
|
6
|
-
option :credential
|
|
7
|
-
option :force, default: -> { false }
|
|
8
|
-
|
|
9
|
-
def call
|
|
10
|
-
!!why?
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
def why?
|
|
16
|
-
return :forced if force.present?
|
|
17
|
-
|
|
18
|
-
# From scratch, you only have a username.
|
|
19
|
-
# Adding webauth in that situation would mean passwordless login.
|
|
20
|
-
return :first_time_passwordless if credential.mode_first_time?
|
|
21
|
-
|
|
22
|
-
# Passwordless always requires verification
|
|
23
|
-
return :passwordless if credential.mode_username_and_webauth?
|
|
24
|
-
|
|
25
|
-
false
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Webauth
|
|
3
|
-
class OptionsForCreate
|
|
4
|
-
include ::Booth::MethodObject
|
|
5
|
-
|
|
6
|
-
option :webauthn_id
|
|
7
|
-
option :username
|
|
8
|
-
option :requires_user_verification
|
|
9
|
-
option :device_ids_to_exclude, default: -> {}
|
|
10
|
-
|
|
11
|
-
def call
|
|
12
|
-
verify_setup
|
|
13
|
-
|
|
14
|
-
::WebAuthn::Credential.options_for_create(
|
|
15
|
-
user: {
|
|
16
|
-
id: webauthn_id,
|
|
17
|
-
name: username
|
|
18
|
-
# Also supports `display_name: "..."`
|
|
19
|
-
},
|
|
20
|
-
authenticator_selection: { user_verification: },
|
|
21
|
-
# Use the following instead, if you want to force device-internal authenticators and forbid USB etc.
|
|
22
|
-
# authenticator_selection: { user_verification:, authenticator_attachment: 'platform' },
|
|
23
|
-
exclude: device_ids_to_exclude
|
|
24
|
-
)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# See https://caniuse.com/mdn-api_publickeycredentialrequestoptions_userverification
|
|
30
|
-
# Can be turned off with `:discouraged`
|
|
31
|
-
def user_verification
|
|
32
|
-
requires_user_verification ? :required : :discouraged
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def requires_user_verification?
|
|
36
|
-
!!requires_user_verification
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def verify_setup
|
|
40
|
-
return if WebAuthn.configuration.rp_name.present?
|
|
41
|
-
|
|
42
|
-
raise ::Booth::Errors::MissingRelyingParty
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Booth
|
|
2
|
-
module Webauth
|
|
3
|
-
class OptionsForGet
|
|
4
|
-
include ::Booth::MethodObject
|
|
5
|
-
|
|
6
|
-
option :allowed_device_ids
|
|
7
|
-
option :requires_user_verification
|
|
8
|
-
|
|
9
|
-
def call
|
|
10
|
-
WebAuthn::Credential.options_for_get(
|
|
11
|
-
allow: allowed_device_ids,
|
|
12
|
-
user_verification: user_verification_value
|
|
13
|
-
)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
private
|
|
17
|
-
|
|
18
|
-
# See https://caniuse.com/mdn-api_publickeycredentialrequestoptions_userverification
|
|
19
|
-
# Can be turned off with `:discouraged`
|
|
20
|
-
def user_verification_value
|
|
21
|
-
requires_user_verification ? :required : :discouraged
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def requires_user_verification?
|
|
25
|
-
!!requires_user_verification
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Don't change anything in this file.
|
|
2
|
-
|
|
3
|
-
class CreateBoothModeTypes < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
4
|
-
def up
|
|
5
|
-
execute <<-SQL
|
|
6
|
-
CREATE TYPE booth_credential_mode AS ENUM
|
|
7
|
-
('first_time',
|
|
8
|
-
'username_and_password',
|
|
9
|
-
'username_password_and_otp',
|
|
10
|
-
'username_password_and_webauth',
|
|
11
|
-
'username_and_webauth');
|
|
12
|
-
SQL
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def down
|
|
16
|
-
execute <<-SQL
|
|
17
|
-
DROP TYPE booth_credential_mode;
|
|
18
|
-
SQL
|
|
19
|
-
end
|
|
20
|
-
end
|