spring - OAuth2RestTemplate 承载 token 类型

标签 spring spring-security oauth oauth-2.0

我使用 Spring Security OAuth2 和 OAuth2RestTemplate 来实现 OAuth 2.0 安全 REST API 的客户端。该流程经历了成功获取访问 token 的步骤:

response.statusCode = 200
response.body = {"access_token":"9b90f8a84b939b8437a4fbaa8fff0052839cf6f5","expires_in":3600,"token_type":"bearer","scope":" read write","refresh_token":"e164f317a1708c3664025e9e56ce605cfe710474”}

但是,当代码尝试使用 OAuth2RestTemplate 访问 protected 资源时,响应不成功:

GET request for "https://redacted.com/api/v1/clients" resulted in 400 (Bad Request)

这是因为 DefaultOAuth2RequestAuthenticator 使用随 access_token 返回的 token_type 值(“承载者”)来形成对 protected 资源的请求的身份验证 header :

request.getHeaders().set("Authorization", String.format("%s %s", tokenType, accessToken.getValue()));

这会导致请求授权 header 中的凭据字段以字符串“bearer”为前缀:

Request Header: "Authorization" "bearer a8f18cb3173c4cbbea44f4495dd5e5662156c391"

但是,根据 OAuth 2.0 承载 token 使用规范第 2.1 节授权请求 header 字段,凭据字段的格式为:

credentials = "Bearer" 1*SP b64token

请注意,在规范中,“Bearer”是大写的。这意味着请求 header 应该是:

Request Header: "Authorization" "Bearer a8f18cb3173c4cbbea44f4495dd5e5662156c391"

显然,我们发送请求的提供商严格执行了规范,因为大写问题(“bearer”与“Bearer”)是导致对 protected 资源的请求失败的原因。当我更改 DefaultOAuth2RequestAuthenticator 以将前缀强制为标题大小写时,请求成功:

if ("bearer".equals(tokenType)) {
    tokenType = "Bearer";
}

Header key = Authorization values = Bearer 8efd4381f3470660291e700e4927012f288ad66c,
Sending GET request to https://redacted.com/api/v1/clients
Received "200 OK" response for GET request to https://redacted.com/api/v1/clients: [[{"id":"999999999","client_user_id":"a1b2c3d4e5f6"...

我真的不想用自己的 Spring Security OAuth2 分支来解决这个问题。这对任何人来说效果如何?我错过了什么吗?

最佳答案

我通过这些代码解决了这个问题

    @Bean
public OAuth2RestOperations restTemplate(){

    AccessTokenRequest accessTokenRequest = new DefaultAccessTokenRequest();
    OAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext(accessTokenRequest);
    OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate( resource(),oAuth2ClientContext );
    oAuth2RestTemplate.setAuthenticator(new DefaultOAuth2RequestAuthenticator(){
        @Override
        public void authenticate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext clientContext, ClientHttpRequest request) {
            clientContext.setAccessToken(new DefaultOAuth2AccessToken(clientContext.getAccessToken()){
                @Override
                public String getTokenType() {
                    if ("bearer".equals(super.getTokenType())) {
                        return "Bearer";
                    }
                    return super.getTokenType();
                }
            });
            OAuth2AccessToken accessToken = clientContext.getAccessToken();
            super.authenticate(resource, clientContext, request);
        }
    });

关于spring - OAuth2RestTemplate 承载 token 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45472510/

相关文章:

java - 如何为配置了 Spring Security 的 Spring Boot API 编写单元测试

c# - 作为提供者实现 Oauth

java - 如何使用 Spring Boot 设置 JSESSIONID cookie 的过期日期时间

azure - 我们可以使用 OAuth 将数据放入 Azure 事件中心吗

oauth - token 返回后,Google 和帐户关联失败的操作

java - BCrypt:有没有办法在数据库中插入已经加密的密码?

spring - 为用户 Keycloak Admin Client 分配角色

java - 没有这样的 bean 定义并且不可能创建 bean

java - Spring @Transactional 配置 xml

Spring Boot 错误 : Error creating bean with name