Class: SAML::UserAttributes::SSOe

Inherits:
Object
  • Object
show all
Includes:
Identity::Parsers::GCIds, SentryLogging
Defined in:
lib/saml/user_attributes/ssoe.rb

Constant Summary collapse

SERIALIZABLE_ATTRIBUTES =
%i[email first_name middle_name last_name gender ssn birth_date
uuid idme_uuid logingov_uuid verified_at sec_id mhv_icn
mhv_correlation_id mhv_account_type edipi loa sign_in multifactor icn].freeze
INBOUND_AUTHN_CONTEXT =
'urn:oasis:names:tc:SAML:2.0:ac:classes:Password'

Constants included from Identity::Parsers::GCIdsConstants

Identity::Parsers::GCIdsConstants::ACTIVE_MHV_IDS_REGEX, Identity::Parsers::GCIdsConstants::BIRLS_IDS_REGEX, Identity::Parsers::GCIdsConstants::CERNER_FACILITY_IDS_REGEX, Identity::Parsers::GCIdsConstants::CERNER_ID_REGEX, Identity::Parsers::GCIdsConstants::DOD_ROOT_OID, Identity::Parsers::GCIdsConstants::EDIPI_REGEX, Identity::Parsers::GCIdsConstants::ICN_ASSIGNING_AUTHORITY_ID, Identity::Parsers::GCIdsConstants::ICN_REGEX, Identity::Parsers::GCIdsConstants::IDENTIFIERS_SPLIT_TOKEN, Identity::Parsers::GCIdsConstants::IDME_ID_REGEX, Identity::Parsers::GCIdsConstants::IDS_SPLIT_TOKEN, Identity::Parsers::GCIdsConstants::ID_MAPPINGS, Identity::Parsers::GCIdsConstants::LOGINGOV_ID_REGEX, Identity::Parsers::GCIdsConstants::MHV_IDS_REGEX, Identity::Parsers::GCIdsConstants::MHV_IEN_REGEX, Identity::Parsers::GCIdsConstants::PERMANENT_ICN_REGEX, Identity::Parsers::GCIdsConstants::SEC_ID_REGEX, Identity::Parsers::GCIdsConstants::VA_ROOT_OID, Identity::Parsers::GCIdsConstants::VBA_CORP_ID_REGEX, Identity::Parsers::GCIdsConstants::VET360_ID_REGEX, Identity::Parsers::GCIdsConstants::VHA_FACILITY_IDS_REGEX

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Identity::Parsers::GCIds

#parse_string_gcids, #parse_xml_gcids

Methods included from Identity::Parsers::GCIdsHelper

#sanitize_edipi, #sanitize_id, #sanitize_id_array

Methods included from SentryLogging

#log_exception_to_sentry, #log_message_to_sentry, #non_nil_hash?, #normalize_level, #rails_logger

Constructor Details

#initialize(saml_attributes, authn_context, tracker_uuid) ⇒ SSOe

Returns a new instance of SSOe.



19
20
21
22
23
24
# File 'lib/saml/user_attributes/ssoe.rb', line 19

def initialize(saml_attributes, authn_context, tracker_uuid)
  @attributes = saml_attributes # never default this to {}
  @authn_context = authn_context
  @tracker_uuid = tracker_uuid
  @warnings = []
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



17
18
19
# File 'lib/saml/user_attributes/ssoe.rb', line 17

def attributes
  @attributes
end

#authn_contextObject (readonly)

Returns the value of attribute authn_context.



17
18
19
# File 'lib/saml/user_attributes/ssoe.rb', line 17

def authn_context
  @authn_context
end

#tracker_uuidObject (readonly)

Returns the value of attribute tracker_uuid.



17
18
19
# File 'lib/saml/user_attributes/ssoe.rb', line 17

def tracker_uuid
  @tracker_uuid
end

#warningsObject (readonly)

Returns the value of attribute warnings.



17
18
19
# File 'lib/saml/user_attributes/ssoe.rb', line 17

def warnings
  @warnings
end

Instance Method Details

#account_typeObject



167
168
169
170
171
172
# File 'lib/saml/user_attributes/ssoe.rb', line 167

def 
  result = 
  result ||= 
  result ||= 'N/A'
  result
end

#birth_dateObject



54
55
56
57
58
59
60
61
# File 'lib/saml/user_attributes/ssoe.rb', line 54

def birth_date
  bd = safe_attr('va_eauth_birthDate_v1')
  begin
    Date.parse(bd).strftime('%Y-%m-%d')
  rescue TypeError, ArgumentError
    nil
  end
end

#dslogon_account_typeObject



116
117
118
# File 'lib/saml/user_attributes/ssoe.rb', line 116

def 
  safe_attr('va_eauth_dslogonassurance')
end

#dslogon_loa_highestObject



146
147
148
149
# File 'lib/saml/user_attributes/ssoe.rb', line 146

def dslogon_loa_highest
  dslogon_assurance = 
  LOA::DSLOGON_PREMIUM_VERIFIED.include?(dslogon_assurance) ? 3 : nil
end

#edipiObject



120
121
122
# File 'lib/saml/user_attributes/ssoe.rb', line 120

def edipi
  edipi_ids[:edipi]
end

#emailObject



63
64
65
# File 'lib/saml/user_attributes/ssoe.rb', line 63

def email
  safe_attr('va_eauth_emailaddress')
end

#first_nameObject

Personal attributes



27
28
29
# File 'lib/saml/user_attributes/ssoe.rb', line 27

def first_name
  safe_attr('va_eauth_firstname')
end

#genderObject



43
44
45
46
# File 'lib/saml/user_attributes/ssoe.rb', line 43

def gender
  gender = safe_attr('va_eauth_gender')&.chars&.first&.upcase
  %w[M F].include?(gender) ? gender : nil
end

#icnObject



39
40
41
# File 'lib/saml/user_attributes/ssoe.rb', line 39

def icn
  mvi_ids[:icn]
end

#idme_uuidObject



82
83
84
85
86
# File 'lib/saml/user_attributes/ssoe.rb', line 82

def idme_uuid
  return safe_attr('va_eauth_uid') if csid == SAML::User::IDME_CSID

  mvi_ids[:idme_id]
end

#last_nameObject



35
36
37
# File 'lib/saml/user_attributes/ssoe.rb', line 35

def last_name
  safe_attr('va_eauth_lastname')
end

#loaObject



174
175
176
# File 'lib/saml/user_attributes/ssoe.rb', line 174

def loa
  { current: loa_current, highest: [loa_current, loa_highest].max }
end

#loa_currentObject

va_eauth_credentialassurancelevel is supposed to roll up the federated assurance level from credential provider and broker. It is currently returning a value of “2” for DSLogon level 2 so we are interpreting any value greater than 1 as “LOA 3”.



128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/saml/user_attributes/ssoe.rb', line 128

def loa_current
  assurance =
    if csid == 'logingov'
      safe_attr('va_eauth_ial')&.to_i
    else
      safe_attr('va_eauth_credentialassurancelevel')&.to_i
    end
  @loa_current ||= assurance.present? && assurance > 1 ? 3 : 1
rescue NoMethodError, KeyError => e
  @warnings << "loa_current error: #{e.message}"
  @loa_current = 1
end

#loa_highestObject

This is the ID.me highest level of assurance attained



152
153
154
155
156
157
# File 'lib/saml/user_attributes/ssoe.rb', line 152

def loa_highest
  result = mhv_loa_highest
  result ||= dslogon_loa_highest
  result ||= %w[2 classic_loa3].include?(safe_attr('va_eauth_ial_idme_highest')) ? 3 : 1
  result
end

#logingov_uuidObject



88
89
90
91
92
# File 'lib/saml/user_attributes/ssoe.rb', line 88

def logingov_uuid
  return safe_attr('va_eauth_uid') if csid == SAML::User::LOGINGOV_CSID

  mvi_ids[:logingov_id]
end

#mhv_account_typeObject



112
113
114
# File 'lib/saml/user_attributes/ssoe.rb', line 112

def 
  safe_attr('va_eauth_mhvassurance')
end

#mhv_correlation_idObject



108
109
110
# File 'lib/saml/user_attributes/ssoe.rb', line 108

def mhv_correlation_id
  safe_attr('va_eauth_mhvuuid') || mvi_ids[:mhv_ien]
end

#mhv_icnObject



104
105
106
# File 'lib/saml/user_attributes/ssoe.rb', line 104

def mhv_icn
  safe_attr('va_eauth_icn')
end

#mhv_loa_highestObject



141
142
143
144
# File 'lib/saml/user_attributes/ssoe.rb', line 141

def mhv_loa_highest
  mhv_assurance = 
  LOA::MHV_PREMIUM_VERIFIED.include?(mhv_assurance) ? 3 : nil
end

#middle_nameObject



31
32
33
# File 'lib/saml/user_attributes/ssoe.rb', line 31

def middle_name
  safe_attr('va_eauth_middlename')
end

#multifactorObject



159
160
161
162
163
164
165
# File 'lib/saml/user_attributes/ssoe.rb', line 159

def multifactor
  if csid == SAML::User::LOGINGOV_CSID
    safe_attr('va_eauth_aal') == AAL::TWO
  else
    safe_attr('va_eauth_multifactor')&.downcase == 'true'
  end
end

#needs_csp_id_mpi_update?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/saml/user_attributes/ssoe.rb', line 199

def needs_csp_id_mpi_update?
  idme_uuid == safe_attr('va_eauth_uid') && mvi_ids[:idme_id].blank?
end

#sec_idObject



100
101
102
# File 'lib/saml/user_attributes/ssoe.rb', line 100

def sec_id
  safe_attr('va_eauth_secid')
end

#sign_inObject



190
191
192
193
194
195
196
197
# File 'lib/saml/user_attributes/ssoe.rb', line 190

def 
   = if authn_context == INBOUND_AUTHN_CONTEXT
              { service_name: csid }
            else
              SAML::User::AUTHN_CONTEXTS.fetch(authn_context).fetch(:sign_in)
            end
  .merge(account_type:, auth_broker: SAML::URLService::BROKER_CODE)
end

#ssnObject

This attribute may sometimes be TIN, Patient identifier, etc. It is not guaranteed to be a SSN



50
51
52
# File 'lib/saml/user_attributes/ssoe.rb', line 50

def ssn
  safe_attr('va_eauth_pnid')&.delete('-') if safe_attr('va_eauth_pnidtype') == 'SSN'
end

#to_hashObject



203
204
205
# File 'lib/saml/user_attributes/ssoe.rb', line 203

def to_hash
  SERIALIZABLE_ATTRIBUTES.index_with { |k| send(k) }.merge(authn_context:)
end

#transactionidObject



178
179
180
# File 'lib/saml/user_attributes/ssoe.rb', line 178

def transactionid
  safe_attr('va_eauth_transactionid')
end

#uuidObject

Identifiers



68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/saml/user_attributes/ssoe.rb', line 68

def uuid
  return idme_uuid if idme_uuid
  return logingov_uuid if logingov_uuid
  # The sec_id is not a UUID, and while unique this has a potential to cause issues
  # in downstream processes that are expecting a user UUID to be 32 bytes. For
  # example, if there is a log filtering process that was striping out any 32 byte
  # id, an 10 byte sec id would be missed. Using a one way UUID hash, will convert
  # the sec id to a 32 byte unique identifier so that any downstream processes will
  # will treat it exactly the same as a typical 32 byte ID.me identifier.
  return Digest::UUID.uuid_v3('sec-id', sec_id).tr('-', '') if sec_id

  raise Common::Exceptions::InvalidResource, @attributes
end

#validate!Object

Raise any fatal exceptions due to validation issues



208
209
210
211
212
213
214
215
216
217
# File 'lib/saml/user_attributes/ssoe.rb', line 208

def validate!
  multiple_id_validations
  if should_raise_missing_uuid_error
    data = SAML::UserAttributeError::ERRORS[:uuid_missing]
    raise SAML::UserAttributeError.new(code: data[:code],
                                       message: data[:message],
                                       tag: data[:tag],
                                       identifier: mhv_icn)
  end
end

#verified_atObject

only applies to Login.gov IAL2 verification used to automatically upcert IAL1 users without additional service calls



96
97
98
# File 'lib/saml/user_attributes/ssoe.rb', line 96

def verified_at
  safe_attr('va_eauth_verifiedAt')
end

#vha_facility_hashObject



186
187
188
# File 'lib/saml/user_attributes/ssoe.rb', line 186

def vha_facility_hash
  mvi_ids[:vha_facility_hash]
end

#vha_facility_idsObject



182
183
184
# File 'lib/saml/user_attributes/ssoe.rb', line 182

def vha_facility_ids
  mvi_ids[:vha_facility_ids]
end