1. Overview

In this tutorial, we’ll be setting up SAML2 with Spring Boot. SAML is a long-trusted technology for implementing secure applications. Setting up SAML requires configurations of multiple parties, hence making the process somewhat complex. We have to move back and forth a few times between our Service Provider and Identity Provider, so it requires patience as we follow a step-by-step guide. Let’s dive into each of the steps to create our working app.

2. Setting Up the Service Provider (Sp)

In our case, the Spring Boot application is our Service Provider. Let’s set up a Spring Boot app with Spring Security, Spring MVC, and OpenSAML dependencies. A key dependency is Spring Security SAML2. The new SAML2 support in the Spring Security framework is provided via a single dependency:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-saml2-service-provider</artifactId>
</dependency>

2.1. SAML Configurations

Let’s now add the necessary configurations for SAML2 in our application.yml. The most important configuration is the metadata from the Identity Provider. Although we’ve added the metadata-uri to our configurations for completion, at this moment, it isn’t available yet:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          okta:
            signing:
              credentials:
                - private-key-location: classpath:local.key
                  certificate-location: classpath:local.crt
            singlelogout:
              binding: POST
              response-url: "{baseUrl}/logout/saml2/slo"
            assertingparty:
              metadata-uri: "classpath:metadata/metadata-idp.xml"

The singlelogout configuration defines the endpoint where our Identity Provider will redirect after successful logout. Furthermore, the signing credentials configuration adds the key and the certificate that our app will use to sign the logout request to the Identity Provider. We use the OpenSSL tool to generate the local.key and local.crt files:

openssl req -newkey rsa:2048 -nodes -keyout local.key -x509 -days 365 -out local.crt

2.2. Security Configurations in the Code

In this step, let’s add a security filter to our filter chain. This filter adds the Identity Provider metadata to our security context. In addition to this, let’s also add saml2Login() and saml2Logout() method calls on our http object to enable login and logout, respectively:

Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());

http.csrf(AbstractHttpConfigurer::disable).authorizeHttpRequests(authorize -> authorize.anyRequest()
  .authenticated())
  .saml2Login(withDefaults())
  .saml2Logout(withDefaults())
  .addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);

return http.build();

We’re using the withDefaults() method to configure the default behaviors for saml2Login and saml2Logout. This is the real power of using the Spring Boot platform. Only a few lines of code complete all our SAML2 application setup. Next, we’re going to set up our Identity Provider in Okta.

3. Setting Up the Identity Provider (IdP)

In this step, let’s set up Okta as our Identity Provider. The Identity Provider is the party that authenticates our users and generates a SAML assertion as a result. Then, this SAML assertion is communicated back to our User Agents. The User Agents present this SAML assertion to the Service Provider for authentication. The Service Provider verifies it from the Identity Provider and allows the users to access its resources.

On the Okta developer account after signup and login, we get a screen with a left sidebar. In this sidebar, let’s navigate to the Applications page and start our SAML application integration process:

Okta dashboard

3.1. Create App Integration

Next, let’s click ‘Create App Integration’ to open the ‘Create a new app integration’ dialog and choose SAML 2.0:

Okta create a new app integration

We’ll click on ‘Next’ to start the ‘Create SAML Integration’ wizard. This is a three-step wizard. Let’s complete each step to finish our setup.

3.2. General Settings

We enter our app name in this step as ‘Baeldung Spring Security SAML2 App‘:

Okta create SAML integration

3.3. Configure SAML

Let’s now configure the most important details for our SAML app. Here, we’ll register the Single Sign-on URL in the Identity Provider. As a result, the Identity Provider accepts the SSO request coming from this URL. The Audience URI is the identifier for the SAML assertion recipient. This is added to the SAML assertion that is generated and sent back to the user agent:

Okta Create A New App Integration Configure

The Audience URI in our example is http://localhost:8080/saml2/service-provider-metadata/okta while the single sign-on URL is http://localhost:8080/login/saml2/sso/okta

3.4. Advanced Settings and User Attributes

Let’s now expand the ‘Show Advanced Settings’ section. In order to enable the singlelogout feature, we’ll need to upload the local.crt certificate here. This is the same certificate we have configured in our Service Provider application.yml. The Service Provider app signs any logout request using this certificate.

Create SAML Integration

Additionally, let’s configure the ‘Single Logout URL’ as http://localhost:8080/logout/saml2/slo.

In the end, we also configure the Attribute Statements for emailAddress and firstName:

emailAddress -> Unspecified -> user.email
firstName -> Unspecified -> user.firstName

Let’s preview the SAML assertion using the ‘Preview the SAML Assertion’ link at the bottom of this step before moving to the ‘Next’ step.

Preview SAML

3.5. Final Feedback

On the feedback step, let’s choose the option, “I’m an Okta customer adding an internal app”.

SAML integration feedback step

3.6. SAML Setup Instructions

After completing the feedback step, we’ll end up on the ‘Sign On’ tab for our application. On this screen let’s follow the link “View SAML setup instructions” at the bottom of the right sidebar:

SAML configuration sign in step

This takes us to a page with the necessary information about our Identity Provider. Let’s move to the last field that has IdP metadata present in it:

SAML settings and certificate configurations

We copy this metadata and save it as metadata-idp-okta.xml in our Service Provider app resources/metadata folder, hence fulfilling the requirement of metadata_uri in our application.yml:

Okta create a new app integration fetch IDP metadata

This completes our setup for both the ‘Service Provider’ and the ‘Identity Provider’. Next, we’re going to create a user and assign it to our application in our Okta developer account.

4. Creating the User Principal

Let’s sign in to the Okta developer account and navigate to the ‘People’ page under the ‘Directory’ section in the left sidebar. Here, we’ll fill out the ‘Add Person’ form to create a user. Sometimes, it might need a refresh of the ‘People’ page to see the new user in the list:

Add a new Okta user

In this case, we are activating the user automatically. Usually, you might want to send an activation email or switch the toggle to make the user change the assigned password on the first attempt.

Finally, we click ‘Assign’ and follow a few steps to assign the new user to our SAML app.

Okta user assignment

5. Testing the Application

Now, we’re all set to test our app. Let’s launch our Spring Boot app and open the default endpoint for our app at http://localhost:8080. This takes us to the login screen:Okta User Login

Next, we’re on our successfully logged-in page. In addition to our username, we also get user attributes shown on this page, such as the emailAddress and the firstName:

Okta User Login Reset Password

This concludes the entire process of setting up our SAML app. But, before we leave, let’s check one last thing: the ‘Logout’ button.
First of all, we need to set the property as your okta identifier (you can see that in the URL):

spring:
  security:
    saml2:
      relyingparty:
        registration:
          okta:
            ...
            singlelogout:
              url: https://dev-<OKTA-ID>.okta.com/app/dev-56617222_springbootsaml_1/exk8b5jr6vYQqVXp45d7/slo/saml
              binding: POST
              response-url: "{baseUrl}/logout/saml2/slo"

Then we will be able to log out from all our SAML sessions against the logged-in user:

Okta User Logout Success

6. Conclusion

In this article, we learned about Spring Boot Security SAML2 support. Although SAML2 is a complex technology, it’s the first choice for large enterprises. Once we understand SAML2, it’s really fun to utilize the powerful features it provides. In addition to securing our application, SAML2 allows us to use SSO and avoid remembering multiple usernames and passwords for dozens of applications.

As always, the source code for the article’s example is available over on GitHub.