Module: SignIn::Authentication

Extended by:
ActiveSupport::Concern
Included in:
AuthenticationAndSSOConcerns, Instrumentation, ApplicationController, ServiceAccountApplicationController
Defined in:
app/controllers/concerns/sign_in/authentication.rb

Constant Summary collapse

BEARER_PATTERN =
/^Bearer /

Instance Method Summary collapse

Instance Method Details

#access_tokenObject (private)



47
48
49
# File 'app/controllers/concerns/sign_in/authentication.rb', line 47

def access_token
  @access_token ||= authenticate_access_token
end

#access_token_authenticate(skip_error_handling: false) ⇒ Object (protected)



37
38
39
40
41
42
43
# File 'app/controllers/concerns/sign_in/authentication.rb', line 37

def access_token_authenticate(skip_error_handling: false)
  access_token.present?
rescue Errors::AccessTokenExpiredError => e
  render json: { errors: e }, status: :forbidden unless skip_error_handling
rescue Errors::StandardError => e
  handle_authenticate_error(e) unless skip_error_handling
end

#authenticateObject (protected)



17
18
19
20
21
22
23
24
25
# File 'app/controllers/concerns/sign_in/authentication.rb', line 17

def authenticate
  @current_user = load_user_object
  validate_request_ip
  @current_user.present?
rescue Errors::AccessTokenExpiredError => e
  render json: { errors: e }, status: :forbidden
rescue Errors::StandardError => e
  handle_authenticate_error(e)
end

#authenticate_access_token(with_validation: true) ⇒ Object (private)



62
63
64
65
# File 'app/controllers/concerns/sign_in/authentication.rb', line 62

def authenticate_access_token(with_validation: true)
  access_token_jwt = bearer_token || cookie_access_token
  AccessTokenJwtDecoder.new(access_token_jwt:).perform(with_validation:)
end

#bearer_tokenObject (private)



51
52
53
54
# File 'app/controllers/concerns/sign_in/authentication.rb', line 51

def bearer_token
  header = request.authorization
  header.gsub(BEARER_PATTERN, '') if header&.match(BEARER_PATTERN)
end


56
57
58
59
60
# File 'app/controllers/concerns/sign_in/authentication.rb', line 56

def cookie_access_token(access_token_cookie_name: Constants::Auth::ACCESS_TOKEN_COOKIE_NAME)
  return unless defined?(cookies)

  cookies[access_token_cookie_name]
end

#handle_authenticate_error(error, access_token_cookie_name: Constants::Auth::ACCESS_TOKEN_COOKIE_NAME) ⇒ Object (private)



71
72
73
74
75
76
77
78
79
# File 'app/controllers/concerns/sign_in/authentication.rb', line 71

def handle_authenticate_error(error, access_token_cookie_name: Constants::Auth::ACCESS_TOKEN_COOKIE_NAME)
  context = {
    access_token_authorization_header: scrub_bearer_token,
    access_token_cookie: cookie_access_token(access_token_cookie_name:)
  }.compact

  log_message_to_sentry(error.message, :error, context) if context.present?
  render json: { errors: error }, status: :unauthorized
end

#load_user(skip_expiration_check: false) ⇒ Object (protected)



27
28
29
30
31
32
33
34
35
# File 'app/controllers/concerns/sign_in/authentication.rb', line 27

def load_user(skip_expiration_check: false)
  @current_user = load_user_object
  validate_request_ip
  @current_user.present?
rescue Errors::AccessTokenExpiredError => e
  render json: { errors: e }, status: :forbidden unless skip_expiration_check
rescue Errors::StandardError
  nil
end

#load_user_objectObject (private)



67
68
69
# File 'app/controllers/concerns/sign_in/authentication.rb', line 67

def load_user_object
  UserLoader.new(access_token:, request_ip: request.remote_ip).perform
end

#scrub_bearer_tokenObject (private)



81
82
83
# File 'app/controllers/concerns/sign_in/authentication.rb', line 81

def scrub_bearer_token
  bearer_token == 'undefined' ? nil : bearer_token
end

#validate_request_ipObject (private)



85
86
87
88
89
90
91
92
# File 'app/controllers/concerns/sign_in/authentication.rb', line 85

def validate_request_ip
  return if @current_user.fingerprint == request.remote_ip

  log_context = { request_ip: request.remote_ip, fingerprint: @current_user.fingerprint }
  Rails.logger.warn('[SignIn][Authentication] fingerprint mismatch', log_context)
  @current_user.fingerprint = request.remote_ip
  @current_user.save
end