oktaspring-security-saml2

Spring boot and Okta SAML2


I like the idea of using spring-security-saml2-service-provider - from of docs: https://docs.spring.io/spring-security/reference/5.6.0-RC1/servlet/saml2/index.html Instead of spring-security-saml2-core it looks way less boilerplate, but I catch 400 response when I send App Embed Link from Okta admin app. Through debug it seems that

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        AbstractSaml2AuthenticationRequest authenticationRequest = this.authenticationRequestResolver.resolve(request);
        if (authenticationRequest == null) {
            filterChain.doFilter(request, response);..}

can't resolve the incoming request,but I am not sure whether it's related. My yml config:

 security:
    saml2:
      relyingparty:
        registration:
          okta:
            identityprovider:
              entity-id: http://www.okta.com/exk1juy5xrR5BsW44697
              verification.credentials:
                - certificate-location: "classpath:saml/okta.cert"
              singlesignon.url: https://trial-8410773.okta.com/app/trial-8410773_templatemanager_2/exk1juy5xrR5BsW44697/sso/saml
              singlesignon.sign-request: false
              assertingparty.metadata-uri: https://trial-8410773.okta.com/app/trial-8410773_templatemanager_2/exk1juy5xrR5BsW44697/sso/saml/metadata

My Okta config:

GENERAL
Single Sign On URLhttp://localhost:8080/api/v1/saml2/SSO
Requestable SSO URLsURLIndex
http://localhost:8080/api/v1/saml2/SSO0Recipient URLhttp://localhost:8080/api/v1/saml2/SSODestination URLhttp://localhost:8080/api/v1/saml2/SSOAudience Restrictionhttp://localhost:8080/saml/metadata

Also I provide endpoint for saml authentication:

@RequestMapping(SsoAuthenticationController.BASE_NAME)
public interface SsoAuthenticationController {

    final String BASE_NAME = "/v1/saml2/SSO";

    @GetMapping("/")
    public ResponseEntity<HttpStatus> index( Saml2AuthenticatedPrincipal principal) ;
}

Actual security config:

http.cors()
        .and()
        .csrf()
        .disable()
        .authorizeRequests()
        .antMatchers(SECURITY_WHITELIST)
        .permitAll()
        .anyRequest()
        .authenticated()
        /*.and()
        .httpBasic()
        .and()
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint).and().sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)*/
        .and()
        .saml2Login(Customizer.withDefaults());

Here is Saml interceptor's logs for google chrome: https://pastebin.com/Be3NZe5B

Any ideas?


Solution

  • I created a Spring Boot 3 + SAML example with Okta recently. Hopefully, these instructions help.

    Create a Spring Boot app using start.spring.io. Select the following options:

    Add src/main/java/com/example/demo/HomeController.java to populate the authenticated user's information.

    package com.example.demo;
    
    import org.springframework.security.core.annotation.AuthenticationPrincipal;
    import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HomeController {
    
        @RequestMapping("/")
        public String home(@AuthenticationPrincipal Saml2AuthenticatedPrincipal principal, Model model) {
            model.addAttribute("name", principal.getName());
            model.addAttribute("emailAddress", principal.getFirstAttribute("email"));
            model.addAttribute("userAttributes", principal.getAttributes());
            return "home";
        }
    
    }
    

    Create a src/main/resources/templates/home.html file to render the user's information.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
          xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity6">
    <head>
        <title>Spring Boot and SAML</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    </head>
    <body>
    
    <h1>Welcome</h1>
    <p>You are successfully logged in as <span sec:authentication="name"></span></p>
    <p>Your email address is <span th:text="${emailAddress}"></span>.</p>
    <p>Your authorities are <span sec:authentication="authorities"></span>.</p>
    <h2>All Your Attributes</h2>
    <dl th:each="userAttribute : ${userAttributes}">
        <dt th:text="${userAttribute.key}"></dt>
        <dd th:text="${userAttribute.value}"></dd>
    </dl>
    
    <form th:action="@{/logout}" method="post">
        <button id="logout" type="submit">Logout</button>
    </form>
    
    </body>
    </html>
    

    Create a src/main/resources/application.yml file to contain your metadata URI.

    spring:
      security:
        saml2:
          relyingparty:
            registration:
                assertingparty:
                  metadata-uri: <your-metadata-uri>
    

    Then, change build.gradle to use thymeleaf-extras-springsecurity6 instead of thymeleaf-extras-springsecurity5 and add Spring Security SAML's dependency:

    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
    implementation 'org.springframework.security:spring-security-saml2-service-provider'
    

    To get the metadata URI from Okta, log in to your account and go to Applications > Create App Integration. Select SAML 2.0 and click Next. Name your app something like Spring Boot SAML and click Next.

    Use the following settings:

    Then click Next. Select the following options:

    Select Finish.

    Okta will create your app, and you will be redirected to its Sign On tab. Scroll down to the SAML Signing Certificates and go to SHA-2 > Actions > View IdP Metadata. You can right-click and copy this menu item's link or open its URL. Copy the resulting link to your clipboard. It should look something like the following:

    https://dev-13337.okta.com/app/<random-characters>/sso/saml/metadata
    

    Go to your app's Assignment tab and assign access to the Everyone group.

    Paste your metadata URI in to your application.yml file. Start the app using ./gradlew bootRun and open http://localhost:8080 in your favorite browser. You should be redirected to login.