Oath2 with Client Credentialsフローを使用して、Spring Bootでマイクロサービスを保護しようとしています。
ちなみに、これらのマイクロサービスはミドルウェア層を介してのみ相互に通信します。つまり、認証を許可するためにユーザー資格情報は必要ありません(Facebookとしてのユーザーログインプロセス)。
この通信を管理するための承認およびリソースサーバーの作成方法を示すサンプルをインターネットで探しました。ただし、ユーザー資格情報(3つのレッグ)を使用してそれを行う方法を説明する例を見つけました。
Spring BootとOauth2でそれを行う方法のサンプルはありますか?使用できるスコープの詳細を提供できる場合は、トークンの交換に感謝します。
REST Oauth2 Client資格情報スキームで保護されたサービス。リソースと承認サービスは同じアプリで実行されていますが、異なるアプリに分割できます。
@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);
}
}
}
Oauth2テーブルのデータソース設定:
@Bean(name = "OAuth")
@ConfigurationProperties(prefix="datasource.oauth")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
認証およびリソースサーバーとの通信は次のようになります
curl -H "Accept: application/json" user:password@localhost:8080/oauth/token -d grant_type=client_credentials
curl -H "Authorization: Bearer token" localhost:8080/...
Oauth2データベースには次のレコードが存在します。
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
@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;
}
}
RestTemplateを挿入して、Oauth2のセキュリティで保護されたサービスと(非同期で)通信できます。現時点ではスコープを使用しません。