SAML2 Service Provider configuration for enterprise single sign-on (SSO) integration with SAML2 Identity Providers.
Configure SAML2 authentication (Web Browser SSO Profile).
package org.springframework.security.config.annotation.web.configurers.saml2;
public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>>
extends AbstractAuthenticationFilterConfigurer<B, Saml2LoginConfigurer<B>,
Saml2WebSsoAuthenticationFilter> {
public Saml2LoginConfigurer<B> relyingPartyRegistrationRepository(
RelyingPartyRegistrationRepository relyingPartyRegistrationRepository
);
public Saml2LoginConfigurer<B> authenticationManager(
AuthenticationManager authenticationManager
);
public Saml2LoginConfigurer<B> authenticationConverter(
AuthenticationConverter authenticationConverter
);
public Saml2LoginConfigurer<B> authenticationRequestContextResolver(
Saml2AuthenticationRequestContextResolver authenticationRequestContextResolver
);
public Saml2LoginConfigurer<B> loginPage(String loginPage);
public Saml2LoginConfigurer<B> loginProcessingUrl(String loginProcessingUrl);
public Saml2LoginConfigurer<B> successHandler(
AuthenticationSuccessHandler successHandler
);
public Saml2LoginConfigurer<B> failureHandler(
AuthenticationFailureHandler failureHandler
);
}Usage Example:
http
.saml2Login(Customizer.withDefaults());
// With custom configuration
http
.saml2Login(saml2 -> saml2
.loginPage("/saml2/login")
.defaultSuccessUrl("/dashboard")
.failureUrl("/login?error")
);
// application.yml configuration
spring:
security:
saml2:
relyingparty:
registration:
my-idp:
entity-id: "{baseUrl}/saml2/service-provider-metadata/{registrationId}"
signing:
credentials:
- private-key-location: classpath:credentials/rp-private.key
certificate-location: classpath:credentials/rp-certificate.crt
assertingparty:
entity-id: https://idp.example.com/entityid
singlesignon:
url: https://idp.example.com/sso
sign-request: true
binding: POST
verification:
credentials:
- certificate-location: classpath:credentials/idp-certificate.crtConfigure SAML2 single logout.
package org.springframework.security.config.annotation.web.configurers.saml2;
public final class Saml2LogoutConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<Saml2LogoutConfigurer<H>, H> {
public Saml2LogoutConfigurer<H> logoutUrl(String logoutUrl);
public Saml2LogoutConfigurer<H> logoutRequest(
Customizer<LogoutRequestConfigurer> logoutRequestCustomizer
);
public Saml2LogoutConfigurer<H> logoutResponse(
Customizer<LogoutResponseConfigurer> logoutResponseCustomizer
);
// Logout Request Configurer
public final class LogoutRequestConfigurer {
public LogoutRequestConfigurer logoutRequestResolver(Saml2LogoutRequestResolver logoutRequestResolver);
public LogoutRequestConfigurer logoutRequestRepository(Saml2LogoutRequestRepository logoutRequestRepository);
}
// Logout Response Configurer
public final class LogoutResponseConfigurer {
public LogoutResponseConfigurer logoutResponseResolver(Saml2LogoutResponseResolver logoutResponseResolver);
}
}Usage Example:
http
.saml2Login(Customizer.withDefaults())
.saml2Logout(Customizer.withDefaults());
// Custom logout configuration
http
.saml2Logout(saml2Logout -> saml2Logout
.logoutUrl("/saml2/logout")
.logoutRequest(logoutRequest -> logoutRequest
.logoutRequestResolver(customLogoutRequestResolver)
)
.logoutResponse(logoutResponse -> logoutResponse
.logoutResponseResolver(customLogoutResponseResolver)
)
);Configure SAML2 metadata endpoint.
package org.springframework.security.config.annotation.web.configurers.saml2;
public final class Saml2MetadataConfigurer<H extends HttpSecurityBuilder<H>>
extends AbstractHttpConfigurer<Saml2MetadataConfigurer<H>, H> {
public Saml2MetadataConfigurer<H> metadataUrl(String metadataUrl);
}Usage Example:
http
.saml2Metadata(Customizer.withDefaults());
// Metadata will be available at: /saml2/service-provider-metadata/{registrationId}// Relying Party Registration
public final class RelyingPartyRegistration {
public String getRegistrationId();
public String getEntityId();
public String getAssertionConsumerServiceLocation();
public Saml2MessageBinding getAssertionConsumerServiceBinding();
public String getSingleLogoutServiceLocation();
public String getSingleLogoutServiceResponseLocation();
public Saml2MessageBinding getSingleLogoutServiceBinding();
public AssertingPartyDetails getAssertingPartyDetails();
public Collection<Saml2X509Credential> getSigningX509Credentials();
public Collection<Saml2X509Credential> getDecryptionX509Credentials();
}
// Asserting Party Details (Identity Provider)
public final class AssertingPartyDetails {
public String getEntityId();
public String getSingleSignOnServiceLocation();
public Saml2MessageBinding getSingleSignOnServiceBinding();
public String getSingleLogoutServiceLocation();
public String getSingleLogoutServiceResponseLocation();
public Saml2MessageBinding getSingleLogoutServiceBinding();
public Collection<Saml2X509Credential> getVerificationX509Credentials();
public Collection<Saml2X509Credential> getEncryptionX509Credentials();
}
// SAML2 Authentication
public interface Saml2AuthenticatedPrincipal extends AuthenticatedPrincipal {
String getName();
Map<String, List<Object>> getAttributes();
List<Object> getAttribute(String name);
<A> A getFirstAttribute(String name);
String getRelyingPartyRegistrationId();
List<String> getSessionIndexes();
}@Configuration
@EnableWebSecurity
public class Saml2SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/", "/error").permitAll()
.anyRequest().authenticated()
)
.saml2Login(Customizer.withDefaults())
.saml2Logout(Customizer.withDefaults())
.saml2Metadata(Customizer.withDefaults());
return http.build();
}
// Programmatic Relying Party Registration (alternative to application.yml)
@Bean
public RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() {
RelyingPartyRegistration registration = RelyingPartyRegistration
.withRegistrationId("my-idp")
.entityId("https://my-app.example.com/saml2/service-provider-metadata/my-idp")
.assertionConsumerServiceLocation("https://my-app.example.com/login/saml2/sso/my-idp")
.signingX509Credentials(c -> c.add(relyingPartySigningCredential()))
.assertingPartyDetails(party -> party
.entityId("https://idp.example.com/entityid")
.singleSignOnServiceLocation("https://idp.example.com/sso")
.wantAuthnRequestsSigned(true)
.verificationX509Credentials(c -> c.add(assertingPartyVerificationCredential()))
)
.build();
return new InMemoryRelyingPartyRegistrationRepository(registration);
}
// Access SAML2 attributes in controller
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal Saml2AuthenticatedPrincipal principal) {
return Map.of(
"name", principal.getName(),
"email", principal.getFirstAttribute("email"),
"attributes", principal.getAttributes()
);
}
}