diff --git a/app/Resources/translations/messages.en_GB.xliff b/app/Resources/translations/messages.en_GB.xliff index 7c7c279bb..f404dbc7b 100644 --- a/app/Resources/translations/messages.en_GB.xliff +++ b/app/Resources/translations/messages.en_GB.xliff @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -38,8 +38,8 @@ Nederlands - views/Exception/error.html.twig views/Exception/error404.html.twig + views/Exception/error.html.twig ss.error.button.go_home Back to Home @@ -94,8 +94,8 @@ Please report this error, including the error code, to the helpdesk via help@surfconext.nl - views/Exception/error.html.twig views/Exception/error404.html.twig + views/Exception/error.html.twig ss.error.text.your_art_code The error code is @@ -155,42 +155,42 @@ Code - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_expired Your code has expired. Please request a new code. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_request_limit_reached You have exceeded the limit of three codes; you can no longer request any more codes. Contact your helpdesk or try again later. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_response_incorrect The code you entered does not match. Please try again or request a new code. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.incorrect_challenge_response The code you entered does not match. Please try again or request a new code. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.proof_of_possession_failed The token could not be created due to unknown reasons. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.send_sms_challenge_failed Sending the SMS failed. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.too_many_attempts You have exceeded the limit of ten attempts; you can no longer attempt verification of any more codes. Contact your helpdesk or try again later. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_yubikey_possession.proof_of_possession_failed The token could not be created due to unknown reasons. @@ -204,56 +204,6 @@ ss.registration.email_verification_email_sent.title Verify your e-mail - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.button.initiate - Register biometric device - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.error.authn_failed - Registration of biometric device has failed. Please try again. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.error.proof_of_possession_failed - Registration of your token failed. Please try again. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.text.explanation - Click the button below to register a biometric device. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.title.page - Register a biometric device - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.button.initiate - Register with Tiqr - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.error.authn_failed - Registration with Tiqr has failed. Please try again. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.error.proof_of_possession_failed - Registration of your token failed. Please try again. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.text.explanation - Click the button below to register with Tiqr. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.title.page - Register with Tiqr - Registration/partial/progressBar.html.twig ss.registration.progress_bar.confirm_second_factor @@ -334,26 +284,6 @@ ss.registration.registration_email_sent.title.list_of_ras Location(s) to activate your token - - Resources/views/translations.twig - ss.registration.selector.biometric.alt - Biometric device - - - Resources/views/translations.twig - ss.registration.selector.biometric.button.use - Select - - - Resources/views/translations.twig - ss.registration.selector.biometric.description - Log in using a biometric device. - - - Resources/views/translations.twig - ss.registration.selector.biometric.title - Biometric device - Resources/views/translations.twig ss.registration.selector.sms.alt @@ -375,49 +305,28 @@ For all mobile phones. ss.registration.selector.sms.title SMS - - Resources/views/translations.twig - ss.registration.selector.tiqr.alt - Tiqr - - - Resources/views/translations.twig - ss.registration.selector.tiqr.button.use - Select - - - Resources/views/translations.twig - ss.registration.selector.tiqr.description - Log in with a smartphone app. -For all smartphones with %tiqr_ios_link_start%Apple iOS%tiqr_ios_link_end% or %tiqr_android_link_start%Android%tiqr_android_link_end%. - - - Resources/views/translations.twig - ss.registration.selector.tiqr.title - Tiqr - views/Registration/displaySecondFactorTypes.html.twig ss.registration.selector.title.welcome Select token - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.alt U2F token - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.button.use Select - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.description Sign in with a U2F device. - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.title U2F @@ -443,7 +352,7 @@ For all devices with a USB port. YubiKey - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.sms.alert.no_verification_state Your session has expired. Please request a new code. @@ -493,12 +402,12 @@ For all devices with a USB port. Click 'Send new code' if you did not receive a code. - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.u2f.alert.device_reported_an_error The U2F device reported an error. Try again or visit your IT helpdesk. - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.u2f.alert.error The registration of the U2F device failed. Try again or visit your IT helpdesk. @@ -564,20 +473,20 @@ For all devices with a USB port. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.unverified For the token below the e-mail address must be verified. An e-mail was sent to '%email%'. Please follow the instructions in this e-mail to continue with the registration. Didn't receive an e-mail? Remove the token to try again. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.verified The following token is registered for your account, but not yet activated. An e-mail with your activation code has been sent to the e-mail address %email%. Please follow the instructions in the e-mail on how to proceed. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.vetted The following token is registered for your account. @@ -587,12 +496,12 @@ An e-mail with your activation code has been sent to the e-mail address %email%. Token Overview - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.alert.revocation_failed Token revocation failed - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.alert.revocation_successful Your token has been removed. @@ -607,27 +516,27 @@ An e-mail with your activation code has been sent to the e-mail address %email%. Test - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.biometric Biometric - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.sms SMS - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.tiqr Tiqr - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.u2f U2F - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.yubikey YubiKey @@ -652,27 +561,27 @@ An e-mail with your activation code has been sent to the e-mail address %email%. Remove token - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.biometric Biometric - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.sms SMS - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.tiqr Tiqr - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.u2f U2F - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.yubikey YubiKey @@ -707,22 +616,22 @@ An e-mail with your activation code has been sent to the e-mail address %email%. Help - Resources/views/translations.twig + Resources/views/translations.twig ss.test_second_factor.verification_failed The test with your token failed. - Resources/views/translations.twig + Resources/views/translations.twig ss.test_second_factor.verification_successful The test with your token was successful. You can login with Strong Authentication. - Resources/views/translations.twig + Resources/views/translations.twig ss.verify_yubikey_command.otp.otp_invalid This YubiKey code was invalid. Please try again. - Resources/views/translations.twig + Resources/views/translations.twig ss.verify_yubikey_command.otp.verification_error The verification of the YubiKey code failed due to unknown reasons. Please try again. diff --git a/app/Resources/translations/messages.nl_NL.xliff b/app/Resources/translations/messages.nl_NL.xliff index 9351ce301..adf1607a5 100644 --- a/app/Resources/translations/messages.nl_NL.xliff +++ b/app/Resources/translations/messages.nl_NL.xliff @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -38,8 +38,8 @@ Nederlands - views/Exception/error.html.twig views/Exception/error404.html.twig + views/Exception/error.html.twig ss.error.button.go_home Terug naar Home @@ -94,8 +94,8 @@ Meld deze error code aan de helpdesk via support@surfconext.nl - views/Exception/error.html.twig views/Exception/error404.html.twig + views/Exception/error.html.twig ss.error.text.your_art_code De fout code is @@ -155,42 +155,42 @@ Code - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_expired Deze code is verlopen. Vraag een nieuwe code aan. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_request_limit_reached Je hebt de limiet van drie codes bereikt; je kunt geen codes meer aanvragen. Neem contact op met de helpdesk van je instelling of probeer het later nog eens. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.challenge_response_incorrect De code die je ingevoerd hebt komt niet overeen met de code die je hebt ontvangen. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.incorrect_challenge_response De ingevoerde code is onjuist. Probeer het nog eens, of vraag een nieuwe code op. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.proof_of_possession_failed Het token kon wegens een onbekende reden niet aangemaakt worden. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.send_sms_challenge_failed Het versturen van de code per SMS is mislukt. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_phone_possession.too_many_attempts U heeft de limiet van tien pogingen bereikt; u kunt geen codes meer verifiëren. Neem contact op met uw helpdesk of probeer het later nog eens. - Resources/views/translations.twig + Resources/views/translations.twig ss.prove_yubikey_possession.proof_of_possession_failed Het token kon wegens een onbekende reden niet aangemaakt worden. @@ -204,56 +204,6 @@ ss.registration.email_verification_email_sent.title Bevestig je e-mailadres - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.button.initiate - Registreer biometrisch apparaat - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.error.authn_failed - Registratie biometrisch apparaat is mislukt. Probeer het nogmaals. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.error.proof_of_possession_failed - De registratie van uw token is mislukt. Probeer het nogmaals. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.text.explanation - Klik op de knop hieronder om je biometrisch apparaat te registreren. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.biometric.title.page - Registratie biometrisch apparaat - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.button.initiate - Registreren bij Tiqr - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.error.authn_failed - Registratie bij Tiqr is mislukt. Probeer het nogmaals. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.error.proof_of_possession_failed - De registratie van uw token is mislukt. Probeer het nogmaals. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.text.explanation - Klik op de knop hieronder om je bij Tiqr te registreren. - - - Resources/views/translations.twig - ss.registration.gssf.initiate.tiqr.title.page - Registreren bij Tiqr - Registration/partial/progressBar.html.twig ss.registration.progress_bar.confirm_second_factor @@ -334,26 +284,6 @@ ss.registration.registration_email_sent.title.list_of_ras Locatie(s) om je token te activeren - - Resources/views/translations.twig - ss.registration.selector.biometric.alt - Biometrisch apparaat - - - Resources/views/translations.twig - ss.registration.selector.biometric.button.use - Selecteer - - - Resources/views/translations.twig - ss.registration.selector.biometric.description - Log in met een biometrisch apparaat. - - - Resources/views/translations.twig - ss.registration.selector.biometric.title - Biometrisch apparaat - Resources/views/translations.twig ss.registration.selector.sms.alt @@ -375,49 +305,28 @@ Geschikt voor alle mobiele telefoons. ss.registration.selector.sms.title SMS - - Resources/views/translations.twig - ss.registration.selector.tiqr.alt - Tiqr - - - Resources/views/translations.twig - ss.registration.selector.tiqr.button.use - Selecteer - - - Resources/views/translations.twig - ss.registration.selector.tiqr.description - Log in met een app op je smartphone. -Geschikt voor smartphones met %tiqr_ios_link_start%Apple iOS%tiqr_ios_link_end% of %tiqr_android_link_start%Android%tiqr_android_link_end%. - - - Resources/views/translations.twig - ss.registration.selector.tiqr.title - Tiqr - views/Registration/displaySecondFactorTypes.html.twig ss.registration.selector.title.welcome Selecteer token - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.alt U2F-token - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.button.use Selecteer - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.description Log in met een U2F-apparaat. - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.selector.u2f.title U2F @@ -443,7 +352,7 @@ Geschikt voor alle devices met een USB-poort. YubiKey - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.sms.alert.no_verification_state Uw sessie is verlopen. Vraag een nieuwe code aan. @@ -493,12 +402,12 @@ Geschikt voor alle devices met een USB-poort. Geen code ontvangen? Klik dan op 'Stuur een nieuwe code' - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.u2f.alert.device_reported_an_error Het U2F-apparaat heeft een foutmelding gerapporteerd. Probeer het opnieuw of neem contact op met de IT-helpdesk. - Resources/views/translations.twig + Resources/views/translations.twig ss.registration.u2f.alert.error De registratie van het U2F-apparaat is mislukt. Probeer het opnieuw of neem contact op met de IT-helpdesk. @@ -563,19 +472,19 @@ Geschikt voor alle devices met een USB-poort. Er zijn geen tokens geregistreerd voor jouw account. Klik op 'Registreer token' om een nieuw token te registreren. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.unverified Voor het onderstaande token moet het e-mailadres nog bevestigd worden. Er is een e-mail verstuurd naar '%email%'. Volg de instructies in deze e-mail om verder te gaan met de registratie. Geen e-mail ontvangen? Verwijder het token om het opnieuw te proberen. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.verified Het volgende token is geregistreerd voor jouw account, maar nog niet geactiveerd. Er is een e-mail met activatiecode gestuurd naar het e-mailadres %email%. Volg de instructies uit de e-mail om je token te activeren. - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.list.text.vetted Het volgende token is geregistreerd voor jouw account. @@ -585,12 +494,12 @@ Er is een e-mail met activatiecode gestuurd naar het e-mailadres %email%. Volg d Overzicht tokens - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.alert.revocation_failed Token intrekken is mislukt - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.alert.revocation_successful Je token is verwijderd. @@ -605,27 +514,27 @@ Er is een e-mail met activatiecode gestuurd naar het e-mailadres %email%. Volg d Testen - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.biometric Biometrie - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.sms SMS - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.tiqr Tiqr - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.u2f U2F - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.revoke.second_factor_type.yubikey YubiKey @@ -650,27 +559,27 @@ Er is een e-mail met activatiecode gestuurd naar het e-mailadres %email%. Volg d Verwijder token - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.biometric Biometrie - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.sms SMS - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.tiqr Tiqr - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.u2f U2F - Resources/views/translations.twig + Resources/views/translations.twig ss.second_factor.type.yubikey YubiKey @@ -705,22 +614,22 @@ Er is een e-mail met activatiecode gestuurd naar het e-mailadres %email%. Volg d Help - Resources/views/translations.twig + Resources/views/translations.twig ss.test_second_factor.verification_failed De test met je token is mislukt. - Resources/views/translations.twig + Resources/views/translations.twig ss.test_second_factor.verification_successful De test met je token is geslaagd. Je kunt inloggen met Sterke Authenticatie. - Resources/views/translations.twig + Resources/views/translations.twig ss.verify_yubikey_command.otp.otp_invalid Deze YubiKey code was ongeldig. Probeer het nog eens. - Resources/views/translations.twig + Resources/views/translations.twig ss.verify_yubikey_command.otp.verification_error Het verifiëren van de YubiKey-code is wegens een onbekende reden niet gelukt. Probeer het opnieuw. diff --git a/app/Resources/translations/validators.en_GB.xliff b/app/Resources/translations/validators.en_GB.xliff index 1b382b1bf..ef384bcd5 100644 --- a/app/Resources/translations/validators.en_GB.xliff +++ b/app/Resources/translations/validators.en_GB.xliff @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -78,6 +78,10 @@ Sign request version must be a string Sign request version must be a string + + middleware_client.dto.configuration.allowed_second_factors.must_be_array + middleware_client.dto.configuration.allowed_second_factors.must_be_array + middleware_client.dto.configuration.show_raa_contact_information.must_be_boolean middleware_client.dto.configuration.show_raa_contact_information.must_be_boolean diff --git a/app/Resources/translations/validators.nl_NL.xliff b/app/Resources/translations/validators.nl_NL.xliff index 7b67d9370..37948e03b 100644 --- a/app/Resources/translations/validators.nl_NL.xliff +++ b/app/Resources/translations/validators.nl_NL.xliff @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -78,6 +78,10 @@ Sign request version must be a string Sign request version must be a string + + middleware_client.dto.configuration.allowed_second_factors.must_be_array + middleware_client.dto.configuration.allowed_second_factors.must_be_array + middleware_client.dto.configuration.show_raa_contact_information.must_be_boolean middleware_client.dto.configuration.show_raa_contact_information.must_be_boolean diff --git a/app/config/config.yml b/app/config/config.yml index 2115bc6b7..9de1a7887 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -162,6 +162,7 @@ jms_translation: surfnet_stepup_self_service_self_service: enabled_second_factors: %enabled_second_factors% + enabled_generic_second_factors: %enabled_generic_second_factors% second_factor_test_identity_provider: entity_id: '%second_factor_test_idp_entity_id%' sso_url: '%second_factor_test_idp_sso_url%' diff --git a/app/config/parameters.yml.dist b/app/config/parameters.yml.dist index db9e9f8ff..9e5157706 100644 --- a/app/config/parameters.yml.dist +++ b/app/config/parameters.yml.dist @@ -48,6 +48,11 @@ parameters: enabled_second_factors: - sms - yubikey + enabled_generic_second_factors: + biometric: + loa: 3 + tiqr: + loa: 3 u2f_app_id: https://gateway.tld/u2f/app-id diff --git a/app/config/samlstepupproviders.yml b/app/config/samlstepupproviders.yml index 8695117aa..8ccec7ab8 100644 --- a/app/config/samlstepupproviders.yml +++ b/app/config/samlstepupproviders.yml @@ -18,6 +18,18 @@ surfnet_stepup_self_service_saml_stepup_provider: entity_id: %gssp_tiqr_remote_entity_id% sso_url: %gssp_tiqr_remote_sso_url% certificate: %gssp_tiqr_remote_certificate% + view_config: + loa: %gssp_tiqr_loa% + logo: %gssp_tiqr_logo% + alt: %gssp_tiqr_alt% + title: %gssp_tiqr_title% + description: %gssp_tiqr_description% + button_use: %gssp_tiqr_button_use% + initiate_title: %gssp_tiqr_initiate_title% + initiate_button: %gssp_tiqr_initiate_button% + explanation: %gssp_tiqr_initiate_title% + authn_failed: %gssp_tiqr_authn_failed% + pop_failed: %gssp_tiqr_pop_failed% biometric: hosted: service_provider: @@ -30,3 +42,15 @@ surfnet_stepup_self_service_saml_stepup_provider: entity_id: %gssp_biometric_remote_entity_id% sso_url: %gssp_biometric_remote_sso_url% certificate: %gssp_biometric_remote_certificate% + view_config: + loa: %gssp_biometric_loa% + logo: %gssp_biometric_logo% + alt: %gssp_biometric_alt% + title: %gssp_biometric_title% + description: %gssp_biometric_description% + button_use: %gssp_biometric_button_use% + initiate_title: %gssp_biometric_initiate_title% + initiate_button: %gssp_biometric_initiate_button% + explanation: %gssp_biometric_initiate_title% + authn_failed: %gssp_biometric_authn_failed% + pop_failed: %gssp_biometric_pop_failed% diff --git a/app/config/samlstepupproviders_parameters.yml.dist b/app/config/samlstepupproviders_parameters.yml.dist index fc22ba12b..4a461231a 100644 --- a/app/config/samlstepupproviders_parameters.yml.dist +++ b/app/config/samlstepupproviders_parameters.yml.dist @@ -7,11 +7,69 @@ parameters: gssp_tiqr_remote_entity_id: 'https://actual-gssp.entity-id.tld' gssp_tiqr_remote_sso_url: 'https://actual-gssp.entity-id.tld/single-sign-on/url' gssp_tiqr_remote_certificate: 'The contents of the certificate published by the gssp' + gssp_tiqr_loa: 3 + gssp_tiqr_logo: '/path/to/tiqr/tiqr.png' + gssp_tiqr_alt: + en_GB: 'Tiqr' + nl_NL: 'Tiqr' + gssp_tiqr_title: + en_GB: 'Tiqr' + nl_NL: 'Tiqr' + gssp_tiqr_description: + en_GB: 'Log in with a smartphone app. For all smartphones with %%tiqr_ios_link_start%%Apple iOS%%tiqr_ios_link_end%% or %%tiqr_android_link_start%%Android%%tiqr_android_link_end%%.' + nl_NL: 'Log in met een app op je smartphone. Geschikt voor smartphones met %%tiqr_ios_link_start%%Apple iOS%%tiqr_ios_link_end%% of %%tiqr_android_link_start%%Android%%tiqr_android_link_end%%.' + gssp_tiqr_button_use: + en_GB: 'Select' + nl_NL: 'Selecteer' + gssp_tiqr_initiate_title: + en_GB: 'Register with Tiqr' + nl_NL: 'Registreren bij Tiqr' + gssp_tiqr_initiate_button: + en_GB: 'Register with Tiqr' + nl_NL: 'Registreren bij Tiqr' + gssp_tiqr_explanation: + en_GB: 'Click the button below to register with Tiqr.' + nl_NL: 'Klik op de knop hieronder om je bij Tiqr te registreren.' + gssp_tiqr_authn_failed: + en_GB: 'Registration with Tiqr has failed. Please try again.' + nl_NL: 'Registratie bij Tiqr is mislukt. Probeer het nogmaals.' + gssp_tiqr_pop_failed: + en_GB: 'Registration of your token failed. Please try again.' + nl_NL: 'De registratie van uw token is mislukt. Probeer het nogmaals.' - gssp_biometric_sp_publickey: '/full/path/to/the/gateway-as-sp/public-key-file.cer' - gssp_biometric_sp_privatekey: '/full/path/to/the/gateway-as-sp/private-key-file.pem' - gssp_biometric_metadata_publickey: '/full/path/to/the/gateway-metadata/public-key-file.cer' - gssp_biometric_metadata_privatekey: '/full/path/to/the/gateway-as-sp/private-key-file.pem' + gssp_biometric_sp_publickey: /full/path/to/the/gateway-as-sp/public-key-file.cer + gssp_biometric_sp_privatekey: /full/path/to/the/gateway-as-sp/private-key-file.pem + gssp_biometric_metadata_publickey: /full/path/to/the/gateway-metadata/public-key-file.cer + gssp_biometric_metadata_privatekey: /full/path/to/the/gateway-as-sp/private-key-file.pem gssp_biometric_remote_entity_id: 'https://actual-gssp.entity-id.tld' gssp_biometric_remote_sso_url: 'https://actual-gssp.entity-id.tld/single-sign-on/url' gssp_biometric_remote_certificate: 'The contents of the certificate published by the gssp' + gssp_biometric_loa: 3 + gssp_biometric_logo: '/images/second-factor/biometric.png' + gssp_biometric_alt: + en_GB: 'Biometric device' + nl_NL: 'Biometrisch apparaat' + gssp_biometric_title: + en_GB: 'Biometric device' + nl_NL: 'Biometrisch apparaat' + gssp_biometric_description: + en_GB: 'Log in using a biometric device.' + nl_NL: 'Log in met een biometrisch apparaat.' + gssp_biometric_button_use: + en_GB: 'Select' + nl_NL: 'Selecteer' + gssp_biometric_initiate_title: + en_GB: 'Register a biometric device' + nl_NL: 'Registratie biometrisch apparaat' + gssp_biometric_initiate_button: + en_GB: 'Register biometric device' + nl_NL: 'Registreer biometrisch apparaat' + gssp_biometric_explanation: + en_GB: 'Click the button below to register a biometric device.' + nl_NL: 'Klik op de knop hieronder om je biometrisch apparaat te registreren.' + gssp_biometric_authn_failed: + en_GB: 'Registration of biometric device has failed. Please try again.' + nl_NL: 'Registratie biometrisch apparaat is mislukt. Probeer het nogmaals.' + gssp_biometric_pop_failed: + en_GB: 'Registration of your token failed. Please try again.' + nl_NL: 'De registratie van uw token is mislukt. Probeer het nogmaals.' \ No newline at end of file diff --git a/app/phpunit.xml.dist b/app/phpunit.xml.dist index 36aaaaddf..7b9687a3e 100644 --- a/app/phpunit.xml.dist +++ b/app/phpunit.xml.dist @@ -10,6 +10,7 @@ ../src/Surfnet/StepupSelfService/SelfServiceBundle/Tests + ../src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Tests diff --git a/composer.json b/composer.json index 7193663a9..5eaac7fdd 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ "surfnet/stepup-middleware-client-bundle": "^2.0", "guzzlehttp/guzzle": "^6", "surfnet/stepup-saml-bundle": "^2.5", - "surfnet/stepup-bundle": "^1.7", + "surfnet/stepup-bundle": "^2.0", "surfnet/stepup-u2f-bundle": "dev-develop", "mopa/composer-bridge": "~1.5" }, diff --git a/composer.lock b/composer.lock index dbf307fbc..9d19b26ce 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "09e257cfcd2d3317b35d78a281e76646", + "content-hash": "39fb57b9627d081ab1bb14b546d22842", "packages": [ { "name": "beberlei/assert", @@ -1963,16 +1963,16 @@ }, { "name": "surfnet/stepup-bundle", - "version": "1.7.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/OpenConext/Stepup-bundle.git", - "reference": "084b1e11781ca3f526e32a486f75a7e6a953e5fc" + "reference": "0766c91a6b391739d9fe4693f684ef1332342df4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/OpenConext/Stepup-bundle/zipball/084b1e11781ca3f526e32a486f75a7e6a953e5fc", - "reference": "084b1e11781ca3f526e32a486f75a7e6a953e5fc", + "url": "https://api.github.com/repos/OpenConext/Stepup-bundle/zipball/0766c91a6b391739d9fe4693f684ef1332342df4", + "reference": "0766c91a6b391739d9fe4693f684ef1332342df4", "shasum": "" }, "require": { @@ -2016,7 +2016,7 @@ "suaas", "surfnet" ], - "time": "2017-03-07T13:44:04+00:00" + "time": "2017-06-14T13:03:51+00:00" }, { "name": "surfnet/stepup-middleware-client-bundle", @@ -2992,12 +2992,12 @@ "version": "0.9.5", "source": { "type": "git", - "url": "https://github.com/padraic/mockery.git", + "url": "https://github.com/mockery/mockery.git", "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", + "url": "https://api.github.com/repos/mockery/mockery/zipball/4db079511a283e5aba1b3c2fb19037c645e70fc2", "reference": "4db079511a283e5aba1b3c2fb19037c645e70fc2", "shasum": "" }, diff --git a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/Configuration.php b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/Configuration.php index 2332c5a7c..36140fc12 100644 --- a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/Configuration.php +++ b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/Configuration.php @@ -68,6 +68,7 @@ private function addRoutesSection(ArrayNodeDefinition $rootNode) /** * @param ArrayNodeDefinition $rootNode + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function addProvidersSection(ArrayNodeDefinition $rootNode) { @@ -129,6 +130,126 @@ private function addProvidersSection(ArrayNodeDefinition $rootNode) ->end() ->end() ->end() + ->arrayNode('view_config') + ->children() + ->scalarNode('loa') + ->isRequired() + ->info('The loa level (for now 1-3 are supported)') + ->end() + ->scalarNode('logo') + ->isRequired() + ->info('The absolute path to the logo of the gssp') + ->end() + ->arrayNode('alt') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English alt text translation') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch alt text translation') + ->end() + ->end() + ->end() + ->arrayNode('title') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English title of the gssp') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch title of the gssp') + ->end() + ->end() + ->end() + ->arrayNode('description') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English description of the gssp') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch description of the gssp') + ->end() + ->end() + ->end() + ->arrayNode('button_use') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English text shown on the use button') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch text shown on the use button') + ->end() + ->end() + ->end() + ->arrayNode('initiate_title') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English initiate title text') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch initiate title text') + ->end() + ->end() + ->end() + ->arrayNode('initiate_button') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English initiate button text') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch initiate button text') + ->end() + ->end() + ->end() + ->arrayNode('explanation') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English explanation for step 2') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch explanation for step 2') + ->end() + ->end() + ->end() + ->arrayNode('authn_failed') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English text shown when authn request failed') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch text shown when authn request failed') + ->end() + ->end() + ->end() + ->arrayNode('pop_failed') + ->children() + ->scalarNode('en_GB') + ->isRequired() + ->info('English text shown on failed proof of posession') + ->end() + ->scalarNode('nl_NL') + ->isRequired() + ->info('Dutch text shown on failed proof of posession') + ->end() + ->end() + ->end() + ->end() + ->end() ->end(); } } diff --git a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/SurfnetStepupSelfServiceSamlStepupProviderExtension.php b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/SurfnetStepupSelfServiceSamlStepupProviderExtension.php index 2dddf831d..570ff34d9 100644 --- a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/SurfnetStepupSelfServiceSamlStepupProviderExtension.php +++ b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/DependencyInjection/SurfnetStepupSelfServiceSamlStepupProviderExtension.php @@ -35,7 +35,6 @@ public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.yml'); @@ -56,6 +55,7 @@ private function loadProviderConfiguration( array $routes, ContainerBuilder $container ) { + if ($container->has('gssp.provider.' . $provider)) { throw new InvalidConfigurationException(sprintf('Cannot create the same provider "%s" twice', $provider)); } @@ -80,6 +80,24 @@ private function loadProviderConfiguration( $providerDefinition->setPublic(false); $container->setDefinition('gssp.provider.' . $provider, $providerDefinition); + $viewConfigDefinition = new Definition('Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig', [ + new Reference('request'), + $configuration['view_config']['loa'], + $configuration['view_config']['logo'], + $configuration['view_config']['alt'], + $configuration['view_config']['title'], + $configuration['view_config']['description'], + $configuration['view_config']['button_use'], + $configuration['view_config']['initiate_title'], + $configuration['view_config']['initiate_button'], + $configuration['view_config']['explanation'], + $configuration['view_config']['authn_failed'], + $configuration['view_config']['pop_failed'], + ]); + $viewConfigDefinition->setScope('request'); + + $container->setDefinition('gssp.view_config.' . $provider, $viewConfigDefinition); + $container ->getDefinition('gssp.provider_repository') ->addMethodCall('addProvider', [new Reference('gssp.provider.' . $provider)]); diff --git a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Provider/ViewConfig.php b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Provider/ViewConfig.php new file mode 100644 index 000000000..0f4cccde2 --- /dev/null +++ b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Provider/ViewConfig.php @@ -0,0 +1,241 @@ +loa = $loa; + $this->logo = $logo; + $this->alt = $alt; + $this->title = $title; + $this->description = $description; + $this->buttonUse = $buttonUse; + $this->initiateTitle = $initiateTitle; + $this->initiateButton = $initiateButton; + $this->explanation = $explanation; + $this->authnFailed = $authnFailed; + $this->popFailed = $popFailed; + $this->request = $request; + } + + /** + * @return string + */ + public function getLogo() + { + return $this->logo; + } + + /** + * @return string + */ + public function getLoa() + { + return $this->loa; + } + + /** + * @return string + */ + public function getTitle() + { + return $this->getTranslation($this->title); + } + + /** + * @return string + */ + public function getAlt() + { + return $this->getTranslation($this->alt); + } + + /** + * @return string + */ + public function getDescription() + { + return $this->getTranslation($this->description); + } + + /** + * @return string + */ + public function getButtonUse() + { + return $this->getTranslation($this->buttonUse); + } + + /** + * @return string + */ + public function getInitiateTitle() + { + return $this->getTranslation($this->initiateTitle); + } + + /** + * @return string + */ + public function getInitiateButton() + { + return $this->getTranslation($this->initiateButton); + } + + /** + * @return string + */ + public function getExplanation() + { + return $this->getTranslation($this->explanation); + } + + /** + * @return string + */ + public function getAuthnFailed() + { + return $this->getTranslation($this->authnFailed); + } + + /** + * @return string + */ + public function getPopFailed() + { + return $this->getTranslation($this->popFailed); + } + + /** + * @param array $translations + * @return mixed + * @throws LogicException + */ + private function getTranslation(array $translations) + { + $currentLocale = $this->request->getLocale(); + if (is_null($currentLocale)) { + throw new LogicException('The current language is not set'); + } + if (isset($translations[$currentLocale])) { + return $translations[$currentLocale]; + } + throw new LogicException( + sprintf( + 'The requested translation is not available in this language: %s. Available languages: %s', + $currentLocale, + implode(', ', array_keys($translations)) + ) + ); + } +} diff --git a/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Tests/Provider/ViewConfigTest.php b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Tests/Provider/ViewConfigTest.php new file mode 100644 index 000000000..c8adfd2cf --- /dev/null +++ b/src/Surfnet/StepupSelfService/SamlStepupProviderBundle/Tests/Provider/ViewConfigTest.php @@ -0,0 +1,123 @@ +buildViewConfig('nl_NL'); + + $this->assertEquals('NL alt', $viewConfig->getAlt()); + $this->assertEquals('NL title', $viewConfig->getTitle()); + $this->assertEquals('NL description', $viewConfig->getDescription()); + $this->assertEquals('NL buttonUse', $viewConfig->getButtonUse()); + $this->assertEquals('NL initiateTitle', $viewConfig->getInitiateTitle()); + $this->assertEquals('NL explanation', $viewConfig->getExplanation()); + $this->assertEquals('NL authnFailed', $viewConfig->getAuthnFailed()); + $this->assertEquals('NL popFailed', $viewConfig->getPopFailed()); + $this->assertEquals('NL initiateButton', $viewConfig->getInitiateButton()); + + $viewConfig = $this->buildViewConfig('en_GB'); + $this->assertEquals('EN alt', $viewConfig->getAlt()); + $this->assertEquals('EN title', $viewConfig->getTitle()); + $this->assertEquals('EN description', $viewConfig->getDescription()); + $this->assertEquals('EN buttonUse', $viewConfig->getButtonUse()); + $this->assertEquals('EN initiateTitle', $viewConfig->getInitiateTitle()); + $this->assertEquals('EN explanation', $viewConfig->getExplanation()); + $this->assertEquals('EN authnFailed', $viewConfig->getAuthnFailed()); + $this->assertEquals('EN popFailed', $viewConfig->getPopFailed()); + $this->assertEquals('EN popFailed', $viewConfig->getPopFailed()); + $this->assertEquals('EN initiateButton', $viewConfig->getInitiateButton()); + } + + /** + * @test + * @group di + * @expectedException \Surfnet\StepupSelfService\SelfServiceBundle\Exception\LogicException + * @expectedExceptionMessage The current language is not set + */ + public function translation_fails_when_no_current_language_set() + { + $viewConfig = $this->buildViewConfig(null); + $viewConfig->getTitle(); + } + + /** + * @test + * @group di + * @expectedException \Surfnet\StepupSelfService\SelfServiceBundle\Exception\LogicException + * @expectedExceptionMessage The requested translation is not available in this language: fr_FR. + * Available languages: en_GB, nl_NL + */ + public function view_config_cannot_serve_french_translations() + { + $viewConfig = $this->buildViewConfig('fr_FR'); + $viewConfig->getTitle(); + } + + /** + * @param string $locale + * @return ViewConfig + */ + private function buildViewConfig($locale = '') + { + $request = m::mock(Request::class); + $request->shouldReceive('getLocale')->andReturn($locale)->byDefault(); + return new ViewConfig( + $request, + 3, + '/path/to/logo.png', + $this->getTranslationsArray('alt'), + $this->getTranslationsArray('title'), + $this->getTranslationsArray('description'), + $this->getTranslationsArray('buttonUse'), + $this->getTranslationsArray('initiateTitle'), + $this->getTranslationsArray('initiateButton'), + $this->getTranslationsArray('explanation'), + $this->getTranslationsArray('authnFailed'), + $this->getTranslationsArray('popFailed') + ); + } + + /** + * @param $string + * @return array + */ + private function getTranslationsArray($string) + { + return [ + 'en_GB' => 'EN ' . $string, + 'nl_NL' => 'NL ' . $string, + ]; + } +} diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/Registration/GssfController.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/Registration/GssfController.php index aa4804baa..ea9e9d69a 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/Registration/GssfController.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/Registration/GssfController.php @@ -22,6 +22,7 @@ use Surfnet\SamlBundle\Http\XMLResponse; use Surfnet\SamlBundle\SAML2\AuthnRequestFactory; use Surfnet\SamlBundle\SAML2\Response\Assertion\InResponseTo; +use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig; use Surfnet\StepupSelfService\SelfServiceBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -40,7 +41,7 @@ public function initiateAction($provider) { $this->assertSecondFactorEnabled($provider); - return $this->renderInitiateForm($provider); + return $this->renderInitiateForm($provider, []); } /** @@ -104,7 +105,10 @@ public function consumeAssertionAction(Request $httpRequest, $provider) sprintf('Could not process received Response, error: "%s"', $exception->getMessage()) ); - return $this->renderInitiateForm($provider->getName(), ['authenticationFailed' => true]); + return $this->renderInitiateForm( + $provider->getName(), + ['authenticationFailed' => true] + ); } $expectedResponseTo = $provider->getStateHandler()->getRequestId(); @@ -116,7 +120,10 @@ public function consumeAssertionAction(Request $httpRequest, $provider) ($expectedResponseTo ? 'expected "' . $expectedResponseTo . '"' : ' no response expected') )); - return $this->renderInitiateForm($provider->getName(), ['authenticationFailed' => true]); + return $this->renderInitiateForm( + $provider->getName(), + ['authenticationFailed' => true] + ); } $this->get('logger')->notice( @@ -142,7 +149,10 @@ public function consumeAssertionAction(Request $httpRequest, $provider) $this->getLogger()->error('Unable to prove GSSF possession'); - return $this->renderInitiateForm($provider->getName(), ['proofOfPossessionFailed' => true]); + return $this->renderInitiateForm( + $provider->getName(), + ['proofOfPossessionFailed' => true] + ); } /** @@ -188,11 +198,30 @@ private function getLogger() return $this->get('logger'); } + /** + * @param string $provider + * @param array $parameters + * @return Response + */ private function renderInitiateForm($provider, array $parameters = []) { - $form = $this->createForm('ss_initiate_gssf', null, ['provider' => $provider]); - $templateParameters = array_merge($parameters, ['form' => $form->createView(), 'provider' => $provider]); - + /** @var ViewConfig $secondFactorConfig */ + $secondFactorConfig = $this->get("gssp.view_config.{$provider}"); + + $form = $this->createForm( + 'ss_initiate_gssf', + null, + [ + 'provider' => $provider, + /** @Ignore from translation message extraction */ + 'label' => $secondFactorConfig->getInitiateButton() + ] + ); + /** @var ViewConfig $secondFactorConfig */ + $templateParameters = array_merge( + $parameters, + ['form' => $form->createView(), 'provider' => $provider, 'secondFactorConfig' => $secondFactorConfig] + ); return $this->render( 'SurfnetStepupSelfServiceSelfServiceBundle:Registration/Gssf:initiate.html.twig', $templateParameters diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/RegistrationController.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/RegistrationController.php index a96e708db..b461cc332 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/RegistrationController.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/RegistrationController.php @@ -19,7 +19,9 @@ namespace Surfnet\StepupSelfService\SelfServiceBundle\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig; use Surfnet\StepupSelfService\SelfServiceBundle\Service\SecondFactorService; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -28,6 +30,7 @@ class RegistrationController extends Controller { /** * @Template + * @return array */ public function displaySecondFactorTypesAction() { @@ -41,10 +44,25 @@ public function displaySecondFactorTypesAction() $institutionConfigurationOptions->allowedSecondFactors ); } + $availableSecondFactors = array_combine($availableSecondFactors, $availableSecondFactors); + $availableGsspSecondFactors = []; + + foreach ($availableSecondFactors as $index => $secondFactor) { + try { + /** @var ViewConfig $secondFactorConfig */ + $secondFactorConfig = $this->get("gssp.view_config.{$secondFactor}"); + $availableGsspSecondFactors[$index] = $secondFactorConfig; + // Remove the gssp second factors from the regular second factors. + unset($availableSecondFactors[$index]); + } catch (ServiceNotFoundException $e) { + continue; + } + } return [ 'commonName' => $this->getIdentity()->commonName, - 'availableSecondFactors' => array_combine($availableSecondFactors, $availableSecondFactors), + 'availableSecondFactors' => $availableSecondFactors, + 'availableGsspSecondFactors' => $availableGsspSecondFactors, 'tiqrAppAndroidUrl' => $this->getParameter('tiqr_app_android_url'), 'tiqrAppIosUrl' => $this->getParameter('tiqr_app_ios_url'), ]; diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/SamlController.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/SamlController.php index d797b27dd..e73be9428 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/SamlController.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Controller/SamlController.php @@ -58,13 +58,13 @@ public function testSecondFactorAction($secondFactorId) $loaResolutionService = $this->get('surfnet_stepup.service.loa_resolution'); $authenticationRequestFactory = $this->get('self_service.test_second_factor_authentication_request_factory'); - + $secondFactorTypeService = $this->get('surfnet_stepup.service.second_factor_type'); $secondFactor = $secondFactorService->findOneVetted($secondFactorId); $secondFactorType = new SecondFactorType($secondFactor->type); $authenticationRequest = $authenticationRequestFactory->createSecondFactorTestRequest( $identity->nameId, - $loaResolutionService->getLoaByLevel($secondFactorType->getLevel()) + $loaResolutionService->getLoaByLevel($secondFactorTypeService->getLevel($secondFactorType)) ); $this->get('session')->set('second_factor_test_request_id', $authenticationRequest->getRequestId()); diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/Configuration.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/Configuration.php index 1180d294e..769a5d8e3 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/Configuration.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/Configuration.php @@ -18,9 +18,6 @@ namespace Surfnet\StepupSelfService\SelfServiceBundle\DependencyInjection; -use Surfnet\StepupBundle\Exception\DomainException; -use Surfnet\StepupBundle\Exception\InvalidArgumentException; -use Surfnet\StepupBundle\Value\SecondFactorType; use Symfony\Component\Config\Definition\Builder\NodeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; @@ -117,22 +114,15 @@ private function appendEnabledSecondFactorTypesConfiguration(NodeBuilder $childN ->arrayNode('enabled_second_factors') ->isRequired() ->prototype('scalar') - ->validate() - ->ifTrue( - function ($type) { - try { - new SecondFactorType($type); - } catch (InvalidArgumentException $e) { - return true; - } catch (DomainException $e) { - return true; - } - } - ) - ->thenInvalid( - 'Enabled second factor type "%s" is not one of the valid types. See SecondFactorType' - ) - ->end() + ->end(); + $childNodes + ->arrayNode('enabled_generic_second_factors') + ->isRequired() + ->prototype('array') + ->children() + ->scalarNode('loa') + ->isRequired() + ->info('The lao level of the Gssf') ->end() ->end(); } diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/SurfnetStepupSelfServiceSelfServiceExtension.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/SurfnetStepupSelfServiceSelfServiceExtension.php index 915e6dd72..706257adf 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/SurfnetStepupSelfServiceSelfServiceExtension.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/DependencyInjection/SurfnetStepupSelfServiceSelfServiceExtension.php @@ -48,8 +48,12 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition('self_service.locale.request_stack_locale_provider') ->replaceArgument(1, $container->getParameter('default_locale')) ->replaceArgument(2, $container->getParameter('locales')); - - $container->setParameter('ss.enabled_second_factors', $config['enabled_second_factors']); + // Enabled second factor types (specific and generic) are merged into 'ss.enabled_second_factors' + $gssfSecondFactors = array_keys($config['enabled_generic_second_factors']); + $container->setParameter( + 'ss.enabled_second_factors', + array_merge($config['enabled_second_factors'], $gssfSecondFactors) + ); $container->setParameter( 'self_service.security.authentication.session.maximum_absolute_lifetime_in_seconds', diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Form/Type/InitiateGssfType.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/Form/Type/InitiateGssfType.php index 501331412..f93dd3055 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Form/Type/InitiateGssfType.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Form/Type/InitiateGssfType.php @@ -18,6 +18,7 @@ namespace Surfnet\StepupSelfService\SelfServiceBundle\Form\Type; +use Surfnet\StepupSelfService\SamlStepupProviderBundle\Provider\ViewConfig; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -38,12 +39,12 @@ public function __construct(RouterInterface $router) public function buildForm(FormBuilderInterface $builder, array $options) { $action = $this->router->generate('ss_registration_gssf_authenticate', ['provider' => $options['provider']]); - + /** @var ViewConfig $secondFactorConfig */ $builder ->add('submit', 'submit', [ 'attr' => ['class' => 'btn btn-primary'], - /** @Ignore string for translation message extrantion */ - 'label' => 'ss.registration.gssf.initiate.' . $options['provider'] . '.button.initiate' + /** @Ignore from translation message extraction */ + 'label' => $options['label'] ]) ->setAction($action); } diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/Gssf/initiate.html.twig b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/Gssf/initiate.html.twig index e8ff389db..41d65443d 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/Gssf/initiate.html.twig +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/Gssf/initiate.html.twig @@ -1,6 +1,6 @@ {% extends "::base.html.twig" %} -{% block page_title %}{{ ('ss.registration.gssf.initiate.' ~ provider ~ '.title.page')|trans }}{% endblock %} +{% block page_title %}{{ secondFactorConfig.getInitiateTitle() }}{% endblock %} {% block page_header %} {{ parent() }} @@ -11,15 +11,15 @@ {% block content %}

{{ block('page_title') }}

-

{{ ('ss.registration.gssf.initiate.' ~ provider ~ '.text.explanation')|trans }}

+

{{ secondFactorConfig.getExplanation() }}


{% if authenticationFailed is defined %} -
{{ ('ss.registration.gssf.initiate.' ~ provider ~ '.error.authn_failed')|trans }}
+
{{ secondFactorConfig.getAuthnFailed() }}
{% endif %} {% if proofOfPossessionFailed is defined %} -
{{ ('ss.registration.gssf.initiate.' ~ provider ~ '.error.proof_of_possession_failed')|trans }}
+
{{ secondFactorConfig.getPopFailed() }}
{% endif %} {{ form(form) }} diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/displaySecondFactorTypes.html.twig b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/displaySecondFactorTypes.html.twig index 8ae1a5584..b83797b6f 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/displaySecondFactorTypes.html.twig +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/displaySecondFactorTypes.html.twig @@ -21,15 +21,6 @@ 'tiqrAppIosUrl': tiqrAppIosUrl, } only %} {% endif %} - {% if availableSecondFactors.tiqr is defined %} - {% include 'SurfnetStepupSelfServiceSelfServiceBundle::Registration/partial/secondFactor.html.twig' with { - 'type': 'tiqr', - 'security': 2, - 'url': path('ss_registration_gssf_initiate', {'provider': 'tiqr'}), - 'tiqrAppAndroidUrl': tiqrAppAndroidUrl, - 'tiqrAppIosUrl': tiqrAppIosUrl, - } only %} - {% endif %} {% if availableSecondFactors.yubikey is defined %} {% include 'SurfnetStepupSelfServiceSelfServiceBundle::Registration/partial/secondFactor.html.twig' with { 'type': 'yubikey', @@ -48,14 +39,16 @@ 'tiqrAppIosUrl': tiqrAppIosUrl, } only %} {% endif %} - {% if availableSecondFactors.biometric is defined %} - {% include 'SurfnetStepupSelfServiceSelfServiceBundle::Registration/partial/secondFactor.html.twig' with { - 'type': 'biometric', - 'security': 3, - 'url': path('ss_registration_gssf_initiate', {'provider': 'biometric'}), - 'tiqrAppAndroidUrl': tiqrAppAndroidUrl, - 'tiqrAppIosUrl': tiqrAppIosUrl, + + {% for type, secondFactor in availableGsspSecondFactors %} + {% include 'SurfnetStepupSelfServiceSelfServiceBundle::Registration/partial/genericSecondFactor.html.twig' with { + 'type': type, + 'security': secondFactor.loa, + 'url': path('ss_registration_gssf_initiate', {'provider': type}), + 'tiqrAppAndroidUrl': tiqrAppAndroidUrl, + 'tiqrAppIosUrl': tiqrAppIosUrl, + 'secondFactor': secondFactor } only %} - {% endif %} + {% endfor %} {% endblock %} diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/partial/genericSecondFactor.html.twig b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/partial/genericSecondFactor.html.twig new file mode 100644 index 000000000..c20d1bcff --- /dev/null +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/Registration/partial/genericSecondFactor.html.twig @@ -0,0 +1,33 @@ +
+
+ {{ secondFactor.getAlt() }} +

{{ secondFactor.getTitle() }}

+

+ {% for i in 1 .. security %} + + {% endfor %} + {% for i in security+1 .. 4 %} + + {% endfor %} +

+
+

+ {{ + (secondFactor.getDescription())|e|replace( + { + '%tiqr_android_link_start%': '', + '%tiqr_android_link_end%': '', + '%tiqr_ios_link_start%': '', + '%tiqr_ios_link_end%': '', + } + )|raw + }} +

+

+ + {{ secondFactor.getButtonUse() }} + +

+
+
diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/translations.twig b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/translations.twig index b97d7680b..e292c34cf 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/translations.twig +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Resources/views/translations.twig @@ -7,18 +7,10 @@ {{ 'ss.registration.selector.yubikey.title'|trans }} {{ 'ss.registration.selector.yubikey.description'|trans }} {{ 'ss.registration.selector.yubikey.button.use'|trans }} -{{ 'ss.registration.selector.tiqr.alt'|trans }} -{{ 'ss.registration.selector.tiqr.title'|trans }} -{{ 'ss.registration.selector.tiqr.description'|trans }} -{{ 'ss.registration.selector.tiqr.button.use'|trans }} {{ 'ss.registration.selector.u2f.alt'|trans }} {{ 'ss.registration.selector.u2f.title'|trans }} {{ 'ss.registration.selector.u2f.description'|trans }} {{ 'ss.registration.selector.u2f.button.use'|trans }} -{{ 'ss.registration.selector.biometric.alt'|trans }} -{{ 'ss.registration.selector.biometric.title'|trans }} -{{ 'ss.registration.selector.biometric.description'|trans }} -{{ 'ss.registration.selector.biometric.button.use'|trans }} {# SmsController form errors #} {{ 'ss.prove_phone_possession.send_sms_challenge_failed'|trans }} @@ -55,18 +47,6 @@ {{ 'ss.second_factor.revoke.alert.revocation_successful'|trans }} {{ 'ss.second_factor.revoke.alert.revocation_failed'|trans }} -{# GssfController #} -{{ ('ss.registration.gssf.initiate.tiqr.title.page')|trans }} -{{ ('ss.registration.gssf.initiate.tiqr.text.explanation')|trans }} -{{ ('ss.registration.gssf.initiate.tiqr.button.initiate')|trans }} -{{ ('ss.registration.gssf.initiate.tiqr.error.authn_failed')|trans }} -{{ ('ss.registration.gssf.initiate.tiqr.error.proof_of_possession_failed')|trans }} -{{ ('ss.registration.gssf.initiate.biometric.title.page')|trans }} -{{ ('ss.registration.gssf.initiate.biometric.text.explanation')|trans }} -{{ ('ss.registration.gssf.initiate.biometric.button.initiate')|trans }} -{{ ('ss.registration.gssf.initiate.biometric.error.authn_failed')|trans }} -{{ ('ss.registration.gssf.initiate.biometric.error.proof_of_possession_failed')|trans }} - {# U2fController #} {{ 'ss.registration.u2f.alert.device_reported_an_error'|trans }} {{ 'ss.registration.u2f.alert.error'|trans }} diff --git a/src/Surfnet/StepupSelfService/SelfServiceBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Surfnet/StepupSelfService/SelfServiceBundle/Tests/DependencyInjection/ConfigurationTest.php index 14239416b..84cc4894a 100644 --- a/src/Surfnet/StepupSelfService/SelfServiceBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Surfnet/StepupSelfService/SelfServiceBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -117,17 +117,6 @@ public function it_allows_two_enabled_second_factors() ); } - /** - * @test - * @group configuration - */ - public function it_rejects_invalid_second_factor_types() - { - $configuration = ['enabled_second_factors' => ['passport']]; - - $this->assertConfigurationIsInvalid([$configuration], 'not one of the valid types'); - } - /** * @test * @group configuration