Spring Boot + Oauth2 client credentials

前端 未结 1 2062
予麋鹿
予麋鹿 2020-12-04 12:46

I am trying to protect my microservices on Spring Boot using Oath2 with Client Credentials flow.

By the way, those microservices will only talk each other over the

相关标签:
1条回答
  • 2020-12-04 13:21

    We have REST services protected with Oauth2 Client credentials scheme. The Resource and authorization service are running in the same app, but can be split into different apps.

    @Configuration
    public class SecurityConfig {
    
    @Configuration
    @EnableResourceServer
    protected static class ResourceServer extends ResourceServerConfigurerAdapter {
    
        // Identifies this resource server. Usefull if the AuthorisationServer authorises multiple Resource servers
        private static final String RESOURCE_ID = "*****";
    
        @Resource(name = "OAuth")
        @Autowired
        DataSource dataSource;
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http    
                    .authorizeRequests().anyRequest().authenticated();
            // @formatter:on
        }
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId(RESOURCE_ID);
            resources.tokenStore(tokenStore());
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
    }
    
    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    
        @Resource(name = "OAuth")
        @Autowired
        DataSource dataSource;
    
        @Bean
        public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenStore(tokenStore());
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource);
        }
    }
    }
    

    Datasource config for the Oauth2 tables:

    @Bean(name = "OAuth")
    @ConfigurationProperties(prefix="datasource.oauth")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    

    Communicating with authentication & resource server goes as followed

    curl -H "Accept: application/json" user:password@localhost:8080/oauth/token -d grant_type=client_credentials
    curl -H "Authorization: Bearer token" localhost:8080/...
    

    The following record is present in the Oauth2 Database:

    client_id  resource_ids  client_secret  scope  authorized_grant_types   web_server_redirect_uri  authorities  access_token_validity refresh_token_validity  additional_information  autoapprove
    user  ****  password  NULL  client_credentials  NULL  X  NULL  NULL  NULL  NULL
    

    Resttemplate configuration in client application

    @Configuration
    @EnableOAuth2Client
    public class OAuthConfig {
    
    @Value("${OAuth2ClientId}")
    private String oAuth2ClientId;
    
    @Value("${OAuth2ClientSecret}")
    private String oAuth2ClientSecret;
    
    @Value("${Oauth2AccesTokenUri}")
    private String accessTokenUri;
    
    @Bean
    public RestTemplate oAuthRestTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setId("1");
        resourceDetails.setClientId(oAuth2ClientId);
        resourceDetails.setClientSecret(oAuth2ClientSecret);
        resourceDetails.setAccessTokenUri(accessTokenUri);
    
        /*
    
        When using @EnableOAuth2Client spring creates a OAuth2ClientContext for us:
    
        "The OAuth2ClientContext is placed (for you) in session scope to keep the state for different users separate.
        Without that you would have to manage the equivalent data structure yourself on the server,
        mapping incoming requests to users, and associating each user with a separate instance of the OAuth2ClientContext."
        (http://projects.spring.io/spring-security-oauth/docs/oauth2.html#client-configuration)
    
        Internally the SessionScope works with a threadlocal to store variables, hence a new thread cannot access those.
        Therefore we can not use @Async
    
        Solution: create a new OAuth2ClientContext that has no scope.
        *Note: this is only safe when using client_credentials as OAuth grant type!
    
         */
    
    //        OAuth2RestTemplate restTemplate = new      OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, new DefaultOAuth2ClientContext());
    
        return restTemplate;
    }
    }
    

    You can inject the restTemplate to talk (Asynchronously) to the Oauth2 secured service. We do not use scope at the moment.

    0 讨论(0)
提交回复
热议问题