在多租户 stup 中使用 Spring Security OAuth 动态注册 OIDC 客户端

Posted

技术标签:

【中文标题】在多租户 stup 中使用 Spring Security OAuth 动态注册 OIDC 客户端【英文标题】:Dynamically register OIDC client with Spring Security OAuth in a multi-tenant stup 【发布时间】:2021-05-31 22:33:21 【问题描述】:

我正在构建一个多租户应用程序,它应该允许每个租户使用自己的 IAM 提供程序来进行用户身份验证。最后,例如,Tenant1 可以使用 Keycloak,Tenant2 可以使用 OneIdentity,Tenant3 可以使用它选择的任何 IAM 提供者......应用程序应该能够动态地(在运行时)注册一个新租户及其 IAM 提供者。我注册了具有ClientRegistrationRepository 的 OIDC 客户端,例如:

@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(), 

    );

但是,ClientRegistrationRepository 不提供更新客户端注册的方法。有没有办法在运行时引入新的客户端注册,Spring Security 会考虑到这一点?

【问题讨论】:

看看这些可以在运行时重新加载 bean 的方法:***.com/questions/51218086/… 【参考方案1】:

重定向到登录控制器中的 /oauth2/authorization/registrationId。

@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());


并覆盖 findByRegistrationId 方法,你可以根据需要更新 ClientRegistration。

@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();
    

【讨论】:

以上是关于在多租户 stup 中使用 Spring Security OAuth 动态注册 OIDC 客户端的主要内容,如果未能解决你的问题,请参考以下文章

Spring在多租户环境中为占位符配置application.properties

如何使用 Spring + Hibernate 对实体进行自定义验证以进行多租户设置

如何在多租户应用程序中更新所有租户的所有架构?

在多租户应用程序中如何检查应用程序在 Azure 门户中注册的租户数据?

在多租户 Hadoop 集群中管理 impala 资源的最佳方法是啥

是否有任何 PHP 框架(例如 CodeIgniter)支持基于每个用户帐户的数据库连接,以便在多租户数据库中使用?