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.
Files changed (383) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE.md +1 -2
  4. data/README.md +37 -6
  5. data/app/assets/images/booth/browsers/README.md +1 -2
  6. data/app/assets/images/booth/browsers/chrome.svg +1 -1
  7. data/app/assets/images/booth/browsers/edge.svg +1 -1
  8. data/app/assets/images/booth/browsers/firefox.svg +1 -1
  9. data/app/assets/images/booth/browsers/opera.svg +1 -1
  10. data/app/assets/images/booth/browsers/safari.svg +1 -1
  11. data/app/assets/images/booth/fido/passkey_mark_a.svg +10 -0
  12. data/app/assets/images/booth/fido/passkey_mark_a_black.svg +32 -0
  13. data/app/assets/images/booth/fido/passkey_mark_a_reverse.svg +33 -0
  14. data/app/assets/images/booth/fido/passkey_mark_a_white.svg +32 -0
  15. data/app/assets/images/booth/fido/passkey_mark_b_black.svg +1 -0
  16. data/app/assets/images/booth/platforms/android.svg +1 -6
  17. data/app/assets/images/booth/platforms/apple.svg +1 -6
  18. data/app/assets/images/booth/platforms/linux.svg +1 -6
  19. data/app/assets/images/booth/platforms/windows.svg +1 -6
  20. data/app/assets/javascripts/booth/authentication.js +29 -0
  21. data/app/assets/javascripts/booth/authentication.js.map +1 -0
  22. data/app/assets/javascripts/booth/error.js +38 -0
  23. data/app/assets/javascripts/booth/error.js.map +1 -0
  24. data/app/assets/javascripts/booth/form.js +78 -0
  25. data/app/assets/javascripts/booth/form.js.map +1 -0
  26. data/app/assets/javascripts/booth/gui.js +53 -0
  27. data/app/assets/javascripts/booth/gui.js.map +1 -0
  28. data/app/assets/javascripts/booth/registration.js +29 -0
  29. data/app/assets/javascripts/booth/registration.js.map +1 -0
  30. data/app/assets/javascripts/booth/setup.js +14 -0
  31. data/app/assets/javascripts/booth/verification.js +49 -0
  32. data/app/assets/javascripts/booth/verification.js.map +1 -0
  33. data/app/assets/javascripts/declarations/authentication.d.ts +6 -0
  34. data/app/assets/javascripts/declarations/error.d.ts +36 -0
  35. data/app/assets/javascripts/declarations/form.d.ts +8 -0
  36. data/app/assets/javascripts/declarations/gui.d.ts +4 -0
  37. data/app/assets/javascripts/declarations/registration.d.ts +6 -0
  38. data/app/assets/javascripts/declarations/setup.d.ts +3 -0
  39. data/app/assets/javascripts/declarations/verification.d.ts +6 -0
  40. data/app/assets/javascripts/src/authentication.ts +41 -0
  41. data/app/assets/javascripts/src/error.ts +35 -0
  42. data/app/assets/javascripts/src/form.ts +90 -0
  43. data/app/assets/javascripts/src/gui.ts +59 -0
  44. data/app/assets/javascripts/src/registration.ts +44 -0
  45. data/app/assets/javascripts/src/verification.ts +61 -0
  46. data/app/assets/stylesheets/booth/booth.css +3 -0
  47. data/config/importmap.rb +11 -0
  48. data/config/locales/de.yml +14 -38
  49. data/config/locales/en.yml +17 -36
  50. data/data/combined_aaguid.json +1 -0
  51. data/lib/booth/adminland/credentials/create.rb +10 -12
  52. data/lib/booth/adminland/credentials/index.rb +31 -0
  53. data/lib/booth/adminland/onboardings/create.rb +24 -15
  54. data/lib/booth/adminland/onboardings/destroy.rb +8 -4
  55. data/lib/booth/adminland/onboardings/find.rb +52 -45
  56. data/lib/booth/adminland/onboardings/find_unconsumed.rb +61 -0
  57. data/lib/booth/adminland/onboardings/index.rb +6 -3
  58. data/lib/booth/adminland/periodic_cleanup.rb +7 -2
  59. data/lib/booth/adminland.rb +17 -18
  60. data/lib/booth/coercers/domain.rb +11 -0
  61. data/lib/booth/coercers/request.rb +51 -0
  62. data/lib/booth/coercers/scope.rb +11 -0
  63. data/lib/booth/comparisons/domain.rb +38 -0
  64. data/lib/booth/comparisons/scope.rb +38 -0
  65. data/lib/booth/concerns/action.rb +25 -13
  66. data/lib/booth/concerns/transition.rb +5 -2
  67. data/lib/booth/configuration.rb +14 -73
  68. data/lib/booth/configure.rb +3 -10
  69. data/lib/booth/{audits/register → core/audit}/completed_onboarding.rb +8 -6
  70. data/lib/booth/core/audit/credential_created.rb +24 -0
  71. data/lib/booth/core/audit/logout.rb +24 -0
  72. data/lib/booth/core/authenticators/confirm.rb +30 -0
  73. data/lib/booth/core/authenticators/step.rb +24 -0
  74. data/lib/booth/core/cooldowns/distance_of_time.rb +50 -0
  75. data/lib/booth/core/cooldowns/strategies/exponential.rb +88 -0
  76. data/lib/booth/core/cooldowns/strategies/global.rb +66 -0
  77. data/lib/booth/core/cooldowns/strategies/result.rb +27 -0
  78. data/lib/booth/core/credentials/create.rb +32 -0
  79. data/lib/booth/core/credentials/find_by_username.rb +63 -0
  80. data/lib/booth/core/credentials/index.rb +15 -0
  81. data/lib/booth/core/credentials/webauth_challenge.rb +37 -0
  82. data/lib/booth/core/geolocation.rb +25 -0
  83. data/lib/booth/core/onboardings/find.rb +92 -0
  84. data/lib/booth/core/onboardings/step.rb +19 -0
  85. data/lib/booth/core/remotes/get.rb +45 -0
  86. data/lib/booth/core/remotes/respond.rb +82 -0
  87. data/lib/booth/core/remotes/set_for_login.rb +31 -0
  88. data/lib/booth/core/sessions/create_and_login.rb +63 -0
  89. data/lib/booth/core/sessions/historical_locations.rb +22 -0
  90. data/lib/booth/core/sessions/index.rb +66 -0
  91. data/lib/booth/core/sessions/revoke.rb +59 -0
  92. data/lib/booth/core/sessions/revoke_all_others.rb +49 -0
  93. data/lib/booth/core/sessions/to_passport.rb +35 -0
  94. data/lib/booth/core/webauth/authentication_verification.rb +76 -0
  95. data/lib/booth/core/webauth/options_for_create.rb +56 -0
  96. data/lib/booth/core/webauth/options_for_get.rb +30 -0
  97. data/lib/booth/core/webauth/provider.rb +36 -0
  98. data/lib/booth/core/webauth/registration_verification.rb +100 -0
  99. data/lib/booth/credential.rb +35 -0
  100. data/lib/booth/engine.rb +15 -4
  101. data/lib/booth/errors.rb +2 -0
  102. data/lib/booth/hooks/after_fetch.rb +14 -6
  103. data/lib/booth/hooks/before_logout.rb +5 -3
  104. data/lib/booth/hooks/serialize_from_session.rb +13 -5
  105. data/lib/booth/hooks/serialize_into_session.rb +6 -3
  106. data/lib/booth/logging.rb +13 -42
  107. data/lib/booth/models/application_record.rb +3 -0
  108. data/lib/booth/models/audit.rb +10 -11
  109. data/lib/booth/models/authenticator.rb +6 -9
  110. data/lib/booth/models/credential.rb +17 -20
  111. data/lib/booth/models/onboarding.rb +16 -39
  112. data/lib/booth/models/{contest.rb → remote.rb} +13 -14
  113. data/lib/booth/models/remotes/scopes/recently_created.rb +26 -0
  114. data/lib/booth/models/remotes/scopes/recently_responded.rb +35 -0
  115. data/lib/booth/models/session.rb +15 -10
  116. data/lib/booth/models/user_agent.rb +2 -0
  117. data/lib/booth/request.rb +43 -22
  118. data/lib/booth/requests/agent.rb +3 -1
  119. data/lib/booth/requests/authentication.rb +15 -5
  120. data/lib/booth/requests/ip.rb +4 -2
  121. data/lib/booth/requests/return_path.rb +4 -2
  122. data/lib/booth/requests/session.rb +6 -4
  123. data/lib/booth/requests/storage.rb +5 -31
  124. data/lib/booth/requests/storages/login.rb +35 -29
  125. data/lib/booth/requests/storages/registration.rb +2 -0
  126. data/lib/booth/requests/storages/webauth.rb +3 -0
  127. data/lib/booth/requests/sudo.rb +6 -50
  128. data/lib/booth/routes/userland.rb +13 -59
  129. data/lib/booth/syntaxes/domain.rb +46 -0
  130. data/lib/booth/syntaxes/email.rb +11 -8
  131. data/lib/booth/syntaxes/ip.rb +6 -4
  132. data/lib/booth/syntaxes/remote_code.rb +60 -0
  133. data/lib/booth/syntaxes/scope.rb +7 -3
  134. data/lib/booth/syntaxes/secret_key.rb +8 -6
  135. data/lib/booth/syntaxes/username.rb +23 -10
  136. data/lib/booth/syntaxes/uuid.rb +3 -1
  137. data/lib/booth/test.rb +27 -22
  138. data/lib/booth/testing/incorporation_test_case.rb +29 -0
  139. data/lib/booth/testing/shortcuts.rb +77 -0
  140. data/lib/booth/testing/support/assert_all_partials_were_covered.rb +69 -0
  141. data/lib/booth/testing/support/assert_logged_in.rb +68 -0
  142. data/lib/booth/{test → testing}/support/assert_logged_out.rb +7 -4
  143. data/lib/booth/testing/support/assert_partial.rb +56 -0
  144. data/lib/booth/{test → testing}/support/force_login.rb +10 -4
  145. data/lib/booth/{test → testing}/support/get_session_value.rb +8 -6
  146. data/lib/booth/testing/support/scenario.rb +23 -0
  147. data/lib/booth/testing/support/shortcuts/create_and_onboard.rb +56 -0
  148. data/lib/booth/testing/support/shortcuts/login_with_passkey.rb +55 -0
  149. data/lib/booth/testing/support/shortcuts/register_new_passkey.rb +51 -0
  150. data/lib/booth/testing/support/soft_reset_session.rb +24 -0
  151. data/lib/booth/testing/support/virtual_authenticators/create.rb +34 -0
  152. data/lib/booth/testing/support/virtual_authenticators/destroy.rb +20 -0
  153. data/lib/booth/testing/support/virtual_authenticators/enable.rb +24 -0
  154. data/lib/booth/testing/support/virtual_authenticators/load.rb +38 -0
  155. data/lib/booth/testing/support/virtual_authenticators/manager.rb +124 -0
  156. data/lib/booth/testing/support/visit.rb +62 -0
  157. data/lib/booth/testing/userland/login_remotely.rb +100 -0
  158. data/lib/booth/testing/userland/onboarding_first_time.rb +81 -0
  159. data/lib/booth/testing/userland/onboarding_to_reset_passkeys.rb +129 -0
  160. data/lib/booth/testing/userland/registration_with_passkey.rb +93 -0
  161. data/lib/booth/testing/userland/registration_without_passkey.rb +101 -0
  162. data/lib/booth/testing/userland/sessions_manage_behavior.rb +68 -0
  163. data/lib/booth/testing/userland/sessions_revoke_all_others.rb +17 -0
  164. data/lib/booth/testing/userland/sessions_revoke_one.rb +17 -0
  165. data/lib/booth/testing/userland.rb +36 -0
  166. data/lib/booth/to_struct.rb +9 -2
  167. data/lib/booth/userland/extract_flash_messages.rb +10 -3
  168. data/lib/booth/userland/logins/create.rb +8 -6
  169. data/lib/booth/userland/logins/destroy.rb +23 -6
  170. data/lib/booth/userland/logins/new.rb +23 -25
  171. data/lib/booth/userland/logins/transitions/create/choose_username.rb +62 -27
  172. data/lib/booth/userland/logins/transitions/create/skip_remotes.rb +18 -14
  173. data/lib/booth/userland/logins/transitions/create/webauth_authentication_initiation.rb +54 -48
  174. data/lib/booth/userland/logins/transitions/create/webauth_authentication_verification.rb +62 -58
  175. data/lib/booth/userland/logins/transitions/new/already_logged_in.rb +4 -3
  176. data/lib/booth/userland/logins/transitions/new/fallible.rb +4 -0
  177. data/lib/booth/userland/logins/transitions/new/{mode_username_and_password.rb → missing_authenticators.rb} +5 -4
  178. data/lib/booth/userland/logins/transitions/new/mode_username_and_webauth.rb +6 -4
  179. data/lib/booth/userland/logins/transitions/new/no_username_chosen.rb +3 -1
  180. data/lib/booth/userland/logins/transitions/new/remote_session_available.rb +20 -13
  181. data/lib/booth/userland/logins/transitions/new/timed_out.rb +3 -1
  182. data/lib/booth/userland/onboardings/show.rb +65 -39
  183. data/lib/booth/userland/onboardings/update.rb +46 -38
  184. data/lib/booth/userland/registrations/create.rb +51 -20
  185. data/lib/booth/userland/registrations/new.rb +6 -7
  186. data/lib/booth/userland/remotes/show.rb +56 -0
  187. data/lib/booth/userland/{personal_contests → remotes}/update.rb +5 -3
  188. data/lib/booth/userland/sessions/destroy_one_or_other.rb +3 -16
  189. data/lib/booth/userland/sessions/index.rb +4 -2
  190. data/lib/booth/userland/sessions/show.rb +5 -6
  191. data/lib/booth/userland/sessions/transitions/destroy/enter_webauth.rb +8 -6
  192. data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_initiation.rb +8 -6
  193. data/lib/booth/userland/sessions/transitions/destroy/webauth_authentication_verification.rb +7 -5
  194. data/lib/booth/userland/sessions/transitions/show/enter_webauth.rb +8 -6
  195. data/lib/booth/userland/webauths/create.rb +20 -17
  196. data/lib/booth/userland/webauths/destroy.rb +6 -16
  197. data/lib/booth/userland/webauths/guards/sudo.rb +10 -5
  198. data/lib/booth/userland/webauths/index.rb +4 -2
  199. data/lib/booth/userland/webauths/new.rb +7 -22
  200. data/lib/booth/userland/webauths/sudo.rb +3 -1
  201. data/lib/booth/userland/webauths/transitions/create/authentication_initiation.rb +8 -11
  202. data/lib/booth/userland/webauths/transitions/create/authentication_verification.rb +11 -13
  203. data/lib/booth/userland/webauths/transitions/create/choose_nickname.rb +8 -5
  204. data/lib/booth/userland/webauths/transitions/create/registration_initiation.rb +15 -14
  205. data/lib/booth/userland/webauths/transitions/create/registration_verification.rb +34 -28
  206. data/lib/booth/userland/webauths/transitions/create/reset.rb +2 -0
  207. data/lib/booth/userland/webauths/transitions/new/step.rb +3 -1
  208. data/lib/booth/userland/webauths/transitions/sudo/authentication_initiation.rb +5 -10
  209. data/lib/booth/userland/webauths/transitions/sudo/authentication_verification.rb +4 -2
  210. data/lib/booth/userland.rb +53 -109
  211. data/lib/booth/version.rb +3 -1
  212. data/lib/booth.rb +6 -236
  213. data/lib/generators/booth/migration/migration_generator.rb +2 -1
  214. data/lib/generators/booth/migration/templates/add_credential_to_users.erb +6 -4
  215. data/lib/generators/booth/migration/templates/create_booth_tables.erb +61 -72
  216. metadata +124 -571
  217. data/app/assets/config/booth_manifest.js +0 -15
  218. data/app/assets/images/booth/browsers/internet_explorer.svg +0 -1
  219. data/app/assets/javascripts/booth/all.js +0 -162
  220. data/app/assets/javascripts/booth/all.js.map +0 -1
  221. data/app/assets/javascripts/booth/booth.ts +0 -194
  222. data/app/assets/javascripts/booth/webauthn-json.ts +0 -99
  223. data/lib/booth/adminland/recoveries/consume.rb +0 -70
  224. data/lib/booth/audits/register/added_otp.rb +0 -22
  225. data/lib/booth/audits/register/changed_otp.rb +0 -22
  226. data/lib/booth/audits/register/correct_otp.rb +0 -42
  227. data/lib/booth/audits/register/correct_password.rb +0 -43
  228. data/lib/booth/audits/register/logout.rb +0 -22
  229. data/lib/booth/audits/register/requested_password_reset.rb +0 -22
  230. data/lib/booth/audits/register/wrong_otp.rb +0 -22
  231. data/lib/booth/audits/register/wrong_password.rb +0 -25
  232. data/lib/booth/authenticators/confirm.rb +0 -34
  233. data/lib/booth/authenticators/credential_mode_after_confirmation.rb +0 -25
  234. data/lib/booth/authenticators/step.rb +0 -19
  235. data/lib/booth/contests/get.rb +0 -36
  236. data/lib/booth/contests/respond.rb +0 -78
  237. data/lib/booth/contests/set_for_login.rb +0 -28
  238. data/lib/booth/cooldowns/distance_of_time.rb +0 -46
  239. data/lib/booth/cooldowns/otp.rb +0 -22
  240. data/lib/booth/cooldowns/password.rb +0 -44
  241. data/lib/booth/cooldowns/password_reset.rb +0 -24
  242. data/lib/booth/cooldowns/strategies/exponential.rb +0 -82
  243. data/lib/booth/cooldowns/strategies/global.rb +0 -62
  244. data/lib/booth/cooldowns/strategies/result.rb +0 -22
  245. data/lib/booth/credentials/create.rb +0 -28
  246. data/lib/booth/credentials/create_with_onboarding.rb +0 -26
  247. data/lib/booth/credentials/find_by_username.rb +0 -45
  248. data/lib/booth/credentials/mode.rb +0 -69
  249. data/lib/booth/credentials/modes/otp_addable.rb +0 -23
  250. data/lib/booth/credentials/modes/otp_changeable.rb +0 -23
  251. data/lib/booth/credentials/modes/otp_manageable.rb +0 -17
  252. data/lib/booth/credentials/modes/otp_removable.rb +0 -23
  253. data/lib/booth/credentials/modes/password_addable.rb +0 -29
  254. data/lib/booth/credentials/modes/password_changeable.rb +0 -31
  255. data/lib/booth/credentials/modes/password_manageable.rb +0 -17
  256. data/lib/booth/credentials/modes/password_removable.rb +0 -24
  257. data/lib/booth/credentials/modes/password_removal_requires_user_verifiable_webauth.rb +0 -16
  258. data/lib/booth/credentials/modes/webauth_addable.rb +0 -26
  259. data/lib/booth/credentials/modes/webauth_manageable.rb +0 -16
  260. data/lib/booth/credentials/modes/webauth_removable.rb +0 -25
  261. data/lib/booth/credentials/otp_authentication.rb +0 -59
  262. data/lib/booth/credentials/password_authentication.rb +0 -72
  263. data/lib/booth/credentials/webauth_challenge.rb +0 -28
  264. data/lib/booth/geolocation.rb +0 -20
  265. data/lib/booth/logger.rb +0 -41
  266. data/lib/booth/method_object.rb +0 -73
  267. data/lib/booth/mode.rb +0 -22
  268. data/lib/booth/models/concerns/modeable.rb +0 -50
  269. data/lib/booth/models/concerns/otpable.rb +0 -37
  270. data/lib/booth/models/concerns/passwordable.rb +0 -58
  271. data/lib/booth/models/contests/scopes/recently_created.rb +0 -23
  272. data/lib/booth/models/contests/scopes/recently_responded.rb +0 -32
  273. data/lib/booth/models/password_reset.rb +0 -41
  274. data/lib/booth/models/recovery.rb +0 -32
  275. data/lib/booth/models/registration.rb +0 -10
  276. data/lib/booth/modes/base.rb +0 -25
  277. data/lib/booth/modes/username_and_password.rb +0 -7
  278. data/lib/booth/modes/username_and_webauth.rb +0 -7
  279. data/lib/booth/modes/username_password_and_otp.rb +0 -7
  280. data/lib/booth/modes/username_password_and_webauth.rb +0 -7
  281. data/lib/booth/onboardings/find.rb +0 -35
  282. data/lib/booth/onboardings/propagate_to_credential.rb +0 -63
  283. data/lib/booth/onboardings/step.rb +0 -68
  284. data/lib/booth/password_resets/create.rb +0 -57
  285. data/lib/booth/password_resets/find.rb +0 -36
  286. data/lib/booth/password_resets/propagate_to_credential.rb +0 -36
  287. data/lib/booth/password_resets/step.rb +0 -18
  288. data/lib/booth/recoveries/create.rb +0 -45
  289. data/lib/booth/requests/storages/otp.rb +0 -54
  290. data/lib/booth/requests/storages/password.rb +0 -49
  291. data/lib/booth/requests/storages/password_reset.rb +0 -35
  292. data/lib/booth/requests/storages/recovery.rb +0 -35
  293. data/lib/booth/sessions/create_and_login.rb +0 -46
  294. data/lib/booth/sessions/historical_locations.rb +0 -18
  295. data/lib/booth/sessions/index.rb +0 -59
  296. data/lib/booth/sessions/revoke.rb +0 -51
  297. data/lib/booth/sessions/revoke_all_others.rb +0 -43
  298. data/lib/booth/sessions/to_passport.rb +0 -51
  299. data/lib/booth/syntaxes/contest_code.rb +0 -58
  300. data/lib/booth/syntaxes/otp.rb +0 -57
  301. data/lib/booth/syntaxes/scope_comparison.rb +0 -28
  302. data/lib/booth/test/helpers.rb +0 -63
  303. data/lib/booth/test/support/assert_all_partials_were_covered.rb +0 -63
  304. data/lib/booth/test/support/assert_logged_in.rb +0 -49
  305. data/lib/booth/test/support/assert_partial.rb +0 -29
  306. data/lib/booth/test/support/otp_code_from_session.rb +0 -30
  307. data/lib/booth/test/support/soft_reset_session.rb +0 -22
  308. data/lib/booth/test/userland/logins/missing_authenticators.rb +0 -72
  309. data/lib/booth/test/userland/logins/missing_onboarding.rb +0 -35
  310. data/lib/booth/test/userland/logins/username_and_password.rb +0 -40
  311. data/lib/booth/test/userland/logins/username_and_webauth.rb +0 -75
  312. data/lib/booth/test/userland/logins/username_password_and_otp.rb +0 -45
  313. data/lib/booth/test/userland/logins/username_password_and_webauth.rb +0 -86
  314. data/lib/booth/test/userland/onboardings/already_logged_in.rb +0 -64
  315. data/lib/booth/test/userland/onboardings/otp.rb +0 -63
  316. data/lib/booth/test/userland/onboardings/password.rb +0 -49
  317. data/lib/booth/test/userland/onboardings/timeout.rb +0 -47
  318. data/lib/booth/test/userland/otps/manage.rb +0 -86
  319. data/lib/booth/test/userland/password_resets/reset.rb +0 -102
  320. data/lib/booth/test/userland.rb +0 -38
  321. data/lib/booth/test/webauthn/disable.rb +0 -17
  322. data/lib/booth/test/webauthn/enable.rb +0 -19
  323. data/lib/booth/test/webauthn/virtual_authenticators/create.rb +0 -38
  324. data/lib/booth/test/webauthn/virtual_authenticators/destroy.rb +0 -20
  325. data/lib/booth/userland/logins/transitions/create/enter_otp.rb +0 -70
  326. data/lib/booth/userland/logins/transitions/create/verify_password.rb +0 -70
  327. data/lib/booth/userland/logins/transitions/new/mode_first_time.rb +0 -20
  328. data/lib/booth/userland/logins/transitions/new/mode_username_password_and_otp.rb +0 -24
  329. data/lib/booth/userland/logins/transitions/new/mode_username_password_and_webauth.rb +0 -24
  330. data/lib/booth/userland/onboardings/transitions/update/choose_mode.rb +0 -58
  331. data/lib/booth/userland/onboardings/transitions/update/choose_password.rb +0 -41
  332. data/lib/booth/userland/onboardings/transitions/update/choose_webauth_nickname.rb +0 -50
  333. data/lib/booth/userland/onboardings/transitions/update/confirm_otp.rb +0 -58
  334. data/lib/booth/userland/onboardings/transitions/update/confirm_password.rb +0 -49
  335. data/lib/booth/userland/onboardings/transitions/update/register_otp.rb +0 -31
  336. data/lib/booth/userland/onboardings/transitions/update/reset_otp.rb +0 -40
  337. data/lib/booth/userland/onboardings/transitions/update/reset_password.rb +0 -35
  338. data/lib/booth/userland/onboardings/transitions/update/reset_webauth.rb +0 -46
  339. data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_initiation.rb +0 -40
  340. data/lib/booth/userland/onboardings/transitions/update/webauth_authentication_verification.rb +0 -59
  341. data/lib/booth/userland/onboardings/transitions/update/webauth_registration_initiation.rb +0 -46
  342. data/lib/booth/userland/onboardings/transitions/update/webauth_registration_verification.rb +0 -56
  343. data/lib/booth/userland/otps/destroy.rb +0 -42
  344. data/lib/booth/userland/otps/edit.rb +0 -72
  345. data/lib/booth/userland/otps/guards/manageable.rb +0 -21
  346. data/lib/booth/userland/otps/guards/sudo.rb +0 -23
  347. data/lib/booth/userland/otps/show.rb +0 -36
  348. data/lib/booth/userland/otps/sudo.rb +0 -51
  349. data/lib/booth/userland/otps/transitions/update/confirm.rb +0 -84
  350. data/lib/booth/userland/otps/transitions/update/register.rb +0 -40
  351. data/lib/booth/userland/otps/transitions/update/reset.rb +0 -31
  352. data/lib/booth/userland/otps/update.rb +0 -34
  353. data/lib/booth/userland/password_resets/create.rb +0 -73
  354. data/lib/booth/userland/password_resets/guards/logged_out.rb +0 -21
  355. data/lib/booth/userland/password_resets/new.rb +0 -57
  356. data/lib/booth/userland/password_resets/show.rb +0 -77
  357. data/lib/booth/userland/password_resets/transitions/update/choose_password.rb +0 -48
  358. data/lib/booth/userland/password_resets/transitions/update/confirm_password.rb +0 -54
  359. data/lib/booth/userland/password_resets/transitions/update/reset_password.rb +0 -29
  360. data/lib/booth/userland/password_resets/update.rb +0 -65
  361. data/lib/booth/userland/passwords/destroy.rb +0 -41
  362. data/lib/booth/userland/passwords/edit.rb +0 -54
  363. data/lib/booth/userland/passwords/guards/manageable.rb +0 -21
  364. data/lib/booth/userland/passwords/guards/removable.rb +0 -21
  365. data/lib/booth/userland/passwords/guards/sudo.rb +0 -21
  366. data/lib/booth/userland/passwords/remove.rb +0 -34
  367. data/lib/booth/userland/passwords/show.rb +0 -32
  368. data/lib/booth/userland/passwords/sudo.rb +0 -55
  369. data/lib/booth/userland/passwords/transitions/remove/step.rb +0 -27
  370. data/lib/booth/userland/passwords/transitions/update/choose_password.rb +0 -62
  371. data/lib/booth/userland/passwords/transitions/update/confirm_password.rb +0 -82
  372. data/lib/booth/userland/passwords/update.rb +0 -33
  373. data/lib/booth/userland/personal_contests/show.rb +0 -60
  374. data/lib/booth/userland/recoveries/create.rb +0 -48
  375. data/lib/booth/userland/recoveries/new.rb +0 -35
  376. data/lib/booth/userland/sessions/transitions/destroy/enter_password.rb +0 -50
  377. data/lib/booth/userland/sessions/transitions/destroy/verify_password.rb +0 -83
  378. data/lib/booth/userland/webauths/guards/manageable.rb +0 -21
  379. data/lib/booth/webauth/authentication_verification.rb +0 -68
  380. data/lib/booth/webauth/demand_user_verification.rb +0 -29
  381. data/lib/booth/webauth/options_for_create.rb +0 -46
  382. data/lib/booth/webauth/options_for_get.rb +0 -29
  383. data/lib/generators/booth/migration/templates/create_booth_mode_types.erb +0 -20
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Sessions
@@ -13,13 +15,13 @@ module Booth
13
15
  def call
14
16
  if sudo.webauth?
15
17
  if session_id_param
16
- debug { 'Having webauth sudo, revoking the desired session...' }
17
- return ::Booth::Sessions::Revoke.call credential_id: authentication.credential_id,
18
- session_id: session_id_param
18
+ log { 'Having webauth sudo, revoking the desired session...' }
19
+ return ::Booth::Core::Sessions::Revoke.call credential_id: authentication.credential_id,
20
+ session_id: session_id_param
19
21
  else
20
- debug { 'Having webauth sudo, revoking all other sessions...' }
21
- return ::Booth::Sessions::RevokeAllOthers.call credential_id: authentication.credential_id,
22
- surviving_session_id: authentication.session_id
22
+ log { 'Having webauth sudo, revoking all other sessions...' }
23
+ return ::Booth::Core::Sessions::RevokeAllOthers.call credential_id: authentication.credential_id,
24
+ surviving_session_id: authentication.session_id
23
25
  end
24
26
  end
25
27
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -8,8 +10,7 @@ module Booth
8
10
  request.must_be_post!
9
11
  request.must_be_logged_in!
10
12
 
11
- ::Booth::Userland::Webauths::Guards::Manageable.call(credential:) { return _1 }
12
- ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return _1 }
13
+ ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return it }
13
14
 
14
15
  do_ensure_authenticator
15
16
  .on_success { do_require_editable_authentictor }
@@ -25,20 +26,32 @@ module Booth
25
26
  authenticator = credential.authenticators.find_or_initialize_by(device_id: nil)
26
27
  authenticator.generate_webauth_id
27
28
 
28
- webauth = ::Booth::Webauth::OptionsForCreate.call(
29
+ webauth = ::Booth::Core::Webauth::OptionsForCreate.call(
29
30
  webauthn_id: authenticator.generate_webauth_id,
31
+ device_ids_to_exclude: credential.registered_authenticator_ids,
30
32
  username: credential.username,
31
- requires_user_verification: enforce_user_verification?
33
+ request:,
32
34
  )
33
35
 
34
36
  authenticator.challenge = webauth.challenge
37
+ authenticator.rp_id = webauth.relying_party_id
35
38
 
36
39
  if authenticator.save
37
40
  storage.authenticator_id = authenticator.id
38
- return Tron.success :authenticator_created if storage.authenticator
41
+ else
42
+ public_message = "Authenticator creation failed: #{authenticator.errors.to_a.to_sentence}"
43
+ log { public_message }
44
+ return Tron.failure :authenticator_persistence_failed,
45
+ public_json: { public_message: },
46
+ http_status: :internal_server_error
39
47
  end
40
48
 
41
- Tron.failure :authenticator_creation_failed
49
+ if storage.authenticator
50
+ Tron.success :authenticator_created
51
+ else
52
+ log { 'Authenticator Cookie persistence failed' }
53
+ Tron.failure :authenticator_creation_failed
54
+ end
42
55
  end
43
56
 
44
57
  def do_require_editable_authentictor
@@ -56,20 +69,10 @@ module Booth
56
69
  ::Booth::Userland::Webauths::Transitions::Create::ChooseNickname,
57
70
  ::Booth::Userland::Webauths::Transitions::Create::RegistrationInitiation,
58
71
  ::Booth::Userland::Webauths::Transitions::Create::RegistrationVerification,
59
- ::Booth::Userland::Webauths::Transitions::Create::Reset,
72
+ ::Booth::Userland::Webauths::Transitions::Create::Reset
60
73
  ]
61
74
  end
62
75
 
63
- # When switching from with-password login to passwordless,
64
- # we need to enable a way to add user-verifiable webauth tokens,
65
- # even though we are currently not passwordless. That's what the param is for.
66
- def enforce_user_verification?
67
- ::Booth::Webauth::DemandUserVerification.call(
68
- credential:,
69
- force: request.params[:enforce_user_verification].present?
70
- )
71
- end
72
-
73
76
  def storage
74
77
  request.storage.webauth
75
78
  end
@@ -1,27 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
4
6
  class Destroy
5
7
  include ::Booth::Concerns::Action
6
8
 
9
+ option :domain
10
+
7
11
  def call
8
12
  request.must_be_delete!
9
13
  request.must_be_html!
10
14
  request.must_be_logged_in!
11
15
 
12
- ::Booth::Userland::Webauths::Guards::Manageable.call(credential:) { return _1 }
13
- ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return _1 }
16
+ ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return it }
14
17
 
15
18
  do_require_eligible_credential
16
19
  .on_success { do_find_authenticator }
17
20
  .on_success { do_destroy_authenticator }
18
- .on_success { do_update_credential }
19
21
  end
20
22
 
21
23
  private
22
24
 
23
25
  def do_require_eligible_credential
24
- return Tron.success :can_remove_webauth if ::Booth::Credentials::Modes::WebauthRemovable.call(credential)
26
+ return Tron.success :can_remove_webauth if credential.authenticators.many?
25
27
 
26
28
  Tron.failure :credential_not_webauth_removable, public_message: I18n.t('booth.webauth_irremovable')
27
29
  end
@@ -39,18 +41,6 @@ module Booth
39
41
  Tron.failure :could_not_remove_authenticator, public_message: I18n.t('booth.authenticator_removal_failed')
40
42
  end
41
43
 
42
- def do_update_credential
43
- if credential.authenticators.present?
44
- return Tron.success(:some_authenticator_removed, public_message: I18n.t('booth.some_authenticator_removed'))
45
- end
46
-
47
- if credential.mode_username_and_password!
48
- return Tron.success :webauth_removed, public_message: I18n.t('booth.webauth_removed')
49
- end
50
-
51
- raise "Could not switch Credential #{credential.id} to `username_and_password`: #{credential.errors.to_a}"
52
- end
53
-
54
44
  def credential
55
45
  @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
56
46
  end
@@ -1,19 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
4
6
  module Guards
5
7
  class Sudo
6
- include ::Booth::MethodObject
8
+ include Calls
9
+ include ::Booth::Logging
7
10
 
8
11
  option :request
9
12
  option :credential
10
13
 
11
14
  def call
12
- return if credential.mode_first_time?
13
- return if credential.mode_username_and_password?
14
- return if credential.mode_username_password_and_otp?
15
+ if credential.authenticators.registered_scope.none?
16
+ log { 'You have no registered Authenticators, not requiring sudo of you' }
17
+ return
18
+ end
15
19
 
16
- request.sudo.guard_with_webauth { yield _1 }
20
+ log { 'You have registered Authenticators, not requiring sudo of you' }
21
+ request.sudo.guard_with_webauth { yield it }
17
22
  end
18
23
  end
19
24
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
6
+ # Lists all currently registered Passkeys for the logged in user.
4
7
  class Index
5
8
  include ::Booth::Concerns::Action
6
9
 
@@ -9,7 +12,6 @@ module Booth
9
12
  request.must_be_html!
10
13
  request.must_be_logged_in!
11
14
 
12
- ::Booth::Userland::Webauths::Guards::Manageable.call(credential:) { return _1 }
13
15
  ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return _1 }
14
16
 
15
17
  do_index
@@ -29,7 +31,7 @@ module Booth
29
31
  ::Booth::ToStruct.call(
30
32
  authenticator.attributes
31
33
  .symbolize_keys
32
- .slice(:id, :confirmed_at, :nickname, :supports_user_verification)
34
+ .slice(:id, :confirmed_at, :nickname)
33
35
  )
34
36
  end
35
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -9,8 +11,6 @@ module Booth
9
11
  request.must_be_html!
10
12
  request.must_be_logged_in!
11
13
 
12
- ::Booth::Userland::Webauths::Guards::Manageable.call(credential:) { return _1 }
13
-
14
14
  # This check must come before the Sudo requirement.
15
15
  if authenticator&.confirmed?
16
16
  return Tron.success :completed, step: :completed,
@@ -18,7 +18,7 @@ module Booth
18
18
  should_add_more_authenticators: should_add_more_authenticators?
19
19
  end
20
20
 
21
- ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return _1 }
21
+ ::Booth::Userland::Webauths::Guards::Sudo.call(request:, credential:) { return it }
22
22
 
23
23
  do_new
24
24
  end
@@ -26,12 +26,10 @@ module Booth
26
26
  private
27
27
 
28
28
  def do_new
29
- debug { "WebAuthn Authenticator registration in step #{step}" }
30
- # debug { authenticator.inspect }
29
+ log { "WebAuthn Authenticator registration in step #{step}" }
30
+ # log { authenticator.inspect }
31
31
 
32
- Tron.success :add_webauth, step:,
33
- nickname: authenticator&.nickname,
34
- enforce_user_verification: enforce_user_verification?
32
+ Tron.success :add_webauth, step:, nickname: authenticator&.nickname
35
33
  end
36
34
 
37
35
  def step
@@ -41,20 +39,7 @@ module Booth
41
39
  end
42
40
 
43
41
  def should_add_more_authenticators?
44
- return true if credential.authenticators.registered_scope.count < 2
45
- return false unless request.authentication.mode == :username_and_webauth
46
-
47
- credential.authenticators.registered_scope.supports_user_verification_scope.count < 2
48
- end
49
-
50
- # When switching from with-password login to passwordless,
51
- # we need to enable a way to add user-verifiable webauth tokens,
52
- # even though we are currently not passwordless. That's what the param is for.
53
- def enforce_user_verification?
54
- ::Booth::Webauth::DemandUserVerification.call(
55
- credential:,
56
- force: params[:enforce_user_verification].present?
57
- )
42
+ credential.authenticators.registered_scope.count < 2
58
43
  end
59
44
 
60
45
  def authenticator
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -16,7 +18,7 @@ module Booth
16
18
  def transitions
17
19
  [
18
20
  ::Booth::Userland::Webauths::Transitions::Sudo::AuthenticationInitiation,
19
- ::Booth::Userland::Webauths::Transitions::Sudo::AuthenticationVerification,
21
+ ::Booth::Userland::Webauths::Transitions::Sudo::AuthenticationVerification
20
22
  ]
21
23
  end
22
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -7,7 +9,7 @@ module Booth
7
9
  include ::Booth::Concerns::Transition
8
10
 
9
11
  def self.applicable?(params:)
10
- params.key?(:test) && !params&.key?(:webauth)
12
+ params.key?(:test) && !params&.key?(:handshake)
11
13
  end
12
14
 
13
15
  def call
@@ -17,15 +19,16 @@ module Booth
17
19
  private
18
20
 
19
21
  def do_challenge
20
- webauth = ::Booth::Webauth::OptionsForGet.call(
22
+ webauth = ::Booth::Core::Webauth::OptionsForGet.call(
21
23
  allowed_device_ids: authenticator.device_id,
22
- requires_user_verification: enforce_user_verification?
24
+ request:,
23
25
  )
24
26
 
25
- debug { "Remembering test challenge #{webauth.challenge.inspect}" }
27
+ log { "Remembering test challenge #{webauth.challenge.inspect}" }
26
28
 
27
29
  if authenticator.update challenge: webauth.challenge
28
- Tron.success :test_challenge_created, public_json: webauth.as_json, http_status: :created
30
+ Tron.success :test_challenge_created, public_json: webauth.as_json,
31
+ http_status: :created
29
32
  else
30
33
  Tron.failure :storing_test_challenge_failed
31
34
  end
@@ -38,12 +41,6 @@ module Booth
38
41
  def credential
39
42
  @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
40
43
  end
41
-
42
- # I.e. modes `first_time` and `username_and_webauth`.
43
- # TODO: Also when force-adding an authenticator for removing a password.
44
- def enforce_user_verification?
45
- !credential.passworded?
46
- end
47
44
  end
48
45
  end
49
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -7,7 +9,7 @@ module Booth
7
9
  include ::Booth::Concerns::Transition
8
10
 
9
11
  def self.applicable?(params:)
10
- params.key?(:test) && params[:webauth].key?(:rawId)
12
+ params.key?(:test) && params[:handshake].key?(:rawId)
11
13
  end
12
14
 
13
15
  def call
@@ -20,20 +22,16 @@ module Booth
20
22
  private
21
23
 
22
24
  def do_verify_response
23
- debug { 'Verifying challenge...' }
24
- # TODO: Replate with ::Booth::Webauth::AuthenticationVerification
25
- webauth.verify(authenticator.challenge,
26
- public_key: authenticator.public_key,
27
- sign_count: authenticator.sign_count)
28
-
29
- Tron.success :challenge_response_correct
30
- rescue WebAuthn::Error => e
31
- debug { "Webauth Handshake failed: #{e.message}" }
32
- Tron.failure :invalid_challenge_response
25
+ log { 'Verifying challenge...' }
26
+ ::Booth::Core::Webauth::AuthenticationVerification.call(
27
+ request:,
28
+ credential_id: authenticator.credential.id,
29
+ challenge: authenticator.challenge,
30
+ )
33
31
  end
34
32
 
35
33
  def do_persist_confirmation
36
- confirmation = ::Booth::Authenticators::Confirm.call(authenticator:,
34
+ confirmation = ::Booth::Core::Authenticators::Confirm.call(authenticator:,
37
35
  sign_count: webauth.sign_count)
38
36
 
39
37
  if confirmation.success?
@@ -50,7 +48,7 @@ module Booth
50
48
  end
51
49
 
52
50
  def webauth_params
53
- params.require(:webauth).permit!
51
+ params.require(:handshake).permit!
54
52
  end
55
53
 
56
54
  def authenticator
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
4
6
  module Transitions
5
7
  module Create
8
+ # User submits form to set custom name for a registered Passkey.
6
9
  class ChooseNickname
7
10
  include ::Booth::Concerns::Transition
8
11
 
@@ -20,27 +23,27 @@ module Booth
20
23
  def do_check_blank_nickname
21
24
  return Tron.success :nickname_is_present if nickname_param.present?
22
25
 
23
- debug { 'The nickname was blank' }
26
+ log { 'The nickname was blank' }
24
27
  Tron.failure :nickname_is_blank, public_message: I18n.t('booth.blank_nickname')
25
28
  end
26
29
 
27
30
  def do_update_authenticator
28
31
  if authenticator.update nickname: nickname_param
29
- debug { 'The nickname successfully changed' }
32
+ log { 'The nickname successfully changed' }
30
33
  Tron.success :nickname_saved
31
34
  else
32
35
  public_message = authenticator.errors.to_a.to_sentence
33
- debug { "The nickname could not be updated: #{public_message}" }
36
+ log { "The nickname could not be updated: #{public_message}" }
34
37
  Tron.failure :nickname_failed, public_message:
35
38
  end
36
39
  end
37
40
 
38
41
  def nickname_param
39
- params.require(:webauth).permit(:nickname)[:nickname]
42
+ params.expect(webauth: [:nickname])[:nickname]
40
43
  end
41
44
 
42
45
  def authenticator
43
- request.storage.webauth.authenticator
46
+ @authenticator ||= request.storage.webauth.authenticator
44
47
  end
45
48
  end
46
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -7,7 +9,7 @@ module Booth
7
9
  include ::Booth::Concerns::Transition
8
10
 
9
11
  def self.applicable?(params:)
10
- params&.key?(:register) && !params&.key?(:webauth)
12
+ params&.key?(:register) && !params&.key?(:handshake)
11
13
  end
12
14
 
13
15
  def call
@@ -18,16 +20,17 @@ module Booth
18
20
  private
19
21
 
20
22
  def do_require_authenticator
21
- return Tron.success :authenticator_waiting_for_registration if storage.authenticator.step == :register
23
+ if storage.authenticator.step == :register
24
+ return Tron.success :authenticator_waiting_for_registration
25
+ end
22
26
 
23
27
  Tron.failure :authenticator_not_registerable
24
28
  end
25
29
 
26
30
  def do_challenge
27
- debug { "Remembering registration challenge #{webauth.challenge.inspect}" }
31
+ log { "Remembering registration challenge #{webauth.challenge.inspect}" }
28
32
 
29
- if storage.authenticator.update challenge: webauth.challenge,
30
- supports_user_verification: enforce_user_verification?
33
+ if storage.authenticator.update challenge: webauth.challenge
31
34
  return Tron.success :registration_challenge_created, public_json: webauth.as_json,
32
35
  http_status: :created
33
36
  end
@@ -36,23 +39,21 @@ module Booth
36
39
  end
37
40
 
38
41
  def webauth
39
- @webauth ||= ::Booth::Webauth::OptionsForCreate.call(
42
+ @webauth ||= ::Booth::Core::Webauth::OptionsForCreate.call(
40
43
  webauthn_id: storage.authenticator.webauthn_id,
44
+ device_ids_to_exclude: credential.registered_authenticator_ids,
41
45
  username: storage.authenticator.credential.username,
42
- requires_user_verification: enforce_user_verification?
43
- )
44
- end
45
-
46
- def enforce_user_verification?
47
- ::Booth::Webauth::DemandUserVerification.call(
48
- credential: storage.authenticator.credential,
49
- force: request.params[:enforce_user_verification].present?
46
+ request:,
50
47
  )
51
48
  end
52
49
 
53
50
  def storage
54
51
  request.storage.webauth
55
52
  end
53
+
54
+ def credential
55
+ @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
56
+ end
56
57
  end
57
58
  end
58
59
  end
@@ -1,13 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
4
6
  module Transitions
5
7
  module Create
8
+ # Controller Transition to verify and persist a new hardware key.
6
9
  class RegistrationVerification
7
10
  include ::Booth::Concerns::Transition
11
+ include ::Booth::Logging
8
12
 
9
13
  def self.applicable?(params:)
10
- params&.key?(:register) && params[:webauth]&.key?(:rawId)
14
+ params&.key?(:register) && params[:handshake]&.key?(:rawId)
11
15
  end
12
16
 
13
17
  def call
@@ -18,47 +22,49 @@ module Booth
18
22
  private
19
23
 
20
24
  def do_verify_response
21
- debug { "Verifying challenge #{authenticator.challenge.inspect}" }
22
- # TODO: Replate with ::Booth::Webauth::RegistrationVerification (?)
23
- webauth.verify(authenticator.challenge)
25
+ if credential_id != request.storage.webauth.authenticator&.credential_id
26
+ log { "Credential #{credential_id} does not match Authenticator #{request.storage.webauth.authenticator&.credential_id}" }
27
+ return Tron.failure :authenticator_credential_mismatch
28
+ end
24
29
 
25
- Tron.success :challenge_response_correct
26
- rescue WebAuthn::Error => e
27
- debug { "Webauth Handshake failed: #{e.message}" }
28
- Tron.failure :invalid_challenge_response
30
+ @verification = ::Booth::Core::Webauth::RegistrationVerification.call(credential_id:,
31
+ challenge:,
32
+ handshake:,
33
+ request:)
34
+ sudo.webauthn_challenge = nil
35
+ sudo.webauth! if @verification.failure?
36
+ @verification
29
37
  end
30
38
 
31
39
  def do_persist_keys
32
- debug { "Persisting authenticator information, the sign count is now at #{webauth.sign_count}..." }
33
- if authenticator.update(device_id: ::Base64.strict_encode64(webauth.raw_id),
34
- public_key: webauth.public_key,
35
- sign_count: webauth.sign_count)
40
+ log { 'Persisting onboarding-authenticator metadata' }
36
41
 
37
- return Tron.success :challenge_accepted, public_json: {}, http_status: :created
42
+ if request.storage.webauth.authenticator.update(device_id: @verification.device_id,
43
+ aaguid: @verification.aaguid,
44
+ issuer: @verification.issuer,
45
+ attachment: @verification.attachment,
46
+ public_key: @verification.public_key,
47
+ sign_count: @verification.sign_count)
48
+ # request.storage.webauth.reset
49
+ return Tron.success :webauth_registration_verification_successful,
50
+ public_json: {},
51
+ http_status: :created
38
52
  end
39
-
40
53
  Tron.failure :storing_response_failed
41
54
  end
42
55
 
43
- def webauth
44
- @webauth ||= ::WebAuthn::Credential.from_create(webauth_params)
45
- end
56
+ delegate :sudo, to: :request
46
57
 
47
- def webauth_params
48
- params.require(:webauth).permit!
58
+ def credential_id
59
+ request.authentication.credential_id
49
60
  end
50
61
 
51
- # def credential
52
- # @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
53
- # end
54
-
55
- def mode_after_update
56
- @mode_after_update ||= ::Booth::Webauth::ModeAfterAdd.call(credential:,
57
- authenticator:)
62
+ def challenge
63
+ request.storage.webauth.authenticator&.challenge
58
64
  end
59
65
 
60
- def authenticator
61
- request.storage.webauth.authenticator
66
+ def handshake
67
+ request.params.require(:handshake).permit!
62
68
  end
63
69
  end
64
70
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # module Booth
2
4
  # module Userland
3
5
  # module Webauths
4
6
  # module New
5
7
  # class Step
6
- # include ::Booth::MethodObject
8
+ # include Calls
7
9
 
8
10
  # param :authenticator
9
11
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Booth
2
4
  module Userland
3
5
  module Webauths
@@ -17,12 +19,12 @@ module Booth
17
19
  private
18
20
 
19
21
  def do_challenge
20
- webauth = ::Booth::Webauth::OptionsForGet.call(
22
+ webauth = ::Booth::Core::Webauth::OptionsForGet.call(
21
23
  allowed_device_ids: credential.registered_authenticator_ids,
22
- requires_user_verification: enforce_user_verification?
24
+ request:,
23
25
  )
24
26
 
25
- debug { "Remembering sudo challenge #{webauth.challenge.inspect}" }
27
+ log { "Remembering sudo challenge #{webauth.challenge.inspect}" }
26
28
 
27
29
  request.sudo.webauthn_challenge = webauth.challenge
28
30
  Tron.success :test_challenge_created, public_json: webauth.as_json,
@@ -32,13 +34,6 @@ module Booth
32
34
  def credential
33
35
  @credential ||= ::Booth::Models::Credential.find(request.authentication.credential_id)
34
36
  end
35
-
36
- def enforce_user_verification?
37
- ::Booth::Webauth::DemandUserVerification.call(
38
- credential:,
39
- force: params[:enforce_user_verification].present?
40
- )
41
- end
42
37
  end
43
38
  end
44
39
  end