1

I've been looking for a solution in many questions and forums but nothing worked for me. I've a use case, in which we register Idp configuration in another service, and then we retrieve that particular configuration providing an orgId query param. Somehow I could built something that works on localhost with Okta as Idp, based on these sites:

Here I could delegate Idp selection before real saml auth gets triggered:
Spring Security SAML2 dynamic selection of IDPs or dynamic URLs for them

It works on localhost even SLO, but when we deploy the service to a EKR cluster, for all backend services, at first we can load the login redirection like:

http://dev.org.com/services/sso/auth-sso?orgId=<id>

It goes to Okta, and we can login, when it tries to redirect back to our service, the "/" path doesn't get triggered and somehow the url it's redirected to

http://dev.org.com/auth-sso?error

We have tried, context-path setting in application.yml with no success, and lastly I read this reference

https://docs.spring.io/spring-security-saml/docs/1.0.4.BUILD-SNAPSHOT/reference/html/configuration-advanced.html#configuration-load-balancing

Also referenced to this questions: Spring SAML 2.0 behind Nginx

but this spring saml version, doesn't recognize SAMLContextProviderLB or SAMLContextProviderImpl

Here some code:

build.gradle.kt:

   constraints {
      implementation("org.opensaml:opensaml-core:4.1.1")
      implementation("org.opensaml:opensaml-saml-api:4.1.1")
      implementation("org.opensaml:opensaml-saml-impl:4.1.1")
   }

   // spring
   implementation("org.springframework.boot:spring-boot-starter-web")
   implementation("org.springframework.boot:spring-boot-starter-security")

   // saml2
   implementation("org.springframework.security.extensions:spring-security-saml2-core:2.0.0.M31")
   implementation("org.springframework.security:spring-security-saml2-service-provider:5.7.4")

In my SamlConfig class, I define these beans:

securityFilterChain:

@Bean
fun securityWebFilterChain(http: HttpSecurity): SecurityFilterChain {
    
    http
        .authorizeRequests {
            it
            .mvcMatchers("/auth-sso").permitAll()
            .mvcMatchers("/actuator/*").permitAll()
            .anyRequest().authenticated()
        }
        .saml2Login {
            it.loginPage("/auth-sso")
        }
        .saml2Logout{}

    return http.build()
}

and a custom implementation of RelyingPartyRegistrationRepository, as LazyRelyingPartyRegistrationRepository :

@Bean
protected fun relyingPartyRegistrations(): RelyingPartyRegistrationRepository? {
    return LazyRelyingPartyRegistrationRepository()
}

And this is my /auth-sso

@GetMapping(value = ["/auth-sso"])
@ResponseBody
fun login(
    @RequestParam(name = "orgId", required = true) orgId: String,
    request: HttpServletRequest,
    response: HttpServletResponse
)  {

    try {

        val id = runBlocking {
            findIdpConfigurationUseCase.execute(object : UserOrganizationLogin {
                override val organizationId = organizationId
                override val token: String? = null
            })
        }

        val spInitiateUrl = "saml2/authenticate/$id"
        log.debug("Redirecting to {}", spInitiateUrl)

        response.sendRedirect(spInitiateUrl)

    }
    catch (e: Exception) {
        log.error("Error preparing assertion info: {}", e)
        response.sendRedirect(MessageFormat.format(environment.getRequiredProperty(HOME_URL), ""))
    }
}

My "auth entry point" / which recieves the Principal crendentials and login the user calling a use case with internally create user and generates token:

@RequestMapping("/")
fun index(model: Model, @AuthenticationPrincipal principal: Saml2AuthenticatedPrincipal, response: HttpServletResponse) {

    log.debug("User is authenticated!!!")

    val loginInfo = runBlocking {
        loginUserUseCase.execute(principal)
    }

    response.sendRedirect(
        environment.getRequiredProperty(HOME_URL) +
        MessageFormat.format(environment.getRequiredProperty(SSO_HOME_PARAMS), loginInfo.token, loginInfo.organizationId)
    )
}

0 Answers0