Class: UserSessionForm
- Inherits:
-
Object
show all
- Includes:
- ActiveModel::Validations, SentryLogging
- Defined in:
- app/models/user_session_form.rb
Constant Summary
collapse
- VALIDATIONS_FAILED_ERROR_CODE =
'004'
- SAML_REPLAY_VALID_SESSION_ERROR_CODE =
'002'
- ERRORS =
{ validations_failed: { code: VALIDATIONS_FAILED_ERROR_CODE,
tag: :validations_failed,
short_message: 'on User/Session Validation',
level: :error },
saml_replay_valid_session: { code: SAML_REPLAY_VALID_SESSION_ERROR_CODE,
tag: :saml_replay_valid_session,
short_message: 'SamlResponse is too late but user has current session',
level: :warn } }.freeze
Instance Attribute Summary collapse
Instance Method Summary
collapse
#log_exception_to_sentry, #log_message_to_sentry, #non_nil_hash?, #normalize_level, #rails_logger
Constructor Details
rubocop:disable Metrics/MethodLength
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
|
# File 'app/models/user_session_form.rb', line 22
def initialize(saml_response)
@saml_uuid = saml_response.in_response_to
saml_user = SAML::User.new(saml_response)
normalized_attributes = normalize_saml(saml_user)
existing_user = User.find(normalized_attributes[:uuid])
@user_identity = UserIdentity.new(normalized_attributes)
@user = User.new(uuid: @user_identity.attributes[:uuid])
@user.instance_variable_set(:@identity, @user_identity)
if saml_user.changing_multifactor?
if existing_user.present?
@user.mhv_last_signed_in = existing_user.last_signed_in
@user.last_signed_in = existing_user.last_signed_in
else
@user.last_signed_in = Time.current.utc
@user.mhv_last_signed_in = Time.current.utc
log_message_to_sentry(
"Couldn't locate exiting user after MFA establishment",
:warn,
{ saml_uuid: normalized_attributes[:uuid], saml_icn: normalized_attributes[:mhv_icn] }
)
end
else
@user.last_signed_in = Time.current.utc
end
@session = Session.new(
uuid: @user.uuid,
ssoe_transactionid: saml_user.user_attributes.try(:transactionid)
)
end
|
Instance Attribute Details
#saml_uuid ⇒ Object
Returns the value of attribute saml_uuid.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def saml_uuid
@saml_uuid
end
|
#session ⇒ Object
Returns the value of attribute session.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def session
@session
end
|
#user ⇒ Object
Returns the value of attribute user.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def user
@user
end
|
#user_identity ⇒ Object
Returns the value of attribute user_identity.
19
20
21
|
# File 'app/models/user_session_form.rb', line 19
def user_identity
@user_identity
end
|
Instance Method Details
#add_csp_id_to_mpi(saml_user_attributes, idme_uuid) ⇒ Object
70
71
72
73
74
75
76
77
78
79
80
|
# File 'app/models/user_session_form.rb', line 70
def add_csp_id_to_mpi(saml_user_attributes, idme_uuid)
return unless saml_user_attributes[:loa][:current] == LOA::THREE
Rails.logger.info("[UserSessionForm] Adding CSP ID to MPI, idme: #{idme_uuid}")
mpi_response = MPI::Service.new.add_person_implicit_search(first_name: saml_user_attributes[:first_name],
last_name: saml_user_attributes[:last_name],
ssn: saml_user_attributes[:ssn],
birth_date: saml_user_attributes[:birth_date],
idme_uuid:)
log_message_to_sentry("Failed Add CSP ID to MPI FAILED, idme: #{idme_uuid}", :warn) unless mpi_response.ok?
end
|
#error_code ⇒ Object
156
157
158
|
# File 'app/models/user_session_form.rb', line 156
def error_code
errors_hash[:code] if errors.any?
end
|
#error_instrumentation_code ⇒ Object
160
161
162
|
# File 'app/models/user_session_form.rb', line 160
def error_instrumentation_code
"error:#{errors_hash[:tag]}" if errors.any?
end
|
#errors_context ⇒ Object
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# File 'app/models/user_session_form.rb', line 126
def errors_context
errors_hash.merge(
uuid: @user.uuid,
user: {
valid: @user&.valid?,
errors: @user&.errors&.full_messages
},
session: {
valid: (@session.valid? && !@session.uuid.nil?),
errors: get_session_errors
},
identity: {
valid: @user_identity&.valid?,
errors: @user_identity&.errors&.full_messages,
authn_context: @user_identity&.authn_context,
loa: @user_identity&.loa
},
mvi: mvi_context
)
end
|
#errors_hash ⇒ Object
122
123
124
|
# File 'app/models/user_session_form.rb', line 122
def errors_hash
ERRORS[:validations_failed] if errors.any?
end
|
#errors_message ⇒ Object
118
119
120
|
# File 'app/models/user_session_form.rb', line 118
def errors_message
@errors_message ||= "Login Failed! #{errors_hash[:short_message]}" if errors.any?
end
|
#get_session_errors ⇒ Object
101
102
103
104
|
# File 'app/models/user_session_form.rb', line 101
def get_session_errors
@session.errors.add(:uuid, "can't be blank") if @session.uuid.nil?
@session.errors&.full_messages
end
|
#mvi_context ⇒ Object
147
148
149
150
151
152
153
154
|
# File 'app/models/user_session_form.rb', line 147
def mvi_context
latest_outage = MPI::Configuration.instance.breakers_service.latest_outage
if latest_outage && !latest_outage.ended?
'breakers is closed for MVI'
else
'breakers is open for MVI'
end
end
|
#normalize_saml(saml_user) ⇒ Object
rubocop:enable Metrics/MethodLength
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
# File 'app/models/user_session_form.rb', line 53
def normalize_saml(saml_user)
saml_user.validate!
saml_user_attributes = saml_user.to_hash
add_csp_id_to_mpi(saml_user_attributes, saml_user_attributes[:idme_uuid]) if saml_user.needs_csp_id_mpi_update?
saml_user_attributes
rescue SAML::UserAttributeError => e
raise unless e.code == SAML::UserAttributeError::UUID_MISSING_CODE
idme_uuid = uuid_from_account(e&.identifier)
raise if idme_uuid.blank?
Rails.logger.info('Account UUID injected into user SAML attributes')
saml_user_attributes = saml_user.to_hash
add_csp_id_to_mpi(saml_user_attributes, idme_uuid)
saml_user_attributes.merge({ uuid: idme_uuid, idme_uuid: })
end
|
#persist ⇒ Object
110
111
112
113
114
115
116
|
# File 'app/models/user_session_form.rb', line 110
def persist
if save
[user, session]
else
[nil, nil]
end
end
|
#save ⇒ Object
106
107
108
|
# File 'app/models/user_session_form.rb', line 106
def save
valid? && session.save && user.save && @user_identity.save
end
|
#uuid_from_account(identifier) ⇒ Object
82
83
84
85
86
87
88
89
90
91
92
|
# File 'app/models/user_session_form.rb', line 82
def uuid_from_account(identifier)
return if identifier.blank?
user_account = UserAccount.find_by(icn: identifier)
return unless user_account
idme_uuid_array = user_account.user_verifications.map(&:idme_uuid) +
user_account.user_verifications.map(&:backing_idme_uuid)
idme_uuid_array.compact.first
end
|
#valid? ⇒ Boolean
94
95
96
97
98
99
|
# File 'app/models/user_session_form.rb', line 94
def valid?
errors.add(:session, :invalid) unless session.valid?
errors.add(:user, :invalid) unless user.valid?
errors.add(:user_identity, :invalid) unless @user_identity.valid?
errors.empty?
end
|