Welcome to mirror list, hosted at ThFree Co, Russian Federation.

combined_two_factor_authenticatable.rb « strategies « devise « auth « gitlab « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ef326fd2a991f14258ab09cb21178f20118dde3d (plain)
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
# frozen_string_literal: true

module Gitlab
  module Auth
    module Devise
      module Strategies
        # This strategy combines the following strategies from
        # devise_two_factor gem:
        # - TwoFactorAuthenticatable: https://github.com/devise-two-factor/devise-two-factor/blob/v4.0.2/lib/devise_two_factor/strategies/two_factor_authenticatable.rb
        # - TwoFactorBackupable: https://github.com/devise-two-factor/devise-two-factor/blob/v4.0.2/lib/devise_two_factor/strategies/two_factor_backupable.rb
        # to avoid double incrementing failed login attempts counter by each
        # strategy in case an incorrect password is provided.
        class CombinedTwoFactorAuthenticatable < ::Devise::Strategies::DatabaseAuthenticatable
          def authenticate!
            resource = mapping.to.find_for_database_authentication(authentication_hash)

            # We check the OTP / backup code, then defer to DatabaseAuthenticatable
            is_valid = validate(resource) do
              validate_otp(resource) || resource.invalidate_otp_backup_code!(params[scope]['otp_attempt'])
            end

            if is_valid
              # Devise fails to authenticate invalidated resources, but if we've
              # gotten here, the object changed (Since we deleted a recovery code)
              resource.save!

              super
            end

            fail(::Devise.paranoid ? :invalid : :not_found_in_database) unless resource # rubocop: disable Style/SignalException

            # We want to cascade to the next strategy if this one fails,
            # but database authenticatable automatically halts on a bad password
            @halted = false if @result == :failure
          end

          def validate_otp(resource)
            return true unless resource.otp_required_for_login

            return if params[scope]['otp_attempt'].nil?

            resource.validate_and_consume_otp!(params[scope]['otp_attempt'])
          end
        end
      end
    end
  end
end

Warden::Strategies.add(
  :combined_two_factor_authenticatable,
  Gitlab::Auth::Devise::Strategies::CombinedTwoFactorAuthenticatable)