Skip to content
Ashish.
All posts
Diagram showing Spring Security SAML integration flow
6 min readDevelopmentJava DevelopersFeatured#spring security#saml#spring boot#authentication#sso#java#security

Spring Security SAML: A Working Integration

A practical guide to integrating Spring Security SAML with Spring Boot, covering SAML2 relying party configuration, service provider setup, and metadata handling.

By Ashish Kumar

Integrating spring security saml into a Spring Boot application used to require manually wiring Saml2WebSsoAuthenticationFilter instances, managing MetadataProvider beans, and handling raw XML parsing. In Spring Security 6.x, the mechanism has shifted from imperative filter chaining to a declarative configuration model centered on RelyingPartyRegistrationRepository. This shift reduces boilerplate and enforces correctness by treating the SAML configuration as data rather than code. This guide details how to build a working integration by focusing on the RelyingPartyRegistration artifact, its metadata exchange, and the underlying HTTP flow.

The RelyingParty Registration Artifact

The core mechanism in modern Spring Security SAML is the RelyingPartyRegistration. Unlike previous versions where you manually instantiated filters, Spring Boot now uses this registration object to automatically configure the entire authentication filter chain. The RelyingPartyRegistration holds three critical pieces of state: the cryptographic material (certificates and keys), the endpoint URLs (IdP Single Sign-On and Logout URLs), and the entity identifiers.

When Spring Security starts, it looks for a bean of type RelyingPartyRegistrationRepository. If you provide a YAML or Properties configuration, Spring Boot auto-creates this repository. This repository acts as a lookup table. When a user attempts to log in, the Saml2WebSsoAuthenticationRequestFilter queries this repository to determine which IdP to contact. This decouples the authentication logic from specific IdP implementations, allowing you to switch IdPs by changing configuration data, not code.

Configuration as Data

To establish a working integration, you must define the relying party in application.yml. The structure maps directly to the RelyingPartyRegistration.Builder methods. The most common mistake is misaligning the entityId or providing an incorrect signing certificate.

spring:
  security:
    saml2:
      relyingparty:
        registration:
          my-idp: # This key is the registration ID
            assertingparty:
              entity-id: https://idp.example.com/entityID
              singlesignon:
                url: https://idp.example.com/sso
                binding: REDIRECT
              singlelogout:
                url: https://idp.example.com/logout
                binding: REDIRECT
              verification:
                credentials:
                  - certificate: |
                      MIID... (IdP's public cert for validating assertions)
            signing:
              credentials:
                - certificate: |
                    MIID... (Base64 encoded X.509 cert)

In this configuration, my-idp is the registration ID used in your security config. The assertingparty.entity-id is the unique identifier for the IdP. The assertingparty.singlesignon.url is where the browser will be redirected. The verification.credentials are crucial: they tell Spring Security which public key to use to validate the digital signature on the SAML Assertion returned by the IdP. Without this, the OpenSaml4AuthenticationProvider will reject the assertion as untrusted.

Technical diagram showing YAML configuration mapping to SAML2RelyingPartyRegistration object. Clean, minimalist style, blue and white color scheme, clear labels for entity-id, certificates, and endpoints.

The SSO Flow Mechanism

Understanding the HTTP flow is essential for debugging. The process begins when a user accesses a protected resource, triggering Spring Security’s AuthorizationFilter. Since the user is unauthenticated, they are redirected to the login page. In a SAML setup, the login page is not a HTML form but a redirect trigger.

  1. Redirect Initiation: The user hits /login. Spring Security’s Saml2WebSsoAuthenticationRequestFilter intercepts this. It looks up the RelyingPartyRegistration (defaulting to the first available if no specific ID is provided). It constructs a Saml2RedirectAuthenticationRequest and redirects the browser to the IdP’s assertingparty.singlesignon.url defined in the YAML.
  2. IdP Processing: The IdP authenticates the user (via username/password, MFA, etc.) and generates a SAML Assertion. This assertion is signed with the IdP’s private key.
  3. POST Response: The IdP sends an HTTP POST response to the Spring Boot application’s /login/saml2/sso/{registrationId} endpoint. This endpoint is automatically mapped by Spring Security based on the RelyingPartyRegistration.
  4. Validation: The Saml2WebSsoAuthenticationFilter receives the POST data. It extracts the SAMLResponse parameter and validates the embedded XML digital signature within the assertion. It uses the verification.credentials from the RelyingPartyRegistration to verify the signature. If valid, it parses the assertion to extract attributes (like email or name).
  5. Authentication Creation: Spring Security creates a Saml2AuthenticatedPrincipal and places it in the SecurityContext. The user is now logged in.

This flow relies entirely on the OpenSaml4AuthenticationProvider. If the signature verification fails, the provider throws an exception, and the login fails silently or with a generic error. Always check your logs for Saml2AuthenticationException if the flow breaks at step 4.

Metadata Handling and Discovery

One of the most powerful features of this integration is automatic metadata generation. Instead of manually uploading an XML file to your IdP, Spring Security exposes the Service Provider (SP) metadata at /saml2/service-provider-metadata/{registrationId}.

This endpoint is handled by Saml2MetadataFilter. It dynamically generates the XML metadata document based on your RelyingPartyRegistration. The metadata includes your SP’s entityID, your ACS (Assertion Consumer Service) URL (/login/saml2/sso/{registrationId}), and your public signing certificate (if configured for request signing).

To expose this, ensure your security config allows access to the metadata endpoint. Typically, you do this by permitting all requests to /saml2/** for unauthenticated users, or by explicitly mapping the metadata filter.

@Configuration
public class SecurityConfig {
 
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, 
            RelyingPartyRegistrationRepository registrations) throws Exception {
        
        http
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/saml2/**").permitAll() // Allow metadata access
                .anyRequest().authenticated()
            )
            .saml2Login(saml2 -> saml2
                .relyingPartyRegistrationRepository(registrations)
            );
            
        return http.build();
    }
}

By accessing /saml2/service-provider-metadata/my-idp, you get the XML needed to configure the IdP. This ensures that your SP’s certificate and endpoints are always in sync with the application’s runtime configuration. If you change the certificate in application.yml, the metadata endpoint reflects the change immediately upon restart.

Conclusion

Spring Security’s SAML2 integration works by treating SAML configuration as structured data (RelyingPartyRegistration) rather than imperative code. By defining the IdP endpoints, certificates, and entity IDs in YAML, Spring Boot automatically wires the Saml2WebSsoAuthenticationFilter and Saml2MetadataFilter. The mechanism hinges on the validation of the IdP’s signature using the configured verification credential and the dynamic generation of SP metadata. This approach minimizes boilerplate, reduces the risk of misconfiguration, and aligns with Spring Boot’s convention-over-configuration principles. For production deployments, ensure that the entityID matches exactly between the SP and IdP configurations, as any mismatch will cause the IdP to reject the authentication request.

Related posts