diff --git a/app/controllers/saml_idp_controller.rb b/app/controllers/saml_idp_controller.rb index 9a9de7d9068..f36b53c29b4 100644 --- a/app/controllers/saml_idp_controller.rb +++ b/app/controllers/saml_idp_controller.rb @@ -131,6 +131,7 @@ def capture_analytics requested_ial: requested_ial, request_signed: saml_request.signed?, matching_cert_serial: saml_request.service_provider.matching_cert&.serial&.to_s, + requested_nameid_format: saml_request.name_id_format, ) analytics.saml_auth(**analytics_payload) end diff --git a/app/services/analytics_events.rb b/app/services/analytics_events.rb index c1cbf685945..19333a38638 100644 --- a/app/services/analytics_events.rb +++ b/app/services/analytics_events.rb @@ -4920,7 +4920,8 @@ def rules_of_use_visit # @param [Boolean] success Whether form validation was successful # @param [Hash] errors Errors resulting from form validation # @param [Hash] error_details Details for errors that occurred in unsuccessful submission - # @param [String] nameid_format + # @param [String] nameid_format The NameID format sent in the response + # @param [String] requested_nameid_format The NameID format requested # @param [Array] authn_context # @param [String] authn_context_comparison # @param [String] service_provider @@ -4934,6 +4935,7 @@ def saml_auth( success:, errors:, nameid_format:, + requested_nameid_format:, authn_context:, authn_context_comparison:, service_provider:, @@ -4952,6 +4954,7 @@ def saml_auth( errors:, error_details:, nameid_format:, + requested_nameid_format:, authn_context:, authn_context_comparison:, service_provider:, diff --git a/spec/controllers/saml_idp_controller_spec.rb b/spec/controllers/saml_idp_controller_spec.rb index 041ba1157ee..f7eafdfe021 100644 --- a/spec/controllers/saml_idp_controller_spec.rb +++ b/spec/controllers/saml_idp_controller_spec.rb @@ -788,21 +788,24 @@ def name_id_version(format_urn) user_fully_authenticated: true, }) expect(@analytics).to receive(:track_event). - with('SAML Auth', { - success: true, - errors: {}, - error_details: nil, - nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, - authn_context: [Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF], - authn_context_comparison: 'exact', - requested_ial: Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF, - service_provider: sp1_issuer, - endpoint: "/api/saml/auth#{path_year}", - idv: false, - finish_profile: false, - request_signed: true, - matching_cert_serial: saml_test_sp_cert_serial, - }) + with( + 'SAML Auth', + hash_including( + success: true, + errors: {}, + error_details: nil, + nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, + authn_context: [Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF], + authn_context_comparison: 'exact', + requested_ial: Saml::Idp::Constants::IAL2_AUTHN_CONTEXT_CLASSREF, + service_provider: sp1_issuer, + endpoint: "/api/saml/auth#{path_year}", + idv: false, + finish_profile: false, + request_signed: true, + matching_cert_serial: saml_test_sp_cert_serial, + ), + ) expect(@analytics).to receive(:track_event).with( 'SP redirect initiated', ial: Idp::Constants::IAL2, @@ -938,21 +941,24 @@ def name_id_version(format_urn) user_fully_authenticated: true, }) expect(@analytics).to receive(:track_event). - with('SAML Auth', { - success: true, - errors: {}, - error_details: nil, - nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, - authn_context: ['http://idmanagement.gov/ns/assurance/ial/1'], - authn_context_comparison: 'minimum', - requested_ial: 'ialmax', - service_provider: sp1_issuer, - endpoint: "/api/saml/auth#{path_year}", - idv: false, - finish_profile: false, - request_signed: true, - matching_cert_serial: saml_test_sp_cert_serial, - }) + with( + 'SAML Auth', + hash_including( + success: true, + errors: {}, + error_details: nil, + nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, + authn_context: ['http://idmanagement.gov/ns/assurance/ial/1'], + authn_context_comparison: 'minimum', + requested_ial: 'ialmax', + service_provider: sp1_issuer, + endpoint: "/api/saml/auth#{path_year}", + idv: false, + finish_profile: false, + request_signed: true, + matching_cert_serial: saml_test_sp_cert_serial, + ), + ) expect(@analytics).to receive(:track_event).with( 'SP redirect initiated', ial: 0, @@ -1009,7 +1015,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end end @@ -1234,7 +1240,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end end @@ -1283,7 +1289,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end end @@ -1488,7 +1494,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end end @@ -1566,7 +1572,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end it 'returns a 400' do @@ -1615,7 +1621,7 @@ def name_id_version(format_urn) } expect(@analytics).to have_received(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) end end @@ -1638,7 +1644,7 @@ def name_id_version(format_urn) ) end - shared_examples_for 'sends the UUID' do + shared_examples_for 'sends the UUID' do |requested_nameid_format| it 'sends the UUID' do generate_saml_response(user, auth_settings) @@ -1649,13 +1655,15 @@ def name_id_version(format_urn) expect(@analytics).to have_logged_event( 'SAML Auth', hash_including( - { nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, success: true }, + nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT, + requested_nameid_format: requested_nameid_format, + success: true, ), ) end end - shared_examples_for 'sends the email' do + shared_examples_for 'sends the email' do |requested_nameid_format| it 'sends the email' do generate_saml_response(user, auth_settings) @@ -1666,13 +1674,15 @@ def name_id_version(format_urn) expect(@analytics).to have_logged_event( 'SAML Auth', hash_including( - { nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_EMAIL, success: true }, + nameid_format: Saml::Idp::Constants::NAME_ID_FORMAT_EMAIL, + requested_nameid_format: requested_nameid_format, + success: true, ), ) end end - shared_examples_for 'returns an unauthorized nameid error' do |invalid_format| + shared_examples_for 'returns an unauthorized nameid error' do |requested_nameid_format| it 'returns an error' do generate_saml_response(user, auth_settings) @@ -1682,7 +1692,9 @@ def name_id_version(format_urn) expect(@analytics).to have_logged_event( 'SAML Auth', hash_including( - { nameid_format: invalid_format, success: false }, + nameid_format: requested_nameid_format, + requested_nameid_format: requested_nameid_format, + success: false, ), ) end @@ -1694,7 +1706,7 @@ def name_id_version(format_urn) context 'when the service provider is not configured with use_legacy_name_id_behavior' do let(:use_legacy_name_id_behavior) { false } - it_behaves_like 'sends the UUID' + it_behaves_like 'sends the UUID', Saml::Idp::Constants::NAME_ID_FORMAT_UNSPECIFIED end context 'when the service provider is configured with use_legacy_name_id_behavior' do let(:use_legacy_name_id_behavior) { true } @@ -1717,18 +1729,18 @@ def name_id_version(format_urn) context 'when the service provider is not configured with use_legacy_name_id_behavior' do let(:use_legacy_name_id_behavior) { false } - it_behaves_like 'sends the UUID' + it_behaves_like 'sends the UUID', nil end context 'when the service provider is configured with use_legacy_name_id_behavior' do let(:use_legacy_name_id_behavior) { true } - it_behaves_like 'sends the UUID' + it_behaves_like 'sends the UUID', nil end end context 'when the NameID format is "persistent"' do let(:name_identifier_format) { Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT } - it_behaves_like 'sends the UUID' + it_behaves_like 'sends the UUID', Saml::Idp::Constants::NAME_ID_FORMAT_PERSISTENT end context 'when the NameID format is "email"' do @@ -1743,7 +1755,7 @@ def name_id_version(format_urn) context 'when the service provider is allowed to use email' do let(:email_allowed) { true } - it_behaves_like 'sends the email' + it_behaves_like 'sends the email', Saml::Idp::Constants::NAME_ID_FORMAT_EMAIL end end @@ -1759,13 +1771,13 @@ def name_id_version(format_urn) context 'when the service provider is not allowed to use email' do let(:email_allowed) { false } - it_behaves_like 'sends the UUID' + it_behaves_like 'sends the UUID', 'urn:oasis:names:tc:SAML:1.1:nameid-format:transient' end context 'when the service provider is allowed to use email' do let(:email_allowed) { true } - it_behaves_like 'sends the email' + it_behaves_like 'sends the email', 'urn:oasis:names:tc:SAML:1.1:nameid-format:transient' end end @@ -2281,7 +2293,7 @@ def name_id_version(format_urn) user_fully_authenticated: true, }) expect(@analytics).to receive(:track_event). - with('SAML Auth', analytics_hash) + with('SAML Auth', hash_including(analytics_hash)) get :auth, params: { path_year: path_year } end @@ -2330,7 +2342,10 @@ def stub_requested_attributes force_authn: false, user_fully_authenticated: true, }) - expect(@analytics).to receive(:track_event).with('SAML Auth', analytics_hash) + expect(@analytics).to receive(:track_event).with( + 'SAML Auth', + hash_including(analytics_hash), + ) expect(@analytics).to receive(:track_event).with( 'SP redirect initiated', ial: 1, @@ -2382,7 +2397,10 @@ def stub_requested_attributes force_authn: false, user_fully_authenticated: true, }) - expect(@analytics).to receive(:track_event).with('SAML Auth', analytics_hash) + expect(@analytics).to receive(:track_event).with( + 'SAML Auth', + hash_including(analytics_hash), + ) expect(@analytics).to receive(:track_event).with( 'SP redirect initiated', ial: 1,