Skip to content
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

Support for JWT Header TYP as "at+jwt" #9900

Open
tekgainers opened this issue Jun 11, 2021 · 13 comments
Open

Support for JWT Header TYP as "at+jwt" #9900

tekgainers opened this issue Jun 11, 2021 · 13 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement

Comments

@tekgainers
Copy link

Expected Behavior

Currently, if the JWT is having typ as "at+jwt", the token is rejected with message "Failed to authenticate since the JWT was invalid". Spring Security Oauth2 Resource Server with JWT as bearer token should accept typ as "at+jwt" as well.

Current Behavior

Currently, if the JWT is having typ as "at+jwt", the token is rejected with message "Failed to authenticate since the JWT was invalid".

My Authorization server is issuing JWT access token with typ as "at+jwt" as per the following draft: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-access-token-jwt-11

How has this issue affected you? JWT token is rejected although this is correct as per Authorization server
What are you trying to accomplish? Validate JWT Bearer token using Spring Security OAuth2 Resource Server capabilities.
What other alternatives have you considered? At this point, in the documentation I didn;t find a way where I can customize the JWT Validator. Although, documentation is around our own Audience or other validations once the JWT is accepted by Spring Security.
Are you aware of any workarounds? Not at this point of time.

@tekgainers tekgainers added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Jun 11, 2021
@tekgainers
Copy link
Author

@jzheaux can you please have a look if this is bug or this needs enhancement in library?

Thanks in advance.

@jzheaux
Copy link
Contributor

jzheaux commented Jul 6, 2021

The reason for this behavior is Nimbus defaults to checking that the typ is JWT. I am not certain whether Nimbus yet supports the at+jwt draft - Spring Security would likely rely on Nimbus for this kind of support.

To get your resource server to accept "typ" : "at+jwt", you can configure Nimbus like so:

@Bean 
JwtDecoder jwtDecoder() {
	DefaultJOSEObjectTypeVerifier<SecurityContext> verifier =
		new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("at+jwt"));
	NimbusJwtDecoder decoder = NimbusJwtDecoder.withJwkSetUri(this.uri)
		.jwtProcessorCustomizer((processor) -> processor.setJWSTypeVerifier(verifier))
		.build()
        // ... any other decoder settings
	return decoder;
}

For passivity reasons, I imagine that Spring Security will continue to use the Nimbus defaults. Once the draft gets finalized, there may be an opportunity to make this configuration simpler.

@jzheaux jzheaux closed this as completed Jul 6, 2021
@jzheaux jzheaux added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 6, 2021
@shartte
Copy link

shartte commented Apr 5, 2023

@jzheaux The draft has now been published as RFC 9068 (and I am running into this problem, thanks for the configuration hint, however :-))

@jzheaux jzheaux added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: declined A suggestion or change that we don't feel we should currently apply labels May 19, 2023
@jzheaux
Copy link
Contributor

jzheaux commented May 19, 2023

In light of a separate request from @ymajoros, I think it would be good to revisit this decision, now that the spec is finalized.

Allowing the at+jwt type is not sufficient to support RFC 9068. If an application allows at+jwt, it should also validate those tokens as per the at+jwt spec as well.

I think this would fit nicely into JwtValidators#createDefault and JwtValidators#createDefaultForIssuer:

@Bean 
JwtDecoder jwtDecoder() {
    NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation("http://issuer").build();
    jwtDecoder.setJwtValidator(JwtValidators.createDefaultForIssuer("http://issuer"));
    return jwtDecoder;
}

where these factory methods change to check the typ field first before deciding on what validation to perform. If it is at+jwt, then it performs the at+jwt validations; otherwise, it does what it has always done.

In this case, NimbusJwtDecoder sets JWSTypeVerifier such that at+jwt, jwt, and null are allowed by Nimbus.

This changes how at+jwt is processed by Spring Security; however, I would consider it a bug if an application is accepting at+jwt tokens today without also validating them.

@jzheaux jzheaux reopened this May 19, 2023
@ymajoros
Copy link

Thanks @jzheaux .
What about this pull request, which solves the problem IMO?
#13186

@jzheaux
Copy link
Contributor

jzheaux commented May 22, 2023

@ymajoros, thank you very much for the PR. I don't think that it should be in JwtDecoders, but NimbusJwtDecoder. Also, it is missing the needed validation. Please see my comment about what needs to be done to add this support.

@ymajoros
Copy link

ymajoros commented Jul 4, 2023

After spending some more time on it, I'm not convinced we can do more validation for now, according to RFC 9068 (at+jwt) and RFC 7519 (jwt):

  • if we strictly follow RFC 9068, we should only accept application/at+jwt or at+jwt (the latter being recommended)
  • besides the typ check already checked in this pull request, we should check:
    • iss, which we already do
    • signature, which we already do
    • exp, which we already do
    • aud, which we don't, but I suggest to keep this as a stricter option for later, as we should also check it for plain jwt anyway, according to RFC 7519

So, I think the current implementation is enough. I'd just add the optional application/ prefix.

@shartte
Copy link

shartte commented Jul 4, 2023

@ymajoros If it isn't already, I think it should be possible to configure the expected audience values. At least it wouldn't allow tokens leaked by one service (i.e. in a microservice architecture) to be successfully used against another service.

@ymajoros
Copy link

ymajoros commented Jul 4, 2023

@shartte true, but that seems out of scope for this issue and a different feature that should also be implemented, isn't it?

@ymajoros
Copy link

ymajoros commented Jul 12, 2023

@jzheaux can you look at it again in light of my previous comments?

@burl21
Copy link

burl21 commented Sep 5, 2023

Is there any update on "at+jwt" support ?

@daniel-susumu
Copy link

Is there any recommended workaround?

@bilalkais
Copy link

bilalkais commented Sep 11, 2024

Any updates on this one @jzheaux?

We've used the following workaround in our application:

  @Bean
  JwkSetUriJwtDecoderBuilderCustomizer jwkSetUriJwtDecoderBuilderCustomizer() {
    final var verifier = new DefaultJOSEObjectTypeVerifier<>(new JOSEObjectType("at+jwt"));
    return builder -> builder.jwtProcessorCustomizer((processor) -> processor.setJWSTypeVerifier(verifier));
  }

This approach works well when using either resourceserver.jwt.issuer-uri or resourceserver.jwt.jwk-set-uri, both of which rely on the jwkSetUriJwtDecoderBuilder. However, when using resourceserver.jwt.public-key-location, we don't have a way to customize the JWT processor without creating a completely new decoder. This is problematic as it leads to losing access to features like the audience validator, which would otherwise be provided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

7 participants