Reputation: 11
Trying to upgrade existing resource services from Spring Boot 1.x to 2.x. Spring Security 4.5 is running on the authentication server and encodes JWT tokens like this:
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
converter.setVerifierKey(publicKey);
return converter;
}
A resource server upgraded to Spring Boot 2.1.3.RELEASE throws this error:
OAuth2AuthenticationProcessingFilter:165 :
Authentication request failed: error="invalid_token",
error_description="Invalid access token:****..."
The log reveals that the OAuth2AuthenticationProcessingFilter is using the MappingJackson2HttpMessageConverter to extract the JWT token. Spring Security auto-configuration should provide the JwtAccessTokenConverter bean instead of the MappingJackson2HttpMessageConverter bean since there is a key-value in my properties file:
security:
oauth2:
resource:
jwt:
key-value: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
Here is the Spring Security ResourceServerTokenServiceConfiguration class that should detect it. The property matches "security.oauth2.resource.jwt.key-value".
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth JWT Condition");
Environment environment = context.getEnvironment();
String keyValue = environment
.getProperty("security.oauth2.resource.jwt.key-value");
String keyUri = environment
.getProperty("security.oauth2.resource.jwt.key-uri");
if (StringUtils.hasText(keyValue) || StringUtils.hasText(keyUri)) {
return ConditionOutcome
.match(message.foundExactly("provided public key"));
}
return ConditionOutcome
.noMatch(message.didNotFind("provided public key").atAll());
}
These are the resource server security dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
This is the resource server configuration. It is essentially the same as it was with Spring Boot 1.5.x.
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my-service";
@Override
public void configure(final HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
}
What am I missing?
Upvotes: 0
Views: 2476
Reputation: 90
The problem was an issue with the properties. I had moved "security.oauth2" to "spring.security.oauth2." When I turned on logging for org.springframework.boot.autoconfigure.security.oauth2 and saw this:
did not match due to OAuth Client ID did not find security.oauth2.client.client-id property
So, I decided to try moving the oauth2 properties back out from under "spring." and it was able to extract the JWT token.
Upvotes: 0