Reputation: 11
I have a Spring Boot + Keycloak project and I found out that the Spring Boot does not validate the JWT with the keycloak. For example if I get a token from Keycloak and turn off the Keycloak, I still can use this JWT token to access my end points. I have this security configurer class:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
@RequiredArgsConstructor
public class KeycloakSecurityConfigurer extends WebSecurityConfigurerAdapter {
private final RoleConverter converter;
@Value("${spring.security.oauth2.keycloak.jwt.issuer-uri}")
private String issuerUri;
@Override
public void configure(final HttpSecurity http) throws Exception {
http.headers().frameOptions().disable()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.oauth2ResourceServer(
oauth2ResourceServer -> oauth2ResourceServer.jwt(
jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())));
http.authorizeRequests().antMatchers("/**").authenticated();
}
private Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter() {
JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
return jwtConverter;
}
@Bean
public JwtDecoder jwtDecoder() {
return JwtDecoders.fromOidcIssuerLocation(issuerUri);
}
}
The "converter" is nothing special, just extracts the roles out of JWT token and returns a list of them.
How to force the Spring Security to validate the JWT token?
application.yml:
spring:
security:
oauth2:
keycloak:
jwt:
issuer-uri: http://localhost:8180/auth/realms/test-realm
Upvotes: 0
Views: 4081
Reputation: 12322
JWTs are meant to be validated offline, and it is what usually happens. The receiving application (consumer of JWT), does not need constant access to the Authorization Server in order to be able to validate a JWT. Even though Spring can't talk to your Keycloak, it does not mean that tokens are not validated. As others pointed out, Spring caches the keys used to validate JWTs' signature and will use the cache if it can.
If, for some reason, you want your service / API to validate the JWT online (maybe because you want to implement a mechanism to revoke tokens), you could switch to using opaque tokens with Token Introspection. On every request your service will have to call Keycloak to exchange the opaque token for a JWT. Mind that this solution will use much more resources, and you should use it only if you have strong reasons for it.
Upvotes: 0
Reputation: 140
The JWT tokens are been cached in your springboot application, this is the default cache store. In order to delete this token from your springboot app use should use some custom caches like redis cache to be configured in your app instead of default. There is no possible way to delete the tokens stored in default caches. The token will automatically get invalidate only after the timeout that's been set inside token
Upvotes: 0
Reputation: 6238
You can look at the implementation of JwtDecoders.fromOidcIssuerLocation(issuerUri)
.
What is happening is that the keys are being fetched at the startup of your application and the application caches them in order to perform the validation after. With this in mind, even if you turn off Keycloak the JWT will still be validated because the keys are still cached.
Upvotes: 1