Get Started with Spring Boot, SAML, and Okta

Matt Raible

Unfortunately, I don’t know the answer to your question Trevor. I’d suggest posting it on Stack Overflow and tagging it with “spring-security” and “saml”.

Trevor Miller

I found the answer, the .basePath("/") configuration can be configured with the context path then everything works.

Matt Raible

Cool! I’m glad you figured it out. Thanks for reporting back with the solution too!

Melo Dai

hello Matt, your tutorial is very helpful, i only has one problem.
when i first go to 8443 and login with okta user, it works fine.
but after several minutes, if i refresh the 8443 page, it will cause a problem “Response doesn’t have any valid assertion which would pass subject validation”, and the web page is keeping switching between 8443 page and okta page, i think it is about the authorization in cookies is invalidate, so how could i handle this

Matt Raible

Hello Melo,

Unfortunately, I don’t know what could be causing this. I’d suggest posting it as a question on our Developer Forums or on Stack Overflow. If you post it to Stack Overflow, make sure add “spring security”, “saml”, and “okta” tags.

Melo Dai

thank you, one more question, do you know how to generate the sp metadata and set up the “/saml/metadata” ?

Matt Raible

The security.saml2.metadata-url in this example is provided by Okta. You just copy the URL after you’ve created your SAML app.

Juan Timoteo Ponce Ortiz

Hi Matt!, I’ve worked with SAML before and this is the first guide that works flawlessly at the first attempt, great job!

Just wanted to know how one would handle the session-logout in this spring-boot project with Okta.

Matt Raible

Hello Juan - I’m glad it worked on your first try!

I opened an issue for the spring-security-saml-dsl project to add a logout example. If you look at the bottom of that issue, it appears a commit was made and if you use a SNAPSHOT version, it might even work.

FWIW, the Spring Security team published a Spring Security SAML Roadmap back in March. I believe they’ll be rolling this extension into Spring Security core in the future.

Walter Hill

Excellent tutorial Matt, thanks very much!

hipster

Hi matt from this app how can i generate saml token and pass this to another app that generate JWT token .

Matt Raible

We have documentation that might help.

Okta supports authentication with an external SAML Identity Provider (IdP). The SAML IdP redirects you to Okta or your application, also called Inbound SAML. You can also include an OpenID Connect ID token with this redirect. Thus, you can use Okta to proxy between SAML-only Identity Providers and OpenID Connect-only applications that normally are incompatible.

Juan Timoteo Ponce Ortiz

Yup, applied the patch and now I get a different error though “IDP doesn’t contain any SingleLogout endpoints” from okta

hipster

hi matt when i am trying to get principal user using saml i am getting org.opensaml.saml2.core.impl.NameIDImpl@2a7df764 instead of username do i need to configure something

Matt Raible

I tried using Principal and Spring Security’s SecurityContext, but I’m unable to figure it out. Here’s what I have so far:


@Controller
public class IndexController {

@RequestMapping("/")
public String index(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
model.addAttribute(“name”, currentPrincipalName);
return “index”;
}
}

If I make my “index.html” template the following:


<!DOCTYPE html>
<html xmlns=“XHTML namespace” xmlns:th=“http://www.thymeleaf.org”>
<head>
<title>Spring Security SAML Example</title>
</head>
<body>
<p>You are successfully logged in <span style=“font-weight:bold” th:text="${name}"></span></p>
</body>
</html>

It prints out:

You are successfully logged in org.opensaml.saml2.core.impl.NameIDImpl@389c1873

This is the same issue you’re seeing. Sorry I can’t be of more assistance. I’m stumped at this point.

https://uploads.disquscdn.c…

hipster

i try with the same what getting the same response
@RequestMapping("/")
public String index(Principal principal) {

Authentication authenticationt=SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName =authenticationt.getName();

System.out.println(“GGGGGGGGGG”+currentPrincipalName);

String url =“http://localhost:8080/oauth/token”;
System.out.println(“after url”);
//String result = restTemplate.getForObject(url, String.class);
//System.out.println(“uuuuuuuuuuuuuuuuuuuuurk=l”+result);
return currentPrincipalName;

}
i also got similar post in http://forum.spring.io/foru… Setting property forcePrincipalAsString to true in the SAMLAuthenticationProvider will solve the issue. It will tell system to store a String as a principal inside the SAMLAuthentication object instead of the NameID from the SAML assertion. i try to add in application property but its not working .do i have to set this in okta if yes than where i didnt see anything in okta

subrat

Hi Matt, i have the SSL certificate which is provided by okta for my application. now the question is how do i create a keystore out of the SSL certificate to communicate to okta.

Matt Raible

Okta uses HTTPS for your tenant, but this doesn’t have anything to do with your application, since your application will live on a different domain. You will need to create/buy/generate an SSL certificate for your application. If you have additional questions, I’d invite you to ask them on our Developer Forums.

Brian Demers

Based on Matt’s suggestion I was able to come up with a couple options.
a.) Most obvious cast the principal to NameID and pull the user’s email address out.
b.) Add custom attributes to the SAML assertion, and parse them out of the response.

My controller looks like this (forgive the unchecked casting):


@RequestMapping("/")
public String index(Model model) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
NameID nameId = (NameID) authentication.getPrincipal();
model.addAttribute(“name”, nameId.getValue());

// there be dragons
Assertion assertion = (Assertion) nameId.getParent().getParent();
assertion.getAttributeStatements().forEach(attributeStatement → {
attributeStatement.getAttributes().forEach(attribute → {
String key = attribute.getName();
// cheat a little to not deal with an array/list value
String value = ((XSString) attribute.getAttributeValues().get(0)).getValue();
model.addAttribute(key, value);
});
});

return “index”;
}

And my template:

 

<!DOCTYPE html>
<html xmlns=“XHTML namespace” xmlns:th=“http://www.thymeleaf.org”>
<head>
<title>Spring Security SAML Example</title>
</head>
<body>
<p>You are successfully logged in <span style=“font-weight:bold” th:text="${name}"></span></p>
<p>Name: <span th:text="${firstName}"></span>&nbsp;<span th:text="${lastName}"></span></p>
</body>
</html>


To add the firstName and lastName attributes you can edit your SAML application and include something like this:
https://uploads.disquscdn.c…

Jason

Brian, Question from a newbie: Getting the error below. What needs to be done so the Authentication class can be found? Assuming it is some dependency in pom.xml.

com/example/demo/IndexController.java:[18,9] cannot find symbol
[ERROR] symbol: class Authentication