1

I am building a multi-tenant application which should enable each tenant to use its own IAM provider for the purpose of users authentication. So finally, for example, Tenant1 can use Keycloak, Tenant2 can use OneIdentity, Tenant3 any IAM provider of its choice... The application should enable registering a new tenant together with its IAM provider dynamically (at runtime). I register the OIDC clients having a ClientRegistrationRepository, like:

@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
    return new InMemoryClientRegistrationRepository(
               
            ClientRegistrations.fromIssuerLocation("iam-provider-1-issuer-location")
                    .registrationId("registration-id")
                    .clientId("client-id")
                    .clientSecret("client-secret")
                    .build(), 

            ClientRegistrations.fromIssuerLocation("iam-provider-2-issuer-location")
                    .registrationId("registration-id")
                    .clientId("client-id")
                    .clientSecret("client-secret")
                    .build(), 

    );
}

But, the ClientRegistrationRepository doesn't provide a way to update the client registrations. Is there a way to introduce a new client registration at runtime which will be taken into consideration from Spring Security?

Christina
  • 361
  • 1
  • 5
  • 17
  • 1
    Have a look at these methods which can reload a bean at runtime: https://stackoverflow.com/questions/51218086/how-to-reinitialize-a-spring-bean/51218781 – Michal Trojanowski Mar 02 '21 at 13:52

1 Answers1

2

Redirect to /oauth2/authorization/{registrationId} in the login controller.

@GetMapping(path = "/login")
public String defaultLogin(HttpServletRequest request) {
    String domainName = request.getServerName();
    Tenant tenant = tenantService.findByDomainName(domainName);
    return String.format("redirect:/oauth2/authorization/%s", tenant.getId());

}

And override findByRegistrationId method, and you can update ClientRegistration as you want.

@Override
public ClientRegistration findByRegistrationId(String registrationId) {

    Tenant tenant = tenantService.findById(registrationId);

    return ClientRegistration.withRegistrationId(registrationId)
       .clientId(tenant.getClientId())
       .clientSecret(tenant.getClientSecret())
       .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
       .redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
       .scope("openid", "profile", "email")
       .clientName(registrationId)
       .authorizationUri(String.format("https://%s/authorize", tenant.getAuthProviderDomain()))
       .tokenUri(String.format("https://%s/oauth/token", tenant.getAuthProviderDomain()))
       .userInfoUri(String.format("https://%s/userinfo", tenant.getAuthProviderDomain()))
       .jwkSetUri(String.format("https://%s/.well-known/jwks.json", tenant.getAuthProviderDomain()))
       .userNameAttributeName("name")
       .build();
    }
h-okhs
  • 44
  • 4