-
Notifications
You must be signed in to change notification settings - Fork 6k
oauth2ResourceServer JWT revocation built-in support #10558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @ah1508, thanks for the detailed suggestion. I could see something like this being useful for folks, but I have a couple of thoughts for discussion. First, are there any specifications that could be used to guide the feature development in the right direction? It would be very helpful to the process if you've found and could present specifics from any RFCs that address this. Second, it would be nice if this enhancement could be narrowed down to a specific starting point, perhaps introducing a |
More readable version of what can be done today : @Bean
WebSecurityConfigurerAdapter securityConfigurerAdapter(){
return new WebSecurityConfigurerAdapter() {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.oauth2ResourceServer(cust -> {
cust.jwt();
});
http.csrf().disable();
}
};
}
private Set<String> revoked = new HashSet<>();
// omitted : revocation endpoint, scheduled removal of expired tokens
@Bean
JwtDecoder jwtDecoder(@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") String issuer) {
OAuth2TokenValidator<Jwt> issuerValidator = JwtValidators.createDefaultWithIssuer(issuer);
// audience validator omitted here
OAuth2TokenValidator<Jwt> revocationValidator = jwt -> {
if(this.revoked.contains(jwt.getTokenValue())) {
var error = new OAuth2Error(OAuth2ErrorCodes.INVALID_TOKEN, "The token is revoked", "https://tools.ietf.org/html/rfc6750#section-3.1");
return OAuth2TokenValidatorResult.failure(error);
}
return OAuth2TokenValidatorResult.success();
};
OAuth2TokenValidator<Jwt> validator = new DelegatingOAuth2TokenValidator<>(issuerValidator, revocationValidator /*+ audience validator*/);
NimbusJwtDecoder jwtDecoder = (NimbusJwtDecoder) JwtDecoders.fromOidcIssuerLocation(issuer);
jwtDecoder.setJwtValidator(validator);
return jwtDecoder;
} |
@sjohnr : I missed your previous post. https://datatracker.ietf.org/doc/html/rfc6750#section-3.1 mentions "revoked token" so the response if token is revoked can be standard (401 with WWW-Authenticated header, I updated my first post). But revocation propagation from OIDC server to APIs that trust tokens issued by the OIDC server is not covered (or maybe I missed something). I see at least two points : self registration of the revocation endpoint by the API on the OIDC server, structure of the payload when this endpoint is called. In my example the payload is just a raw string. This article https://auth0.com/blog/denylist-json-web-token-api-keys/ covers JWT deny list. Without spec I cannot see how self registration can be implemented, but at least spring security could be "passive" : expose a endpoint and it is the developer responsibility to :
The token extraction from the payload is still and issue, a json path could be given by the developer and if a standard appears latter Spring Security could declare a default value for this json path. |
Thanks for the explanation @ah1508. I agree that without a spec, the issues you outlined are problematic for an implementation. Yet I further see a problem with even defining such an endpoint to be provided by Spring Security, with no spec or standard guiding how exactly it is protected, what the payload is, how it works, etc. In essence, it seems that it would be almost entirely custom code and configuration holding it all together, so I'm not sure what benefit there is for Spring Security to provide it. I could see value in the framework providing an implementation that handles some of the boilerplate, such as delegating to a specific component for making the revocation decision, possibly raising a particular type of error when a token is used after being revoked, perhaps making it easier to include that in JWT validation (as in your code sample above), etc. Beyond that, I wonder if anyone else in the community feels that it would be extremely beneficial for the framework to provide the endpoint. Can you point to other vendors or frameworks providing such an endpoint on the resource server side? |
Even if is a common use case, it seems to be ignored, for instance neither quarkus or asp.net have built-in support for that. It is a security hole, if I am notified that my account is used by someone else, all the tokens must be revoked as soon as I change my password. These tokens must be denied by all APIs that thrust the token issuer. A few minutes is enough to do a lot of damages. About the lack of spec : indeed it is problematic, but even with a spec the RBAC for this endpoint would be configurable. Something like
Then it would be developer's responsability to configure the OIDC server so the endpoint can be called with the appropriate roles. Maybe it could be done during the subscription, which would mean "oidc server, when you call my revocation endpoint your request must use a bearer token that carries these roles". Fortunatelly Spring security would just have to check if the token used to call the revocation endpoint carries the required roles. For the paylod structure : without spec it must indeed be configured by the developper :
but if a spec appears the setting would become deprecated. |
Hi @ah1508, I'm just circling back to some older issues and recalled our conversation above. Your conversation and feedback is really helpful and appreciated! However, I'm not seeing anything specific that we can address with this issue as it stands currently largely due to the lack of a specification that addresses it, though there are a lot of ideas that could be used for more specific suggestions. I'm going to close the issue with that in mind, but we can continue to discuss this as long as you want and if anything exciting comes up we can either re-open or open a new more specific issue. |
Dear all,
JWT revocation can be implemented manually with a publish/subscribe : a revocation event is sent (payload is the token to revoke) and subscribers (API that may receive this token and must reject it) receive this event so they can keep an up to date revocation list. Elements are automatically removed when
exp
is beforeInstant.now()
A built-in support for publish/subscribe could be a part of the in-development spring oidc server.
But on the spring security side, as far as I know it must be coded manually. Example (TTL omitted) :
How about a built-in support in spring Security ?
If the revocation endpoint and the revocations set are declared manually the configuration would looks like :
If the revocation endpoint is built-in, like an actuator :
With a customizer :
and configuration properties would allow to configure revocation endpoint path and RBAC for this endpoint (exemple :
hasRole('admin')
).The text was updated successfully, but these errors were encountered: