OAuth2采用非对称方法

huangapple go评论75阅读模式
英文:

OAuth2 with Asymmetric Approache

问题

我已经使用 Spring Cloud OAuth2 实现了一个资源服务器和授权服务器。当我使用默认方法实现 OAuth 应用程序(而不使用非对称或对称方法)时,授权服务器会生成默认令牌。当我需要与资源服务器和授权服务器通信时,可以在资源服务器配置文件中使用以下属性。

resource-server.yml 默认配置

security:
  oauth2:
    client:
      client-id: web
      client-secret: *****
    resource:
      token-info-uri: "http://localhost:9092/oauth/check_token"

当我在授权服务器中使用非对称方法使用私钥对令牌进行签名,并在资源服务器中使用公钥验证令牌时,使用以下属性 security:jwt:public-key: classpath:public.txt 调用资源服务器时出现以下未经授权的响应。

resource-server.yml 使用非对称方法配置

security:
  jwt:
    public-key: classpath:public.txt

API Endpoint

http://localhost:9090/user?Authorization=bearer **********

响应

{
  "error": "invalid_token",
  "error_description": "Cannot convert access token to JSON"
}

注意 - 当我在 resource-server.yml 中的非对称方法中使用 clienttoken-info-uri 属性时,会出现以下错误。

Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
	- tokenServices: defined by method 'tokenServices' in class path resource [com/benz/resource/api/config/ResourceServerConfiguration.class]
	- remoteTokenServices: defined by method 'remoteTokenServices' in class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration.

我需要澄清以下问题:

  1. 在不使用 token-info-uriclient 属性的情况下,资源服务器如何识别特定的授权服务器?

  2. 为什么会发生未经授权的错误(如上所述)?

ResourceServerConfig 类

@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${security.jwt.public-key}")
    private Resource publicKey;

    private TokenStore tokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(tokenStore());
    }

    @Bean
    public DefaultTokenServices tokenServices(TokenStore tokenStore) {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore);
        return tokenServices;
    }

    @Bean
    public TokenStore tokenStore() throws Exception {
        if (tokenStore == null)
            tokenStore = new JwtTokenStore(tokenConverter());

        return tokenStore;
    }

    private JwtAccessTokenConverter tokenConverter() throws Exception {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey(getPublicKeyAsString());
        return converter;
    }

    private String getPublicKeyAsString() throws Exception {
        return IOUtils.toString(publicKey.getInputStream(), StandardCharsets.UTF_8);
    }
}

GitHub 链接

resource-server-implementation

authorization-server-implementation

如果需要更多细节,请提出评论,我将进行更新。

英文:

I have implemented a resource server and authorization server with spring cloud oauth2. When I implemented the OAuth application by using the default approach (without using asymmetric or symmetric approach) then the default token is generated by the authorization server and when I have to communicate with the resource server and the authorization server then the following properties can be used in the resource server config file.

resource-server.yml with default

security:
  oauth2:
    client:
      client-id: web
      client-secret: *****
    resource:
      token-info-uri: "http://localhost:9092/oauth/check_token"

When I use an asymmetric approach to sign the token with the private key in the authorization server and use the public key to validate the token in the resource server with the following property security:jwt:public-key: classpath:public.txt then the following unauthorized response has occurred when I call the resource from the resource server.

resource-server.yml with asymmetric

security:
  jwt:
    public-key: classpath:public.txt

API Endpoint

http://localhost:9090/user?Authorization=bearer **********

Response

{
"error": "invalid_token",
"error_description": "Cannot convert access token to JSON"
}

Note - when I use client and token-info-uri properties with an asymmetric approach in the resource-server.yml then the following error has occurred.

Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
	- tokenServices: defined by method 'tokenServices' in class path resource [com/benz/resource/api/config/ResourceServerConfiguration.class]
	- remoteTokenServices: defined by method 'remoteTokenServices' in class path resource [org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration.

I have to clarify the following question

  1. Without using token-info-uri and client properties how does the resource server identify the particular authorization server?.

  2. why does the unauthorized error has occurred (which is mentioned in the above)?

ResourceServerConfig class

@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${security.jwt.public-key}")
    private Resource publicKey;

    private TokenStore tokenStore;


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(tokenStore());
    }

    @Bean
    public DefaultTokenServices tokenServices(TokenStore tokenStore)
    {
        DefaultTokenServices tokenServices=new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore);
        return tokenServices;
    }

    @Bean
    public TokenStore tokenStore() throws Exception
    {
        if(tokenStore==null)
            tokenStore=new JwtTokenStore(tokenConverter());

        return tokenStore;
    }

    private JwtAccessTokenConverter tokenConverter() throws Exception
    {
        JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
        converter.setVerifierKey(getPublicKeyAsString());
        return converter;
    }


    private String getPublicKeyAsString() throws Exception
    {
        return IOUtils.toString(publicKey.getInputStream(),UTF_8);
    }
}

Github link for

resource-server-implementation

authorization-server-implemetation

If you need more details please comment it then I can update

答案1

得分: 1

我已经解决了这个问题。在我的情况下,tokenConverter 方法是在创建 JwtTokenStore bean 实例时被调用的。我已经改变了创建 JwtAccessTokenConverter bean 实例的方法,通过添加 @Bean 注解来单独创建它。在这种情况下,它可以在没有任何中断的情况下正常工作。

@Bean
public JwtAccessTokenConverter tokenConverter() throws Exception
{
    JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
    converter.setVerifierKey(getPublicKeyAsString());
    return converter;
}
英文:

I have solved the issue. In my case, tokenConverter method is called at the time of JwtTokenStore bean instance created. I have changed the approach to create the bean instance for JwtAccessTokenConverter separately by adding @Bean annotation. In that case, it is worked without any interruption.

    @Bean
    public JwtAccessTokenConverter tokenConverter() throws Exception
    {
        JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
        converter.setVerifierKey(getPublicKeyAsString());
        return converter;
    }

huangapple
  • 本文由 发表于 2020年10月25日 15:56:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/64521548.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定