How to connect Okta SAML and Spring Boot using saml2Login, part 1
If you have a Spring Boot app, chances are you want to allow users to easily login to that app. Here I’ll show you how to use Okta as a SAML Identity Provider to allow your users in Okta to login to your app and preserve their identity.
Create a Dev Account on Okta
To start with, let’s create a dev account on Okta to create the SAML IdP. Start at https://developer.okta.com/signup/. Note that you can use an email that already has an account on Okta, since this email will be a fresh User in the new Okta Dev Account. Once you’re past the confirmation and password screens, you’ll see the Developer Console. You’re now logged in as the administrative user for this Okta Dev Account.
Click Developer Console and toggle to the Classic UI view. Several of the tasks below (People and Groups) can easily be done in either view, but most of the SAML configuration seems only possible in the Classic UI view.
Let’s create another user that can also login to your application. Go to Directory > People and click “Add Person”. Note that you’ll need to use a valid email address here so that you can respond to the activation email. This shouldn’t be the same as your administrative user for the Okta Dev Account. However, if you use Gmail, you can use the + trick to create a different email address.
Click “Save”. Then go through the activation flow for that user. Now set up some groups that your two users can belong to. Navigate to Directory > Groups and click “Add Group”. Note that both users are already in a group called “Everyone”, so we’ll just add a “User” group that your second user belongs to.
Click “Add Group”. You should now see the Users group.
Click “Users”, then “Manage People”. Click your second user and click “Save”.
Add an Application in Okta, which acts as the SAML IDP
Now let’s create the “Application” in Okta. Note that this just means Okta is aware of your local Spring Boot app and knows to create a SAML IdP for it. Click “Applications” and then “Add Application”.
Then click “Create New App”.
Choose “Web” and “SAML 2.0”, then click “Create”.
For App name, I suggest something like “localhost8080” to indicate that this app will (currently) only run at localhost:8080. Then click “Next”.
On step 2 “Configure SAML” we have to be careful to set this up correctly so that it will work correctly with Spring Boot+saml2Login. See below for an example. For the Single sign on URL and Audience URI, note the special string oktaXYZ
. This will be the identifier for for this SAML IdP for saml2Login. For ease of copy/pasting, I’ll include the URIs here.
http://localhost:8080/login/saml2/sso/oktaXYZ
http://localhost:8080/saml2/service-provider-metadata/oktaXYZ
The additional attributes (FirstName, LastName, and Email) are for purposes of example — you may need to add or modify attributes based on your application’s needs. The Group Attribute Statement is helpful, and it indicates that all of the user’s group will be in the Groups attribute of the SAMLResponse.
Click “Next”.
Configure section 3 “Feedback” and click “Finish”.
Now navigate to Applications > localhost8080 > Sign On.
Copy that link to “Identity Provider metadata”. You’ll need it to set up the Spring Boot app — coming up next! Note that much of the above Okta instructions are taken from https://developer.okta.com/docs/guides/build-sso-integration/saml2/create-your-app/, so if you get stuck, take a look at that documentation.
The Identity Provider metadata URL should look like this:
https://dev-#####.okta.com/app/XXXYYYZZZ/sso/saml/metadata
You’ll register this in your Spring Boot app as a SAML relying party, using registration ID oktaXYZ.
Assign the application to your users
In Okta, users must be assigned an application before they can use it. From the Applications view, click your application and then click “Assignments”. There should be no assignments currently. Click “Assign”, then “Assign to People”.
Select a user, accept the login email as username, and then click Assign. Note that this does give you the ability to change the user’s “username” on a per-application basis, but we don’t need that right now. Now you should see two users on the “Assignments” view.
Spring Boot + Spring Security
Here comes the code! I’ve created a sample at https://github.com/joshuatcasey/okta-boot-and-saml2login, so feel free to play around with that. Just substitute the Okta SAML metadata URL from the last step.
Important notes:
- This example uses Boot 2.4.0-SNAPSHOT, which is the only Boot version at the time of writing that includes Spring Security 5.4.1 (required)
- To use http://start.spring.io as the starting point for your own Spring Boot app, just add dependencies on
starter-web
andstarter-security
, then add the below additional dependency - Note the additional dependency on
spring-security-saml2-service-provider
, which is not available on http://start.spring.io/ as of the time of writing
In class `SecurityConfiguration` you will see a Bean registered with the following code snippet (see GitHub for full details). This is all it takes to register the Spring Boot app as a relying party “from the metadata location” specified, with registration ID “oktaXYZ”. This is all it takes to create the endpoints referenced above as the Single Sign On URL and Audience URI.
RelyingPartyRegistrations
.fromMetadataLocation(
"https://dev-#######.okta.com/app/XXXXXXXXXXXXXXXXXXXX/sso/saml/metadata")
.registrationId("oktaXYZ")
.build();
Now we also need to turn off the internal user store (this also means that the Spring Security default “user” with generated password won’t be created).
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
Run the sample app and visit http://localhost:8080/public — you should see the text “public” returned. Now visit http://localhost:8080/protected, and you will be redirected over to an Okta login page for your dev account. Provide the username and password for a user that has been assigned the app you made above, and you should be able to see the text “protected” returned!
This is configured via the HttpSecurity
DSL as shown below. Documentation for saml2Login
can be found here.
http.authorizeRequests()
.antMatchers("/protected").authenticated()
.antMatchers("/public").permitAll()
.anyRequest().denyAll()
.and().saml2Login();
I hope this helps. I plan to add another blog post to document how a user’s Groups in Okta can flow into roles or authorities in the Spring security model. Let me know if you would appreciate this!
UPDATE (2020-Dec-29): I’ve added part 2!