diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/java-configuration.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/java-configuration.adoc index 6d5c30155a..3764745b23 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/java-configuration.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/java-configuration.adoc @@ -597,7 +597,7 @@ More powerful than `jwkSetUri()` is `decoder()`, which will completely replace a ```java @EnableWebSecurity -public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter { +public class DirectlyConfiguredJwtDecoder extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) { http .authorizeRequests() @@ -624,6 +624,157 @@ public JwtDecoder jwtDecoder() { } ``` +[[oauth2resourceserver-jwt-decoder-algorithm]] +=== Configuring Trusted Algorithms + +By default, `NimbusJwtDecoder`, and hence Resource Server, will only trust and verify tokens using `RS256`. + +You can customize this via <>, <>, or from the <>. + +[[oauth2-resourceserver-jwt-boot-algorithm]] +==== Via Spring Boot + +The simplest way to set the algorithm is as a property: + +```yaml +spring: + security: + oauth2: + resourceserver: + jwt: + jws-algorithm: RS512 + jwk-set-uri: https://idp.example.org/.well-known/jwks.json +``` + +[[oauth2-resourceserver-jwt-decoder-builder]] +==== Using a Builder + +For greater power, though, we can use a builder that ships with `NimbusJwtDecoder`: + +```java +@Bean +JwtDecoder jwtDecoder() { + return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri) + .jwsAlgorithm(RS512).build(); +} +``` + +Calling `jwsAlgorithm` more than once will configure `NimbusJwtDecoder` to trust more than one algorithm, like so: + +```java +@Bean +JwtDecoder jwtDecoder() { + return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri) + .jwsAlgorithm(RS512).jwsAlgorithm(EC512).build(); +} +``` + +Or, you can call `jwsAlgorithms`: + +```java +@Bean +JwtDecoder jwtDecoder() { + return NimbusJwtDecoder.fromJwkSetUri(this.jwkSetUri) + .jwsAlgorithms(algorithms -> { + algorithms.add(RS512); + algorithms.add(EC512); + }).build(); +} +``` + +[[oauth2-resourceserver-jwt-decoder-jwk-response]] +==== From JWK Set response + +Since Spring Security's JWT support is based off of Nimbus, you can use all it's great features as well. + +For example, Nimbus has a `JWSKeySelector` implementation that will select the set of algorithms based on the JWK Set URI response. +You can use it to generate a `NimbusJwtDecoder` like so: + +```java +@Bean +public JwtDecoder jwtDecoder() { + // makes a request to the JWK Set endpoint + JWSKeySelector jwsKeySelector = + JWSAlgorithmFamilyJWSKeySelector.fromJWKSetURL(this.jwkSetUrl); + + DefaultJWTProcessor jwtProcessor = + new DefaultJWTProcessor<>(); + jwtProcessor.setJWSKeySelector(jwsKeySelector); + + return new NimbusJwtDecoder(jwtProcessor); +} +``` + +[[oauth2resourceserver-jwt-decoder-public-key]] +=== Trusting a Single Asymmetric Key + +Simpler than backing a Resource Server with a JWK Set endpoint is to hard-code an RSA public key. +The public key can be provided via <> or by <>. + +[[oauth2resourceserver-jwt-decoder-public-key-boot]] +==== Via Spring Boot + +Specifying a key via Spring Boot is quite simple. +The key's location can be specified like so: + +```yaml +spring: + security: + oauth2: + resourceserver: + jwt: + public-key-location: classpath:my-key.pub +``` + +Or, to allow for a more sophisticated lookup, you can post-process the `RsaKeyConversionServicePostProcessor`: + +```java +@Bean +BeanFactoryPostProcessor conversionServiceCustomizer() { + return beanFactory -> + beanFactory.getBean(RsaKeyConversionServicePostProcessor.class) + .setResourceLoader(new CustomResourceLoader()); +} +``` + +Specify your key's location: + +```yaml +key.location: hfds://my-key.pub +``` + +And then autowire the value: + +```java +@Value("${key.location}") +RSAPublicKey key; +``` + +[[oauth2resourceserver-jwt-decoder-public-key-builder]] +==== Using a Builder + +To wire an `RSAPublicKey` directly, you can simply use the appropriate `NimbusJwtDecoder` builder, like so: + +```java +@Bean +public JwtDecoder jwtDecoder() { + return NimbusJwtDecoder.withPublicKey(this.key).build(); +} +``` + +[[oauth2resourceserver-jwt-decoder-secret-key]] +=== Trusting a Single Symmetric Key + +Using a single symmetric key is also simple. +You can simply load in your `SecretKey` and use the appropriate `NimbusJwtDecoder` builder, like so: + +```java +@Bean +public JwtDecoder jwtDecoder() { + return NimbusJwtDecoder.withSecretKey(this.key).build(); +} +``` + [[oauth2resourceserver-jwt-authorization]] === Configuring Authorization @@ -690,7 +841,7 @@ Converter grantedAuthoritiesExtractor() { ``` which is responsible for converting a `Jwt` into an `Authentication`. -As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of `GrantedAuthority`s. +As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of granted authorities. That final converter might be something like `GrantedAuthoritiesExtractor` below: