-
Notifications
You must be signed in to change notification settings - Fork 6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes gh-13185
- Loading branch information
Showing
10 changed files
with
751 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
= OAuth 2.0 Changes | ||
|
||
== Validate `typ` Header with `JwtTypeValidator` | ||
|
||
`NimbusJwtDecoder` in Spring Security 7 will move `typ` header validation to `JwtTypeValidator` intsead of relying on Nimbus. | ||
This brings it in line with `NimbusJwtDecoder` validating claims instead of relying on Nimbus to validate them. | ||
|
||
If you are changing Nimbus's default type validation in a `jwtProcessorCustomizer` method, then you should move that to `JwtTypeValidator` or an implementation of `OAuth2TokenValidator` of your own. | ||
|
||
To check if you are prepared for this change, add the default `JwtTypeValidator` to your list of validators, as this will be included by default in 7: | ||
|
||
[tabs] | ||
====== | ||
Java:: | ||
+ | ||
[source,java,role="primary"] | ||
---- | ||
@Bean | ||
JwtDecoder jwtDecoder() { | ||
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(false) <1> | ||
// ... your remaining configuration | ||
.build(); | ||
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators( | ||
new JwtIssuerValidator(location), JwtTypeValidator.jwt())); <2> | ||
return jwtDecoder; | ||
} | ||
---- | ||
Kotlin:: | ||
+ | ||
[source,kotlin,role="secondary"] | ||
---- | ||
@Bean | ||
fun jwtDecoder(): JwtDecoder { | ||
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(false) <1> | ||
// ... your remaining configuration | ||
.build() | ||
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators( | ||
JwtIssuerValidator(location), JwtTypeValidator.jwt())) <2> | ||
return jwtDecoder | ||
} | ||
---- | ||
====== | ||
<1> - Switch off Nimbus verifying the `typ` (this will be off by default in 7) | ||
<2> - Add the default `typ` validator (this will be included by default in 7) | ||
|
||
Note the default value verifies that the `typ` value either be `JWT` or not present, which is the same as the Nimbus default. | ||
It is also aligned with https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.9[RFC 7515] which states that `typ` is optional. | ||
|
||
|
||
=== I'm Using A `DefaultJOSEObjectTypeVerifier` | ||
|
||
If you have something like the following in your configuration: | ||
|
||
[tabs] | ||
====== | ||
Java:: | ||
+ | ||
[source,java,role="primary"] | ||
---- | ||
@Bean | ||
JwtDecoder jwtDecoder() { | ||
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.jwtProcessorCustomizer((c) -> c | ||
.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>("JOSE")) | ||
) | ||
.build(); | ||
return jwtDecoder; | ||
} | ||
---- | ||
Kotlin:: | ||
+ | ||
[source,kotlin,role="secondary"] | ||
---- | ||
@Bean | ||
fun jwtDecoder(): JwtDecoder { | ||
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.jwtProcessorCustomizer { | ||
it.setJWSTypeVerifier(DefaultJOSEObjectTypeVerifier("JOSE")) | ||
} | ||
.build() | ||
return jwtDecoder | ||
} | ||
---- | ||
====== | ||
|
||
Then change this to: | ||
|
||
[tabs] | ||
====== | ||
Java:: | ||
+ | ||
[source,java,role="primary"] | ||
---- | ||
@Bean | ||
JwtDecoder jwtDecoder() { | ||
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(false) | ||
.build(); | ||
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators( | ||
new JwtIssuerValidator(location), new JwtTypeValidator("JOSE"))); | ||
return jwtDecoder; | ||
} | ||
---- | ||
Kotlin:: | ||
+ | ||
[source,kotlin,role="secondary"] | ||
---- | ||
@Bean | ||
fun jwtDecoder(): JwtDecoder { | ||
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(false) | ||
.build() | ||
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators( | ||
JwtIssuerValidator(location), JwtTypeValidator("JOSE"))) | ||
return jwtDecoder | ||
} | ||
---- | ||
====== | ||
|
||
To indicate that the `typ` header is optional, use `#setAllowEmpty(true)` (this is the equivalent of including `null` in the list of allowed types in `DefaultJOSEObjectTypeVerifier`). | ||
|
||
=== I want to opt-out | ||
|
||
If you want to keep doing things the way that you are, then the steps are similar, just in reverse: | ||
|
||
[tabs] | ||
====== | ||
Java:: | ||
+ | ||
[source,java,role="primary"] | ||
---- | ||
@Bean | ||
JwtDecoder jwtDecoder() { | ||
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(true) <1> | ||
.jwtProcessorCustomizer((c) -> c | ||
.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>("JOSE")) | ||
) | ||
.build(); | ||
jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>( | ||
new JwtTimestampValidator(), new JwtIssuerValidator(location))); <2> | ||
return jwtDecoder; | ||
} | ||
---- | ||
Kotlin:: | ||
+ | ||
[source,kotlin,role="secondary"] | ||
---- | ||
@Bean | ||
fun jwtDecoder(): JwtDecoder { | ||
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location) | ||
.validateTypes(true) <1> | ||
.jwtProcessorCustomizer { | ||
it.setJWSTypeVerifier(DefaultJOSEObjectTypeVerifier("JOSE")) | ||
} | ||
.build() | ||
jwtDecoder.setJwtValidator(DelegatingOAuth2TokenValidator( | ||
JwtTimestampValidator(), JwtIssuerValidator(location))) <2> | ||
return jwtDecoder | ||
} | ||
---- | ||
====== | ||
<1> - leave Nimbus type verification on | ||
<2> - specify the list of validators you need, excluding `JwtTypeValidator` | ||
|
||
For additional guidance, please see the xref:servlet/oauth2/resource-server/jwt.adoc#oauth2resourceserver-jwt-validation[JwtDecoder Validators] section in the reference. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.