[[servlet-saml2login-sp-initiated-factory]] = Producing ````s As stated earlier, Spring Security's SAML 2.0 support produces a `` to commence authentication with the asserting party. Spring Security achieves this in part by registering the `Saml2WebSsoAuthenticationRequestFilter` in the filter chain. This filter by default responds to endpoint `+/saml2/authenticate/{registrationId}+`. For example, if you were deployed to `https://rp.example.com` and you gave your registration an ID of `okta`, you could navigate to: `https://rp.example.org/saml2/authenticate/okta` and the result would be a redirect that included a `SAMLRequest` parameter containing the signed, deflated, and encoded ``. [[servlet-saml2login-store-authn-request]] == Changing How the `` Gets Stored `Saml2WebSsoAuthenticationRequestFilter` uses an `Saml2AuthenticationRequestRepository` to persist an `AbstractSaml2AuthenticationRequest` instance before xref:servlet/saml2/login/authentication-requests.adoc#servlet-saml2login-sp-initiated-factory[sending the ``] to the asserting party. Additionally, `Saml2WebSsoAuthenticationFilter` and `Saml2AuthenticationTokenConverter` use an `Saml2AuthenticationRequestRepository` to load any `AbstractSaml2AuthenticationRequest` as part of xref:servlet/saml2/login/authentication.adoc#servlet-saml2login-authenticate-responses[authenticating the ``]. By default, Spring Security uses an `HttpSessionSaml2AuthenticationRequestRepository`, which stores the `AbstractSaml2AuthenticationRequest` in the `HttpSession`. If you have a custom implementation of `Saml2AuthenticationRequestRepository`, you may configure it by exposing it as a `@Bean` as shown in the following example: [tabs] ====== Java:: + [source,java,role="primary"] ---- @Bean Saml2AuthenticationRequestRepository authenticationRequestRepository() { return new CustomSaml2AuthenticationRequestRepository(); } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- @Bean open fun authenticationRequestRepository(): Saml2AuthenticationRequestRepository { return CustomSaml2AuthenticationRequestRepository() } ---- ====== [[servlet-saml2login-sp-initiated-factory-signing]] == Changing How the `` Gets Sent By default, Spring Security signs each `` and send it as a GET to the asserting party. Many asserting parties don't require a signed ``. This can be configured automatically via `RelyingPartyRegistrations`, or you can supply it manually, like so: .Not Requiring Signed AuthnRequests [tabs] ====== Boot:: + [source,yaml,role="primary"] ---- spring: security: saml2: relyingparty: okta: identityprovider: entity-id: ... singlesignon.sign-request: false ---- Java:: + [source,java,role="secondary"] ---- RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta") // ... .assertingPartyDetails(party -> party // ... .wantAuthnRequestsSigned(false) ) .build(); ---- Kotlin:: + [source,java,role="secondary"] ---- var relyingPartyRegistration: RelyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta") // ... .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party // ... .wantAuthnRequestsSigned(false) } .build(); ---- ====== Otherwise, you will need to specify a private key to `RelyingPartyRegistration#signingX509Credentials` so that Spring Security can sign the `` before sending. [[servlet-saml2login-sp-initiated-factory-algorithm]] By default, Spring Security will sign the `` using `rsa-sha256`, though some asserting parties will require a different algorithm, as indicated in their metadata. You can configure the algorithm based on the asserting party's xref:servlet/saml2/login/overview.adoc#servlet-saml2login-relyingpartyregistrationrepository[metadata using `RelyingPartyRegistrations`]. Or, you can provide it manually: [tabs] ====== Java:: + [source,java,role="primary"] ---- String metadataLocation = "classpath:asserting-party-metadata.xml"; RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation) // ... .assertingPartyDetails((party) -> party // ... .signingAlgorithms((sign) -> sign.add(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512)) ) .build(); ---- Kotlin:: + [source,kotlin,role="secondary"] ---- var metadataLocation = "classpath:asserting-party-metadata.xml" var relyingPartyRegistration: RelyingPartyRegistration = RelyingPartyRegistrations.fromMetadataLocation(metadataLocation) // ... .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party // ... .signingAlgorithms { sign: MutableList -> sign.add( SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA512 ) } } .build(); ---- ====== NOTE: The snippet above uses the OpenSAML `SignatureConstants` class to supply the algorithm name. But, that's just for convenience. Since the datatype is `String`, you can supply the name of the algorithm directly. [[servlet-saml2login-sp-initiated-factory-binding]] Some asserting parties require that the `` be POSTed. This can be configured automatically via `RelyingPartyRegistrations`, or you can supply it manually, like so: [tabs] ====== Java:: + [source,java,role="primary"] ---- RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistration.withRegistrationId("okta") // ... .assertingPartyDetails(party -> party // ... .singleSignOnServiceBinding(Saml2MessageBinding.POST) ) .build(); ---- Kotlin:: + [source,kotlin,role="secondary"] ---- var relyingPartyRegistration: RelyingPartyRegistration? = RelyingPartyRegistration.withRegistrationId("okta") // ... .assertingPartyDetails { party: AssertingPartyDetails.Builder -> party // ... .singleSignOnServiceBinding(Saml2MessageBinding.POST) } .build() ---- ====== [[servlet-saml2login-sp-initiated-factory-custom-authnrequest]] == Customizing OpenSAML's `AuthnRequest` Instance There are a number of reasons that you may want to adjust an `AuthnRequest`. For example, you may want `ForceAuthN` to be set to `true`, which Spring Security sets to `false` by default. You can customize elements of OpenSAML's `AuthnRequest` by publishing an `OpenSaml4AuthenticationRequestResolver` as a `@Bean`, like so: [tabs] ====== Java:: + [source,java,role="primary"] ---- @Bean Saml2AuthenticationRequestResolver authenticationRequestResolver(RelyingPartyRegistrationRepository registrations) { RelyingPartyRegistrationResolver registrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations); OpenSaml4AuthenticationRequestResolver authenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver); authenticationRequestResolver.setAuthnRequestCustomizer((context) -> context .getAuthnRequest().setForceAuthn(true)); return authenticationRequestResolver; } ---- Kotlin:: + [source,kotlin,role="secondary"] ---- @Bean fun authenticationRequestResolver(registrations : RelyingPartyRegistrationRepository) : Saml2AuthenticationRequestResolver { val registrationResolver : RelyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(registrations) val authenticationRequestResolver : OpenSaml4AuthenticationRequestResolver = new OpenSaml4AuthenticationRequestResolver(registrationResolver) authenticationRequestResolver.setAuthnRequestCustomizer((context) -> context .getAuthnRequest().setForceAuthn(true)) return authenticationRequestResolver } ---- ======