Class: SAML::PostURLService

Inherits:
URLService show all
Includes:
SentryLogging
Defined in:
lib/saml/post_url_service.rb

Overview

This class is responsible for providing the requests for the various SSO and SLO endpoints. It provides a similar interface to URLService, but for most endpoints it returns an SSO URL and form request parameters for use in a SAML POST submission, instead of a self-contained redirect URL.

See Also:

Constant Summary

Constants inherited from URLService

URLService::BROKER_CODE, URLService::LOGIN_REDIRECT_PARTIAL, URLService::LOGOUT_REDIRECT_PARTIAL, URLService::MOBILE_CLIENT_ID, URLService::SKIP_MHV_ACCOUNT_CREATION_CLIENTS, URLService::TERMS_OF_USE_DECLINED_PATH, URLService::UNIFIED_SIGN_IN_CLIENTS, URLService::VIRTUAL_HOST_MAPPINGS, URLService::WEB_CLIENT_ID

Instance Attribute Summary

Attributes inherited from URLService

#authn_context, #query_params, #saml_settings, #session, #tracker, #type, #user

Instance Method Summary collapse

Methods included from SentryLogging

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

Methods inherited from URLService

#add_query, #base_redirect_url, #build_authn_context, #callback_verify_url, #current_host, #custom_url, #idme_signup_url, #initialize_tracker, #login_url, #logingov_signup_url, #mfa_url, #previous_saml_uuid, #relay_state_params, #save_saml_request_tracker, #slo_url, #url_settings, #verify_url

Constructor Details

#initialize(saml_settings, session: nil, user: nil, params: {}, loa3_context: LOA::IDME_LOA3_VETS) ⇒ PostURLService

Returns a new instance of PostURLService.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/saml/post_url_service.rb', line 17

def initialize(saml_settings, session: nil, user: nil, params: {}, loa3_context: LOA::IDME_LOA3_VETS)
  unless %w[new saml_callback saml_logout_callback ssoe_slo_callback].include?(params[:action])
    raise Common::Exceptions::RoutingError, params[:path]
  end

  if session.present?
    @session = session
    @user = user
    @authn_context = user&.authn_context
  end

  @saml_settings = saml_settings
  @loa3_context = loa3_context

  if (params[:action] == 'saml_callback') && params[:RelayState].present?
    @type = JSON.parse(CGI.unescapeHTML(params[:RelayState]))['type']
  end
  @query_params = {}
  @tracker = initialize_tracker(params)

  Sentry.set_extras(params:)
  Sentry.set_user(session:, user:)
end

Instance Method Details

#build_sso_url(link_authn_context, authn_con_compare = 'exact') ⇒ Object (private)

Builds the urls to trigger various SSO policies: mhv, dslogon, idme, logingov, mfa, or verify flows. link_authn_context is the new proposed authn_context



138
139
140
141
142
143
144
145
146
147
# File 'lib/saml/post_url_service.rb', line 138

def build_sso_url(link_authn_context, authn_con_compare = 'exact')
  new_url_settings = url_settings
  new_url_settings.authn_context = link_authn_context
  new_url_settings.authn_context_comparison = authn_con_compare
  saml_auth_request = OneLogin::RubySaml::Authrequest.new
  save_saml_request_tracker(saml_auth_request.uuid, link_authn_context)
  post_params = saml_auth_request.create_params(new_url_settings, 'RelayState' => relay_state_params)
   = new_url_settings.idp_sso_service_url
  [, post_params]
end

#client_redirect_targetObject (private)



123
124
125
126
127
# File 'lib/saml/post_url_service.rb', line 123

def client_redirect_target
  redirect_target = @tracker.payload_attr(:redirect)
  redirect_target += '&postLogin=true' if @tracker.payload_attr(:post_login) == 'true'
  redirect_target
end

#enabled_tou_clientsObject (private)



149
150
151
# File 'lib/saml/post_url_service.rb', line 149

def enabled_tou_clients
  Settings.terms_of_use.enabled_clients.split(',').collect(&:strip)
end

#login_redirect_url(auth: 'success', code: nil, request_id: nil) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/saml/post_url_service.rb', line 41

def (auth: 'success', code: nil, request_id: nil)
  return client_redirect_target if auth == 'success' && @tracker.payload_attr(:redirect).present?

  # if the original auth request was an inbound ssoe autologin (type custom)
  # and authentication failed, set 'force-needed' so the FE can silently fail
  # authentication and NOT show the user an error page
  auth = 'force-needed' if auth != 'success' && @tracker&.payload_attr(:type) == 'custom'
  set_query_params(auth, code, request_id)

  if Settings.saml_ssoe.relay.present?
    add_query(Settings.saml_ssoe.relay, query_params)
  else
    add_query("#{base_redirect_url}#{LOGIN_REDIRECT_PARTIAL}", query_params)
  end
end

#logout_redirect_urlObject



57
58
59
# File 'lib/saml/post_url_service.rb', line 57

def logout_redirect_url
  "#{base_redirect_url}#{LOGOUT_REDIRECT_PARTIAL}"
end

#retrieve_and_delete_terms_of_use_redirect_user(cache_key) ⇒ Object (private)



97
98
99
100
101
# File 'lib/saml/post_url_service.rb', line 97

def retrieve_and_delete_terms_of_use_redirect_user(cache_key)
  application = Rails.cache.read(cache_key)
  Rails.cache.delete(cache_key)
  application
end

#set_query_params(auth, code, request_id) ⇒ Object (private)



129
130
131
132
133
134
# File 'lib/saml/post_url_service.rb', line 129

def set_query_params(auth, code, request_id)
  @query_params[:type] = type if type
  @query_params[:auth] = auth if auth != 'success'
  @query_params[:code] = code if code
  @query_params[:request_id] = request_id unless request_id.nil?
end

#should_cache_application?(application) ⇒ Boolean (private)

Returns:

  • (Boolean)


93
94
95
# File 'lib/saml/post_url_service.rb', line 93

def should_cache_application?(application)
  enabled_tou_clients.include?(application)
end

#ssoe_slo_urlObject

logout URL for SSOe



75
76
77
# File 'lib/saml/post_url_service.rb', line 75

def ssoe_slo_url
  Settings.saml_ssoe.logout_url
end

#terms_of_use_enabled_applicationObject (private)



81
82
83
84
85
86
87
# File 'lib/saml/post_url_service.rb', line 81

def terms_of_use_enabled_application
  cache_key = "terms_of_use_redirect_user_#{user.uuid}"
  cached_application = retrieve_and_delete_terms_of_use_redirect_user(cache_key)
  current_application = @tracker&.payload_attr(:application)
  write_terms_of_use_redirect_user(cache_key, current_application) if should_cache_application?(current_application)
  terms_of_use_redirect_enabled?(cached_application, current_application)
end

#terms_of_use_redirect_enabled?(cached_application, current_application) ⇒ Boolean (private)

Returns:

  • (Boolean)


89
90
91
# File 'lib/saml/post_url_service.rb', line 89

def terms_of_use_redirect_enabled?(cached_application, current_application)
  enabled_tou_clients.include?(cached_application || current_application || 'vaweb')
end

#terms_of_use_redirect_urlObject



65
66
67
68
69
70
71
72
# File 'lib/saml/post_url_service.rb', line 65

def terms_of_use_redirect_url
  if terms_of_use_enabled_application
    Rails.logger.info('Redirecting to /terms-of-use', type: :ssoe)
    add_query(terms_of_use_url, { redirect_url:  })
  else
    
  end
end

#terms_of_use_urlObject (private)



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/saml/post_url_service.rb', line 107

def terms_of_use_url
  current_application = @tracker&.payload_attr(:application)

  base_url = if Settings.review_instance_slug.present?
               "http://#{Settings.review_instance_slug}.review.vetsgov-internal/terms-of-use"
             else
               "#{base_redirect_url}/terms-of-use"
             end

  if current_application.in?(SKIP_MHV_ACCOUNT_CREATION_CLIENTS)
    base_url = add_query(base_url, { skip_mhv_account_creation: true })
  end

  base_url
end

#tou_declined_logout_redirect_urlObject



61
62
63
# File 'lib/saml/post_url_service.rb', line 61

def tou_declined_logout_redirect_url
  "#{base_redirect_url}#{TERMS_OF_USE_DECLINED_PATH}"
end

#write_terms_of_use_redirect_user(cache_key, application) ⇒ Object (private)



103
104
105
# File 'lib/saml/post_url_service.rb', line 103

def write_terms_of_use_redirect_user(cache_key, application)
  Rails.cache.write(cache_key, application, expires_in: 5.minutes)
end