Guidance/Ideas multiple Identity Providers with Spring Security Vaadin Flow

Hi,
I have a Vaadin Flow (v23) application in which I have implemented Spring Security for Single Sign-On (SSO) functionality. This integration with Spring Security is working well.

Now, I need to support multiple Identity Providers (IdPs) in my application. The main use case is supporting multiple active directories, but the ability to log in using identity provider services like different Azure Active Directories, Google, Facebook, etc would also be great.

Here is a rough outline of the authentication flow I’m envisioning:

*If a Vaadin webpage or route requires authentication and there is no active session,
the user would be redirected to a page where they can select from a list of available Identity Providers (IdPs).
After selecting their preferred IdP, the user will then be navigated to the corresponding login page for that IdP.
The IdP would then provide a token back to the Vaadin application to authenticate the user.

The user’s preferred IdP would then be stored in a cookie or local storage to facilitate a seamless SSO experience in future sessions.
*

Is this flow even possible with a Vaadin/Spring Security application?

If so, some guidance on how to approach such implementation would be greatly appreciated.

Thank you for your time and assistance.

Yes it’s possible, what is the problem you have, where are you stuck?
I guess you’re not using the SSO Kit? (I think it’s working out the box with SSO Kit)

You are right vaadin Single Sign-On (SSO) Kit isn’t being utilized.
The current configuration is as follows, security is being handled through the use of Spring Security beans.

// 1.
There is a class that is extending WebSecurityConfigurerAdapter. I am aware of VaadinWebSecurity, but it’s not being utilized in this setup.
SecurityConfig class extending WebSecurityConfigurerAdapter (
{ // customise http security.
}

// 2 and set up a single OAuth2 Client ID

@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(cognitoClientRegistration());
}

private ClientRegistration cognitoClientRegistration() {
    return ClientRegistration.withRegistrationId("cognito").clientId(clientid)
            .clientSecret("")// client secret is not set for authorization flow.
            .clientAuthenticationMethod(ClientAuthenticationMethod.POST)
            .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
            .redirectUri(redirectURL).scope(scopes)
            .authorizationUri(authorizationUri)
            .tokenUri(cognitoTokenUrl)
            .jwkSetUri(jwkSetUri)
            .clientName(clientName)
            .build();

}

I am wondering if I register another OAuth2 Client ID, how do i configure vaadin application to
display login page with two clients. At the moment it does not display any login page, it just redirects to cognito(active directory) login page.

I’m always using the configuration with the yml file ( and you can use multiple providers). I guess you can do the same with the code, you should check the spring boot documentation since it’s mainly an issue with spring boot: Core Configuration :: Spring Security

You can also store the configurations for an IdP in the database and dynamically add and remove them. The ClientRegistrationRepository is a good place to implement this

thanks @bonny-elephant It seems like a good potential solution worth exploring.

“You can also store the configurations for an IdP in the database and dynamically add and remove them. The ClientRegistrationRepository is a good place to implement this”

thanks @faithful-emu. I agree that this question is more relevant for Spring Security.

However, I’m curious if you have any insights on building the UI for the selection of an IDP.

If I add multiple IDPs, Spring Security should, by default, display an IDP selection screen. I’m wondering how I can override this screen from Spring Security to allow the user to select an IDP.

I assume it would look something like this.
setLoginView(http, SelectIDP.class); ? SelectIDP would be new vaadin component here.

Your assumption is correct. In there you iterate over the IDPs and create links with router-ignore=true and are done

Many thanks @quirky-zebra

One quick question. I presume that we can use cookies or local storage to store the chosen Identity Provider (IDP)
if a user indicates their preference for the application to remember IDP selection.

How does SelectIDP compoenent avoid showing the list of IDPs in case the prefrence is set?

Would something like this work? Or is there any better way to do it?

@Route(“login”)
public class SelectIDP extends Div implements BeforeEnterObserver {

private String preferredIdp;

public SelectIDP() {
    // Retrieve the preferred IDP from storage (cookie or local storage)
    this.preferredIdp = ... // implement method to retrieve the stored IDP
}

@Override
public void beforeEnter(BeforeEnterEvent event) {
    if (...preferredIdp is set ) {
        // If IDP is found and it's available, redirect to it
       //  event.forwardTo(preferredIdp);
    } else {
        // Otherwise, display the list of IDPs
        // along with a rememeber me checkbox.
        
        displayIdpList();
    }
}

}

I would personally handle that earlier, e.g. with a spring security filter. But it should be possible like this, even tho I think that forwardTo does not take a string… so you probably have to call page set location instead

thanks again @quirky-zebra, you are right I probably have to use something like this, I will look it up on vaadin docs.

// pseudo code: assuming set location supports avoiding vaadin router.
Page page = event.getLocation().getPage();
page.setLocation(preferredIdpUrl);