JWTトークンとOAuth2プロトコルを使用するSpringアプリケーションを構築しようとしています。 このチュートリアル のおかげで認証サーバーを実行しています。ただし、リソースサーバーを正しく機能させるのに苦労しています。記事をフォローすることから、そして 前の質問 への応答のおかげで、これは私の現在の試みです:
リソースサーバーのセキュリティ構成:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${security.signing-key}")
private String signingKey;
@Value("${security.encoding-strength}")
private Integer clientID;
@Value("${security.security-realm}")
private String securityRealm;
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setVerifierKey(signingKey);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean ResourceServerTokenServices tokenService() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
@Override
public AuthenticationManager authenticationManager() throws Exception {
OAuth2AuthenticationManager authManager = new OAuth2AuthenticationManager();
authManager.setTokenServices(tokenService());
return authManager;
}
}
リソースサーバーの構成:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private ResourceServerTokenServices tokenServices;
@Value("${security.jwt.resource-ids}")
private String resourceIds;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceIds).tokenServices(tokenServices);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().and().authorizeRequests().antMatchers("/actuator/**", "/api-docs/**").permitAll()
.antMatchers("/**").authenticated();
}
}
Authorization Serverのセキュリティ構成(上記のチュートリアルから):
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${security.signing-key}")
private String signingKey;
@Value("${security.encoding-strength}")
private Integer encodingStrength;
@Value("${security.security-realm}")
private String securityRealm;
@Autowired
private UserDetailsService userDetailsService;
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new ShaPasswordEncoder(encodingStrength));
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName(securityRealm)
.and()
.csrf()
.disable();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
@Primary //Making this primary to avoid any accidental duplication with another token service instance of the same name
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
これで、リソースサーバーにリクエストを送信しようとすると、次のようなエラーが表示されます。
{"error":"invalid_token","error_description":"Invalid access token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsidGVzdGp3dHJlc291cmNlaWQiXSwidXNlcl9uYW1lIjoiam9obi5kb2UiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwiZXh wIjoxNTE1MTE3NTU4LCJhdXRob3JpdGllcyI6WyJTVEFOREFSRF"}
いくつか質問があります。
security.oauth2.resource.token-info-uri=http://localhost:8080/oauth/check_token
。ただし、Resource Serverでキーに依存しないようにしようとすると、ResourceServerTokenServiceの設定で問題が発生します。サービスはトークンストアを想定しており、JWTTokenStoreはJwtAccessTokenConverterを使用し、コンバーターはキーを使用します(キーを削除すると同じinvalid token
以前に経験したエラー)。AuthサーバーとResourceサーバーを分離する方法を示す記事を見つけるのに本当に苦労しています。何かアドバイスをいただければ幸いです。
編集:実際には、リソースサーバーのコードは次のメッセージでコンパイルに失敗しています:
Caused by: Java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
Spring oauthを試しましたが、同じエラーが発生しました:
Caused by: Java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
私の間違いは、私の公開証明書が次のとおりだったということでした:
-----BEGIN PUBLIC KEY-----
tadadada
-----END PUBLIC KEY-----
-----BEGIN CERTIFICATE-----
tadadada
-----END CERTIFICATE-----
そして、これは許可されていません。証明書を削除します。このファイルに公開鍵を入れてください。
-----BEGIN PUBLIC KEY-----
tadadada
-----END PUBLIC KEY-----
そして、起動エラーは消えます。
あなたの2番目の質問については、それが私が理解していることです:
認証サーバーは、ユーザーのすべてのアクセス許可を含む暗号化されたトークン(秘密鍵で暗号化された)を提供します。
リソースサーバーは公開鍵を使用してトークンを復号化し、トークンに含まれるアクセス許可がTRUEであると想定します。
この助けを願っています。
公開鍵が次のようにフォーマットされているときに、この問題が発生しました。
"-----BEGIN RSA PUBLIC KEY-----\n${encoder.encodeToString(keyPair.public.encoded)}\n-----END RSA PUBLIC KEY-----\n"
これを次のように変更したとき:
"-----BEGIN PUBLIC KEY-----\n${encoder.encodeToString(keyPair.public.encoded)}\n-----END PUBLIC KEY-----\n"
キーが受け入れられました。