Spring Boot + Spring Security with SAML 2.0
In this article we are going to see how to configure authentication using the standard SAML 2.0 (Security Assertion Markup Language) on an application built with the Spring Boot framework.
The dependencies used:
- Spring Boot 2.4.2
- Spring Security 5.4.2
- Spring Security SAML2 Service Provider 5.4.2
As Identity Provider (free) we use Okta.
All the Java source present in the article is available at the following Git repos:
What is SAML 2.0?
SAML (Security Assertion Markup Language) è uno standard informatico per lo scambio di dati di autenticazione e autorizzazione (asserzioni SAML basate su XML) tra domini di sicurezza eterogenei.
In genere le entità che partecipano sono due:
SAML (Security Assertion Markup Language) is an IT standard for exchanging authentication and authorization data (SAML assertion based on XML) between heterogeneous security domains.
There are usually two participating entities:
- Identity Provider: abbreviated IdP is a system entity that creates, maintains, and manages identity information for principals (users) and also provides authentication services to relying applications within a federation or distributed network. Usually these systems are part of the IAM (Identity Access Management) world with WAM (Web Access Management) modules
- Service Provider: Application that provides a service protected by SAML2 security
SAML is a market standard and is maintained by the OASIS Security Services Technical Committee (link).
The main use case that SAML tries to solve is that of Web Single Sign-on (SSO) between entities belonging to distinct organizations and security domains.
How SAML 2.0 works?
SAML requires that the user (called “principal”) be registered with at least one identity provider. The identity provider must authenticate the user. The service provider now relies on the identity provider to identify the principal. At the request of the principal, the identity provider passes a SAML assertion (XML-based) to the service provider on the basis of which the latter decides whether to allow or deny access to its services by the principal.
The Sequence Diagram of SAML 2.0 Authentication Flow is shown below:
Identity Provider Configuration (Okta)
First we have to configure our application, which we will later create with the Spring Boot framework, on an Identity Provider.
The Identity Provider used is Okta, so after creating a free Developer account, let’s create our Application.
Entering the administration console, under the heading “Applications”, we find the “Add Application” button:
Clicking on the button, in the modal window where we specify the type of platform (in this case “Web”) and the type of authentication we want to use, specifically SAML 2.0:
On the following page we are going to enter the name of our application (in the figure we have entered “App SAML”):
Moving forward in the process we can now configure the parameters necessary for the configuration of our Identity Provider (briefly IdP) for the use of SAML.
The values we are going to insert are the following:
- Single sign on URL: http://localhost:8080/login/saml2/sso/okta-saml
- Audience URI (SP Entity ID): http://localhost:8080/saml2/service-provider-metadata/okta-saml
We conclude the configuration of our Application by declaring that it is an internal test application that we are creating:
Once the application creation procedure has been completed, select it and move to the “Assignements” tab and add the users enabled to access the application.
Now that our application has been created and we have instructed the Identity Provider with the information of the users who can access it, it is now time to configure our Spring Boot application.
For the configuration we need to retrieve some parameters that will be needed later, by going to the “Sign On” tab, click on “View Setup Instructions” under the SAML 2.0 box.
At the opening of the page we go to save the information in points 1, 2 and 3.
Spring Security SAML2
First we are going to create our project with Maven, below we report the pom.xml useful to satisfy the dependencies of Spring Boot and Spring Security:
Our pom.xml contains the following dependencies:
Then we create our Spring Boot Application with two web pages, the home and a post-authentication page (/secured/hello) in which we will print the logged in user returned from the Identity Provider.
As we see above, to retrieve the principal (user) logged in, let’s use this annotation, within the parameters of the method:
@AuthenticationPrincipal Saml2AuthenticatedPrincipal principal
Another mechanism to retrieve the principal, without wanting to use the annotation is the following:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Saml2AuthenticatedPrincipal principal = (Saml2AuthenticatedPrincipal) authentication.getPrincipal();
Now let’s move on to configuring Spring Security:
In the source above you can see the following configurations:
- Enable SAML2 via the following snippet:
- Generation of the Service Provider metadata.xml file (of our application).
The metadata.xml will be viewable and downloadable at:
This file is most often used as a contract between the Identity Provider and the Service Provider. The code that allows the generation is the following:
// add auto-generation of ServiceProvider Metadata
Converter<HttpServletRequest, RelyingPartyRegistration> relyingPartyRegistrationResolver = new DefaultRelyingPartyRegistrationResolver(relyingPartyRegistrationRepository);Saml2MetadataFilter filter = new Saml2MetadataFilter(relyingPartyRegistrationResolver, new OpenSamlMetadataResolver());http.addFilterBefore(filter, Saml2WebSsoAuthenticationFilter.class);
- The RelyingPartyRegistrationRepository bean useful for configuring parameters for SAML2. In this bean we are going to insert the values taken in the “Setup Instructions” page of the Okta provider (step explained a few paragraphs above). In detail, by viewing the image “SAML 2.0 configuration parameters”, we are going to insert the value at point 1 in singleSignOnServiceLocation, the value at point 2 in entityId and copy the content of the certificate at point 3 under the file in /src/main/resources/saml-certificate/okta.crt and insert the pointing into the verificationKey
If you don’t want to create the RelyingPartyRegistrationRepository bean programmatically, you can use the configuration in the Spring application.yaml file shown below:
Lastly, let’s create our two web pages:
- The homepage, with a link to the protected page:
- Our secure page, where we will print the user logged in via IdP:
Our application is now ready and configured for SAML2 authentication.
Authentication with SAML2
Execute the command to start our application:
From browser by navigating to the address http://localhost:8080/ , we will display our home page.
By clicking on the link we will automatically be redirected to the login page of the Identity Provider, as shown:
We enter the Okta credentials (of the associated user on the Okta application, configured in the paragraphs above) and upon successful login, we will be redirected back to our application at the requested page (therefore the protected one) and we will be able to see the user with the which we logged into Okta.
We are now inside our application logged in via SAML2!