Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security SAML2 dynamic selection of IDPs or dynamic URLs for them

We're trying to configure several identity providers in the application to support different types of SSO. The problem is that for a non-authenticated request the application doesn't know which IDP to redirect to. We can figure out which IDP to use based on the domain name. That's not a problem. The problem is to change filters the way to redirect to that specific IDP instead of the first found one.

I wonder if there's an easy way to support it in Spring Security or its SAML2 library.

I can either somehow modify metadata to redirect it to my own URL (and then have some custom code there) or make the authentication filter pick the right IDP based on some criteria.

UPDATE

Current yaml configuration:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          idpone:
            identityprovider:
              entity-id: https://idpone.com
              sso-url: https://idpone.com
              verification: 
                credentials:
                - certificate-location: "classpath:saml/idpone.crt"
          idptwo:
            identityprovider:
              entity-id: https://idptwo.com
              sso-url: https://idptwo.com
              verification: 
                credentials:
                - certificate-location: "classpath:saml/idptwo.crt"
like image 959
ATrubka Avatar asked Mar 10 '20 21:03

ATrubka


People also ask

How does SAML assertion work?

SAML works by exchanging user information, such as logins, authentication state, identifiers, and other relevant attributes between the identity and service provider. As a result, it simplifies and secures the authentication process as the user only needs to log in once with a single set of authentication credentials.

What is spring SAML extension?

Spring SAML Extension allows seamless inclusion of SAML 2.0 Service Provider capabilities in Spring applications. All products supporting SAML 2.0 in Identity Provider mode (e.g. ADFS 2.0, Shibboleth, OpenAM/OpenSSO, Ping Federate, Okta) can be used to connect with Spring SAML Extension.


Video Answer


1 Answers

As of Spring Security 5.2, you can set up multiple IDPs via the RelyingPartyRegistrationRepository.

Each one looks something like this when using Spring Boot:

spring:
  security:
    saml2:
      relyingparty:
        registration:
          idpone:
            identityprovider:
              verification:
                credentials:
                  - certificate-location: "classpath:idpOne.crt"
              entity-id: https://idp.example.org
              sso-url: https://idp.example.org/SSOService.saml2
          idptwo:
            identityprovider:
              ...

Then, you can initiate an AuthNRequest for idpOne by naving to http://localhost:8080/saml2/authenticate/idpOne.

By Hostname

If you want to do it by hostname, then you can customize the /login page to know which of the /saml2/authenticate/{registrationId} endpoints to redirect to.

First, you'd tell Spring Security that you have a custom /login page, so it doesn't create one:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            .authorizeRequests(authz -> authz
                .mvcMatchers("/login").permitAll() // here
                .anyRequest().authenticated())
            .saml2Login(saml2 -> saml2.loginPage("/login")) // and here
    }

}

And then, you'd define it:

@Controller
public class LoginController {
    private final RelyingPartyRegistrationRepository relyingParties;

    // ... constructor

    @GetMapping("/login")
    public void login(HttpServletRequest request, HttpServletResponse response) {
        String registrationId = // ... derive from the host name
        RelyingPartyRegistration relyingParty = this.relyingParties
                .findByRegistrationId(registrationId);
        if (relyingParty == null) {
            response.setStatusCode(401);
        } else {
            response.sendRedirect("/saml2/authenticate/" + registrationId);
        }
    }
}

The reason for the lookup in the /login endpoint is to ensure that the registrationId supplied in the hostname is legitimate.

like image 185
jzheaux Avatar answered Oct 20 '22 00:10

jzheaux