Spring security 桌面OIDC Spring应用程序安全性:使用初始令牌配置客户端

Spring security 桌面OIDC Spring应用程序安全性:使用初始令牌配置客户端,spring-security,Spring Security,我们有一个JavaSpring桌面应用程序,我们现在正在将其迁移到一个OIDC安全性中(目前使用KeyClope)。 为此,我们在Java应用程序中集成了一个浏览器,以运行身份验证并获取所提供的令牌集(访问、刷新、id) 现在,我们希望将这些令牌与Spring安全性集成,以便我们可以在WebClient(调用服务器)上使用过滤器,并且Spring可以处理访问令牌刷新过程 我们正在努力找到实现这一目标的最佳途径 到目前为止,我们有一个解析访问和刷新令牌以生成授权客户端的解决方案。在这种情况下,我们

我们有一个JavaSpring桌面应用程序,我们现在正在将其迁移到一个OIDC安全性中(目前使用KeyClope)。 为此,我们在Java应用程序中集成了一个浏览器,以运行身份验证并获取所提供的令牌集(访问、刷新、id)

现在,我们希望将这些令牌与Spring安全性集成,以便我们可以在WebClient(调用服务器)上使用过滤器,并且Spring可以处理访问令牌刷新过程

我们正在努力找到实现这一目标的最佳途径

到目前为止,我们有一个解析访问和刷新令牌以生成授权客户端的解决方案。在这种情况下,我们将创建AuthorizedClientProvider,如下所示:

var authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
            .refreshToken()
            .provider(context -> {

                if (context.getAuthorizedClient() != null) {
                    return Mono.empty();
                }

                ObjectMapper objMapper = new ObjectMapper();

                TypeReference<Map<String, Object>> type = new TypeReference<Map<String, Object>>() {//
                };

                Map<String, Object> jsonMap = null;
                try {
                    jsonMap = objMapper.readValue(accessTokenValue, type);
                }
                catch (JsonProcessingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                AccessTokenResponse parsedAccessToken = null;
                try {
                    parsedAccessToken = (AccessTokenResponse) TokenResponse.parse(new JSONObject(jsonMap));
                }
                catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                OAuth2AccessTokenResponse accessTokenResponse = oauth2AccessTokenResponse(parsedAccessToken);

                return Mono.just(
                        new OAuth2AuthorizedClient(
                                context.getClientRegistration(),
                                context.getPrincipal().getName(),
                                accessTokenResponse.getAccessToken(),
                                accessTokenResponse.getRefreshToken()));
            })
            .build();
因此,尽管这种方法允许我们维护访问令牌(并刷新它),但它不允许我们使用这些令牌(在全局策略上)为应用程序创建身份验证。我希望能够使用ID令牌以某种方式生成它

我们已经看到,Spring在登录流(我们不使用)接收令牌时在内部创建了OAuth2AuthorizationCodeAuthenticationToken。 这看起来像是我们应该创建的身份验证对象,但它需要包含我们在用例中没有的消息交换信息。 然后我们可以看到,这个交换对象在Spring安全代码的更多地方使用,所以我们不能忽略它

我们还看到,在InMemoryReactivioAuth2AuthorizedClient服务中,我们有一个将OAuth2AuthorizedClient与身份验证对象关联的方法。 但我们不确定这是否是一条道路,或者究竟需要做些什么

我们是否应该使用适当的身份验证对象来保持对应用程序上令牌(ec:ID令牌)的引用

有人知道如何配置/提供此功能以使此集成浏览器解决方案正常工作吗

提前感谢您的帮助

问候


João

只是提醒一下,反应式OAuth 2.0客户机文档已经过时,并且缺少信息。我建议查看完整的Servlet文档。对于服务帐户(客户端证书授予),这里是Servlet文档。注意:为客户端\u凭据授权配置的客户端将不会收到刷新令牌(根据规范不允许)。但是,当访问令牌过期时,客户端将通过获取新的访问令牌来自动“续订”过期的访问令牌。您好,我已经阅读了文档,但在任何地方都没有提到在外部(集成浏览器)执行授权码时该怎么办,我们只有令牌。在12.2.4中提到setDefaultOAuth2AuthorizedClient(true),它将使用现有的OAuth2AuthenticationToken。有没有关于如何手动创建它而不是运行HttpSecurity.oauth2Login()的文档?如果缺省值不为true,那么在更新2中,我们将描述如何从检索到的令牌创建初始AuthorizedClient并维护refreshToken。不确定这是不是一个正确的方法。我不知道你所说的“当授权代码在外部(集成浏览器)执行时,我们只有令牌”是什么意思?这对我来说没有意义?另外,我也不清楚“是否有关于如何手动创建它而不是运行HttpSecurity.oauth2Login()的文档?”。手动创建什么?我很困惑,因为您最初的评论提到了服务帐户,即
client\u-credentials
grant和
HttpSecurity。oauth2Login()
是使用
authorization\u-code
grant实现的。因此,我尝试用当前的知识重新表述整个问题,并将重点放在开放点上@JoeGrandja,请检查第一句。我们在这个桌面应用程序上有一个集成的浏览器,它执行授权代码流并提供令牌。因此,我们试图了解如何将这些令牌与Spring安全性集成。目前,我们已经解决了如何联系服务器(并保持令牌刷新),但没有解决如何在桌面Spring应用程序中拥有全局身份验证对象。希望这能澄清整个问题。您可以通过GitHub存储库整理一个最小的示例->,这样我就可以看到您的内容了。这将是帮助您完成下一步工作的最有效方法。请注意,反应式OAuth 2.0客户端文档已经过时,并且缺少信息。我建议查看完整的Servlet文档。对于服务帐户(客户端证书授予),这里是Servlet文档。注意:为客户端\u凭据授权配置的客户端将不会收到刷新令牌(根据规范不允许)。但是,当访问令牌过期时,客户端将通过获取新的访问令牌来自动“续订”过期的访问令牌。您好,我已经阅读了文档,但在任何地方都没有提到在外部(集成浏览器)执行授权码时该怎么办,我们只有令牌。在12.2.4中提到setDefaultOAuth2AuthorizedClient(true),它将使用现有的OAuth2AuthenticationToken。有没有关于如何手动创建它而不是运行HttpSecurity.oauth2Login()的文档?如果缺省值不为true,那么在更新2中,我们将描述如何从检索到的令牌创建初始AuthorizedClient并维护refreshToken。不确定这是不是一个正确的方法。我不知道你所说的“当授权代码在外部(集成浏览器)执行时,我们只有令牌”是什么意思?这对我来说没有意义?另外,我也不清楚“是否有关于如何手动创建它而不是运行HttpSecurity.oauth2Login()的文档?”。手动创建什么?我很困惑,因为您最初的评论提到了服务帐户,它是
客户\ u凭证
授权和
Http
        String baseUrl = theOpts.getAuthServiceBaseUrl();
        if (baseUrl == null) {
            baseUrl = theOpts.getAuthServiceIssuerUrl();
        }

        clientRegistration = ClientRegistration.withRegistrationId(AUTHSERVICE_REGISTRATION_ID)
            .userNameAttributeName(IdTokenClaimNames.SUB)
            .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
            .clientAuthenticationMethod(ClientAuthenticationMethod.POST)
            .clientId("myClientId")
            .jwkSetUri(theAuthServiceIssuerUrl + OIDC_CERTS_ENDPOINT)
            .tokenUri(theAuthServiceIssuerUrl + OIDC_TOKEN_ENDPOINT)
            .build();

        ReactiveClientRegistrationRepository inMemoryReactiveClientRegistrationRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistration);

        ReactiveOAuth2AuthorizedClientService authorizedClientService = new InMemoryReactiveOAuth2AuthorizedClientService(inMemoryReactiveClientRegistrationRepository);

        AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                inMemoryReactiveClientRegistrationRepository,
                authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        ServerOAuth2AuthorizedClientExchangeFilterFunction oauthFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);

        oauthFilter.setDefaultOAuth2AuthorizedClient(true);
        oauthFilter.setDefaultClientRegistrationId(AUTHSERVICE_REGISTRATION_ID);
        return oauthFilter;