File: webauthn_login.rb

package info (click to toggle)
ruby-rodauth 2.42.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 812 kB
  • sloc: ruby: 7,524; javascript: 100; makefile: 4
file content (97 lines) | stat: -rw-r--r-- 2,482 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# frozen-string-literal: true

module Rodauth
  Feature.define(:webauthn_login, :WebauthnLogin) do
    depends :login, :webauthn

    before

    redirect(:webauthn_login_failure){require_login_redirect}

    error_flash "There was an error authenticating via WebAuthn"

    auth_value_method :webauthn_login_user_verification_additional_factor?, false

    internal_request_method :webauthn_login_params
    internal_request_method :webauthn_login

    route(:webauthn_login) do |r|
      check_already_logged_in
      before_webauthn_login_route

      r.post do
        catch_error do
          unless account_from_webauthn_login && open_account?
            throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message) 
          end

          webauthn_credential = webauthn_auth_credential_from_form_submission
          before_webauthn_login
          login('webauthn') do
            webauthn_update_session(webauthn_credential.id)
            if webauthn_login_verification_factor?(webauthn_credential)
              two_factor_update_session('webauthn-verification')
            end
          end
        end

        set_redirect_error_flash webauthn_login_error_flash
        redirect webauthn_login_failure_redirect
      end
    end

    def webauthn_auth_additional_form_tags
      if @webauthn_login
        super.to_s + login_hidden_field
      else
        super
      end
    end

    def webauthn_auth_form_path
      if @webauthn_login
        webauthn_login_path
      else
        super
      end
    end

    def webauthn_user_verification
      return 'preferred' if webauthn_login_user_verification_additional_factor?
      super
    end

    def use_multi_phase_login?
      true
    end

    private

    def webauthn_login_verification_factor?(webauthn_credential)
      webauthn_login_user_verification_additional_factor? &&
        webauthn_credential.response.authenticator_data.user_verified? &&
        uses_two_factor_authentication?
    end

    def account_from_webauthn_login
      account_from_login(login_param_value)
    end

    def webauthn_login_options?
      !!account_from_webauthn_login
    end

    def _multi_phase_login_forms
      forms = super
      if valid_login_entered? && webauthn_setup?
        @webauthn_login = true
        forms << [20, render('webauthn-auth'), nil]
      end
      forms
    end

    def webauthn_account_id
      super || account_id
    end
  end
end