Skip to content

Commit 33fb93f

Browse files
committed
Add NimbusJwtDecoder Documentation
Fixes gh-7408
1 parent 101e0a2 commit 33fb93f

File tree

1 file changed

+153
-2
lines changed

1 file changed

+153
-2
lines changed

docs/manual/src/docs/asciidoc/_includes/servlet/preface/java-configuration.adoc

Lines changed: 153 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,7 @@ More powerful than `jwkSetUri()` is `decoder()`, which will completely replace a
597597

598598
```java
599599
@EnableWebSecurity
600-
public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
600+
public class DirectlyConfiguredJwtDecoder extends WebSecurityConfigurerAdapter {
601601
protected void configure(HttpSecurity http) {
602602
http
603603
.authorizeRequests()
@@ -624,6 +624,157 @@ public JwtDecoder jwtDecoder() {
624624
}
625625
```
626626

627+
[[oauth2resourceserver-jwt-decoder-algorithm]]
628+
=== Configuring Trusted Algorithms
629+
630+
By default, `NimbusJwtDecoder`, and hence Resource Server, will only trust and verify tokens using `RS256`.
631+
632+
You can customize this via <<oauth2-resourceserver-jwt-boot-algorithm,Spring Boot>>, <<oauth2-resourceserver-jwt-decoder-builder,the NimbusJwtDecoder builder>>, or from the <<oauth2-resourceserver-jwt-decoder-jwk-response,JWK Set response>>.
633+
634+
[[oauth2-resourceserver-jwt-boot-algorithm]]
635+
==== Via Spring Boot
636+
637+
The simplest way to set the algorithm is as a property:
638+
639+
```yaml
640+
spring:
641+
security:
642+
oauth2:
643+
resourceserver:
644+
jwt:
645+
jws-algorithm: RS512
646+
jwk-set-uri: https://idp.example.org/.well-known/jwks.json
647+
```
648+
649+
[[oauth2-resourceserver-jwt-decoder-builder]]
650+
==== Using a Builder
651+
652+
For greater power, though, we can use a builder that ships with `NimbusJwtDecoder`:
653+
654+
```java
655+
@Bean
656+
JwtDecoder jwtDecoder() {
657+
return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri)
658+
.jwsAlgorithm(RS512).build();
659+
}
660+
```
661+
662+
Calling `jwsAlgorithm` more than once will configure `NimbusJwtDecoder` to trust more than one algorithm, like so:
663+
664+
```java
665+
@Bean
666+
JwtDecoder jwtDecoder() {
667+
return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri)
668+
.jwsAlgorithm(RS512).jwsAlgorithm(EC512).build();
669+
}
670+
```
671+
672+
Or, you can call `jwsAlgorithms`:
673+
674+
```java
675+
@Bean
676+
JwtDecoder jwtDecoder() {
677+
return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri)
678+
.jwsAlgorithms(algorithms -> {
679+
algorithms.add(RS512);
680+
algorithms.add(EC512);
681+
}).build();
682+
}
683+
```
684+
685+
[[oauth2-resourceserver-jwt-decoder-jwk-response]]
686+
==== From JWK Set response
687+
688+
Since Spring Security's JWT support is based off of Nimbus, you can use all it's great features as well.
689+
690+
For example, Nimbus has a `JWSKeySelector` implementation that will select the set of algorithms based on the JWK Set URI response.
691+
You can use it to generate a `NimbusJwtDecoder` like so:
692+
693+
```java
694+
@Bean
695+
public JwtDecoder jwtDecoder() {
696+
// makes a request to the JWK Set endpoint
697+
JWSKeySelector<SecurityContext> jwsKeySelector =
698+
JWSAlgorithmFamilyJWSKeySelector.fromJWKSetURL(this.jwkSetUrl);
699+
700+
DefaultJWTProcessor<SecurityContext> jwtProcessor =
701+
new DefaultJWTProcessor<>();
702+
jwtProcessor.setJWSKeySelector(jwsKeySelector);
703+
704+
return new NimbusJwtDecoder(jwtProcessor);
705+
}
706+
```
707+
708+
[[oauth2resourceserver-jwt-decoder-public-key]]
709+
=== Trusting a Single Asymmetric Key
710+
711+
Simpler than backing a Resource Server with a JWK Set endpoint is to hard-code an RSA public key.
712+
The public key can be provided via <<oauth2resourceserver-jwt-decoder-public-key-boot,Spring Boot>> or by <<oauth2resourceserver-jwt-decoder-public-key-builder,Using a Builder>>.
713+
714+
[[oauth2resourceserver-jwt-decoder-public-key-boot]]
715+
==== Via Spring Boot
716+
717+
Specifying a key via Spring Boot is quite simple.
718+
The key's location can be specified like so:
719+
720+
```yaml
721+
spring:
722+
security:
723+
oauth2:
724+
resourceserver:
725+
jwt:
726+
public-key-location: classpath:my-key.pub
727+
```
728+
729+
Or, to allow for a more sophisticated lookup, you can post-process the `RsaKeyConversionServicePostProcessor`:
730+
731+
```java
732+
@Bean
733+
BeanFactoryPostProcessor conversionServiceCustomizer() {
734+
return beanFactory ->
735+
beanFactory.getBean(RsaKeyConversionServicePostProcessor.class)
736+
.setResourceLoader(new CustomResourceLoader());
737+
}
738+
```
739+
740+
Specify your key's location:
741+
742+
```yaml
743+
key.location: hfds://my-key.pub
744+
```
745+
746+
And then autowire the value:
747+
748+
```java
749+
@Value("${key.location}")
750+
RSAPublicKey key;
751+
```
752+
753+
[[oauth2resourceserver-jwt-decoder-public-key-builder]]
754+
==== Using a Builder
755+
756+
To wire an `RSAPublicKey` directly, you can simply use the appropriate `NimbusJwtDecoder` builder, like so:
757+
758+
```java
759+
@Bean
760+
public JwtDecoder jwtDecoder() {
761+
return NimbusJwtDecoder.withPublicKey(this.key).build();
762+
}
763+
```
764+
765+
[[oauth2resourceserver-jwt-decoder-secret-key]]
766+
=== Trusting a Single Symmetric Key
767+
768+
Using a single symmetric key is also simple.
769+
You can simply load in your `SecretKey` and use the appropriate `NimbusJwtDecoder` builder, like so:
770+
771+
```java
772+
@Bean
773+
public JwtDecoder jwtDecoder() {
774+
return NimbusJwtDecoder.withSecretKey(this.key).build();
775+
}
776+
```
777+
627778
[[oauth2resourceserver-jwt-authorization]]
628779
=== Configuring Authorization
629780

@@ -690,7 +841,7 @@ Converter<Jwt, AbstractAuthenticationToken> grantedAuthoritiesExtractor() {
690841
```
691842

692843
which is responsible for converting a `Jwt` into an `Authentication`.
693-
As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of `GrantedAuthority`s.
844+
As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of granted authorities.
694845

695846
That final converter might be something like `GrantedAuthoritiesExtractor` below:
696847

0 commit comments

Comments
 (0)