@ -32,6 +32,7 @@ import javax.crypto.SecretKey;
import com.nimbusds.jose.Header ;
import com.nimbusds.jose.Header ;
import com.nimbusds.jose.JOSEException ;
import com.nimbusds.jose.JOSEException ;
import com.nimbusds.jose.JOSEObjectType ;
import com.nimbusds.jose.JWSAlgorithm ;
import com.nimbusds.jose.JWSAlgorithm ;
import com.nimbusds.jose.JWSHeader ;
import com.nimbusds.jose.JWSHeader ;
import com.nimbusds.jose.jwk.JWK ;
import com.nimbusds.jose.jwk.JWK ;
@ -39,6 +40,8 @@ import com.nimbusds.jose.jwk.JWKMatcher;
import com.nimbusds.jose.jwk.JWKSelector ;
import com.nimbusds.jose.jwk.JWKSelector ;
import com.nimbusds.jose.jwk.source.JWKSecurityContextJWKSet ;
import com.nimbusds.jose.jwk.source.JWKSecurityContextJWKSet ;
import com.nimbusds.jose.proc.BadJOSEException ;
import com.nimbusds.jose.proc.BadJOSEException ;
import com.nimbusds.jose.proc.DefaultJOSEObjectTypeVerifier ;
import com.nimbusds.jose.proc.JOSEObjectTypeVerifier ;
import com.nimbusds.jose.proc.JWKSecurityContext ;
import com.nimbusds.jose.proc.JWKSecurityContext ;
import com.nimbusds.jose.proc.JWSKeySelector ;
import com.nimbusds.jose.proc.JWSKeySelector ;
import com.nimbusds.jose.proc.JWSVerificationKeySelector ;
import com.nimbusds.jose.proc.JWSVerificationKeySelector ;
@ -308,6 +311,12 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
* /
* /
public static final class JwkSetUriReactiveJwtDecoderBuilder {
public static final class JwkSetUriReactiveJwtDecoderBuilder {
private static final JOSEObjectTypeVerifier < JWKSecurityContext > JWT_TYPE_VERIFIER = new DefaultJOSEObjectTypeVerifier < > (
JOSEObjectType . JWT , null ) ;
private static final JOSEObjectTypeVerifier < JWKSecurityContext > NO_TYPE_VERIFIER = ( header , context ) - > {
} ;
private static final Duration FOREVER = Duration . ofMillis ( Long . MAX_VALUE ) ;
private static final Duration FOREVER = Duration . ofMillis ( Long . MAX_VALUE ) ;
private Function < WebClient , Mono < String > > jwkSetUri ;
private Function < WebClient , Mono < String > > jwkSetUri ;
@ -315,6 +324,8 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
private Function < ReactiveRemoteJWKSource , Mono < Set < JWSAlgorithm > > > defaultAlgorithms = ( source ) - > Mono
private Function < ReactiveRemoteJWKSource , Mono < Set < JWSAlgorithm > > > defaultAlgorithms = ( source ) - > Mono
. just ( Set . of ( JWSAlgorithm . RS256 ) ) ;
. just ( Set . of ( JWSAlgorithm . RS256 ) ) ;
private JOSEObjectTypeVerifier < JWKSecurityContext > typeVerifier = JWT_TYPE_VERIFIER ;
private Set < SignatureAlgorithm > signatureAlgorithms = new HashSet < > ( ) ;
private Set < SignatureAlgorithm > signatureAlgorithms = new HashSet < > ( ) ;
private WebClient webClient = WebClient . create ( ) ;
private WebClient webClient = WebClient . create ( ) ;
@ -349,6 +360,55 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
return this ;
return this ;
}
}
/ * *
* Whether to use Nimbus ' s typ header verification . This is { @code true } by
* default , however it may change to { @code false } in a future major release .
*
* < p >
* By turning off this feature , { @link NimbusReactiveJwtDecoder } expects
* applications to check the { @code typ } header themselves in order to determine
* what kind of validation is needed
* < / p >
*
* < p >
* This is done for you when you use { @link JwtValidators } to construct a
* validator .
*
* < p >
* That means that this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withIssuerLocation ( issuer ) . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithIssuer ( issuer ) ;
* < / code >
*
* < p >
* Is equivalent to this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withIssuerLocation ( issuer )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithValidators (
* new JwtIssuerValidator ( issuer ) , JwtTypeValidator . jwt ( ) ) ;
* < / code >
*
* < p >
* The difference is that by setting this to { @code false } , it allows you to
* provide validation by type , like for { @code at + jwt } :
*
* < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withIssuerLocation ( issuer )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( new MyAtJwtValidator ( ) ) ;
* < / code >
* @param shouldValidateTypHeader whether Nimbus should validate the typ header or
* not
* @return a { @link JwkSetUriReactiveJwtDecoderBuilder } for further configurations
* @since 6 . 5
* /
public JwkSetUriReactiveJwtDecoderBuilder validateType ( boolean shouldValidateTypHeader ) {
this . typeVerifier = shouldValidateTypHeader ? JWT_TYPE_VERIFIER : NO_TYPE_VERIFIER ;
return this ;
}
/ * *
/ * *
* Configure the list of
* Configure the list of
* < a href = "https://tools.ietf.org/html/rfc7515#section-4.1.1" target =
* < a href = "https://tools.ietf.org/html/rfc7515#section-4.1.1" target =
@ -435,13 +495,14 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
Mono < Tuple2 < ConfigurableJWTProcessor < JWKSecurityContext > , Function < JWSAlgorithm , Boolean > > > jwtProcessorMono = jwsKeySelector
Mono < Tuple2 < ConfigurableJWTProcessor < JWKSecurityContext > , Function < JWSAlgorithm , Boolean > > > jwtProcessorMono = jwsKeySelector
. flatMap ( ( selector ) - > {
. flatMap ( ( selector ) - > {
jwtProcessor . setJWSKeySelector ( selector ) ;
jwtProcessor . setJWSKeySelector ( selector ) ;
jwtProcessor . setJWSTypeVerifier ( this . typeVerifier ) ;
return this . jwtProcessorCustomizer . apply ( source , jwtProcessor ) ;
return this . jwtProcessorCustomizer . apply ( source , jwtProcessor ) ;
} )
} )
. map ( ( processor ) - > Tuples . of ( processor , getExpectedJwsAlgorithms ( processor . getJWSKeySelector ( ) ) ) )
. map ( ( processor ) - > Tuples . of ( processor , getExpectedJwsAlgorithms ( processor . getJWSKeySelector ( ) ) ) )
. cache ( ( processor ) - > FOREVER , ( ex ) - > Duration . ZERO , ( ) - > Duration . ZERO ) ;
. cache ( ( processor ) - > FOREVER , ( ex ) - > Duration . ZERO , ( ) - > Duration . ZERO ) ;
return ( jwt ) - > {
return ( jwt ) - > {
return jwtProcessorMono . flatMap ( ( tuple ) - > {
return jwtProcessorMono . flatMap ( ( tuple ) - > {
JWTProcessor < JWKSecurityContext > processor = tuple . getT1 ( ) ;
Configurable JWTProcessor< JWKSecurityContext > processor = tuple . getT1 ( ) ;
Function < JWSAlgorithm , Boolean > expectedJwsAlgorithms = tuple . getT2 ( ) ;
Function < JWSAlgorithm , Boolean > expectedJwsAlgorithms = tuple . getT2 ( ) ;
JWKSelector selector = createSelector ( expectedJwsAlgorithms , jwt . getHeader ( ) ) ;
JWKSelector selector = createSelector ( expectedJwsAlgorithms , jwt . getHeader ( ) ) ;
return source . get ( selector )
return source . get ( selector )
@ -476,10 +537,18 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
* /
* /
public static final class PublicKeyReactiveJwtDecoderBuilder {
public static final class PublicKeyReactiveJwtDecoderBuilder {
private static final JOSEObjectTypeVerifier < SecurityContext > JWT_TYPE_VERIFIER = new DefaultJOSEObjectTypeVerifier < > (
JOSEObjectType . JWT , null ) ;
private static final JOSEObjectTypeVerifier < SecurityContext > NO_TYPE_VERIFIER = ( header , context ) - > {
} ;
private final RSAPublicKey key ;
private final RSAPublicKey key ;
private JWSAlgorithm jwsAlgorithm ;
private JWSAlgorithm jwsAlgorithm ;
private JOSEObjectTypeVerifier < SecurityContext > typeVerifier = JWT_TYPE_VERIFIER ;
private Consumer < ConfigurableJWTProcessor < SecurityContext > > jwtProcessorCustomizer ;
private Consumer < ConfigurableJWTProcessor < SecurityContext > > jwtProcessorCustomizer ;
private PublicKeyReactiveJwtDecoderBuilder ( RSAPublicKey key ) {
private PublicKeyReactiveJwtDecoderBuilder ( RSAPublicKey key ) {
@ -505,6 +574,56 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
return this ;
return this ;
}
}
/ * *
* Whether to use Nimbus ' s typ header verification . This is { @code true } by
* default , however it may change to { @code false } in a future major release .
*
* < p >
* By turning off this feature , { @link NimbusReactiveJwtDecoder } expects
* applications to check the { @code typ } header themselves in order to determine
* what kind of validation is needed
* < / p >
*
* < p >
* This is done for you when you use { @link JwtValidators } to construct a
* validator .
*
* < p >
* That means that this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withIssuerLocation ( issuer ) . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithIssuer ( issuer ) ;
* < / code >
*
* < p >
* Is equivalent to this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withPublicKey ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithValidators (
* new JwtIssuerValidator ( issuer ) , JwtTypeValidator . jwt ( ) ) ;
* new JwtIssuerValidator ( issuer ) , JwtTypeValidator . jwt ( ) ) ;
* < / code >
*
* < p >
* The difference is that by setting this to { @code false } , it allows you to
* provide validation by type , like for { @code at + jwt } :
*
* < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withPublicKey ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( new MyAtJwtValidator ( ) ) ;
* < / code >
* @param shouldValidateTypHeader whether Nimbus should validate the typ header or
* not
* @return a { @link PublicKeyReactiveJwtDecoderBuilder } for further configurations
* @since 6 . 5
* /
public PublicKeyReactiveJwtDecoderBuilder validateType ( boolean shouldValidateTypHeader ) {
this . typeVerifier = shouldValidateTypHeader ? JWT_TYPE_VERIFIER : NO_TYPE_VERIFIER ;
return this ;
}
/ * *
/ * *
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* ConfigurableJWTProcessor } before passing it to the build
* ConfigurableJWTProcessor } before passing it to the build
@ -535,6 +654,7 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
JWSKeySelector < SecurityContext > jwsKeySelector = new SingleKeyJWSKeySelector < > ( this . jwsAlgorithm , this . key ) ;
JWSKeySelector < SecurityContext > jwsKeySelector = new SingleKeyJWSKeySelector < > ( this . jwsAlgorithm , this . key ) ;
DefaultJWTProcessor < SecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
DefaultJWTProcessor < SecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSTypeVerifier ( this . typeVerifier ) ;
// Spring Security validates the claim set independent from Nimbus
// Spring Security validates the claim set independent from Nimbus
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
} ) ;
} ) ;
@ -552,10 +672,18 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
* /
* /
public static final class SecretKeyReactiveJwtDecoderBuilder {
public static final class SecretKeyReactiveJwtDecoderBuilder {
private static final JOSEObjectTypeVerifier < SecurityContext > JWT_TYPE_VERIFIER = new DefaultJOSEObjectTypeVerifier < > (
JOSEObjectType . JWT , null ) ;
private static final JOSEObjectTypeVerifier < SecurityContext > NO_TYPE_VERIFIER = ( header , context ) - > {
} ;
private final SecretKey secretKey ;
private final SecretKey secretKey ;
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm . HS256 ;
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm . HS256 ;
private JOSEObjectTypeVerifier < SecurityContext > typeVerifier = JWT_TYPE_VERIFIER ;
private Consumer < ConfigurableJWTProcessor < SecurityContext > > jwtProcessorCustomizer ;
private Consumer < ConfigurableJWTProcessor < SecurityContext > > jwtProcessorCustomizer ;
private SecretKeyReactiveJwtDecoderBuilder ( SecretKey secretKey ) {
private SecretKeyReactiveJwtDecoderBuilder ( SecretKey secretKey ) {
@ -582,6 +710,55 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
return this ;
return this ;
}
}
/ * *
* Whether to use Nimbus ' s typ header verification . This is { @code true } by
* default , however it may change to { @code false } in a future major release .
*
* < p >
* By turning off this feature , { @link NimbusReactiveJwtDecoder } expects
* applications to check the { @code typ } header themselves in order to determine
* what kind of validation is needed
* < / p >
*
* < p >
* This is done for you when you use { @link JwtValidators } to construct a
* validator .
*
* < p >
* That means that this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withIssuerLocation ( issuer ) . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithIssuer ( issuer ) ;
* < / code >
*
* < p >
* Is equivalent to this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withSecretKey ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithValidators (
* new JwtIssuerValidator ( issuer ) , JwtTypeValidator . jwt ( ) ) ;
* < / code >
*
* < p >
* The difference is that by setting this to { @code false } , it allows you to
* provide validation by type , like for { @code at + jwt } :
*
* < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withSecretKey ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( new MyAtJwtValidator ( ) ) ;
* < / code >
* @param shouldValidateTypHeader whether Nimbus should validate the typ header or
* not
* @return a { @link PublicKeyReactiveJwtDecoderBuilder } for further configurations
* @since 6 . 5
* /
public SecretKeyReactiveJwtDecoderBuilder validateType ( boolean shouldValidateTypHeader ) {
this . typeVerifier = shouldValidateTypHeader ? JWT_TYPE_VERIFIER : NO_TYPE_VERIFIER ;
return this ;
}
/ * *
/ * *
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* ConfigurableJWTProcessor } before passing it to the build
* ConfigurableJWTProcessor } before passing it to the build
@ -610,6 +787,7 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
this . secretKey ) ;
this . secretKey ) ;
DefaultJWTProcessor < SecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
DefaultJWTProcessor < SecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSTypeVerifier ( this . typeVerifier ) ;
// Spring Security validates the claim set independent from Nimbus
// Spring Security validates the claim set independent from Nimbus
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
} ) ;
} ) ;
@ -626,10 +804,18 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
* /
* /
public static final class JwkSourceReactiveJwtDecoderBuilder {
public static final class JwkSourceReactiveJwtDecoderBuilder {
private static final JOSEObjectTypeVerifier < JWKSecurityContext > JWT_TYPE_VERIFIER = new DefaultJOSEObjectTypeVerifier < > (
JOSEObjectType . JWT , null ) ;
private static final JOSEObjectTypeVerifier < JWKSecurityContext > NO_TYPE_VERIFIER = ( header , context ) - > {
} ;
private final Function < SignedJWT , Flux < JWK > > jwkSource ;
private final Function < SignedJWT , Flux < JWK > > jwkSource ;
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm . RS256 ;
private JWSAlgorithm jwsAlgorithm = JWSAlgorithm . RS256 ;
private JOSEObjectTypeVerifier < JWKSecurityContext > typeVerifier = JWT_TYPE_VERIFIER ;
private Consumer < ConfigurableJWTProcessor < JWKSecurityContext > > jwtProcessorCustomizer ;
private Consumer < ConfigurableJWTProcessor < JWKSecurityContext > > jwtProcessorCustomizer ;
private JwkSourceReactiveJwtDecoderBuilder ( Function < SignedJWT , Flux < JWK > > jwkSource ) {
private JwkSourceReactiveJwtDecoderBuilder ( Function < SignedJWT , Flux < JWK > > jwkSource ) {
@ -652,6 +838,55 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
return this ;
return this ;
}
}
/ * *
* Whether to use Nimbus ' s typ header verification . This is { @code true } by
* default , however it may change to { @code false } in a future major release .
*
* < p >
* By turning off this feature , { @link NimbusReactiveJwtDecoder } expects
* applications to check the { @code typ } header themselves in order to determine
* what kind of validation is needed
* < / p >
*
* < p >
* This is done for you when you use { @link JwtValidators } to construct a
* validator .
*
* < p >
* That means that this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withJwkSource ( issuer ) . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithIssuer ( issuer ) ;
* < / code >
*
* < p >
* Is equivalent to this : < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withJwkSource ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( JwtValidators . createDefaultWithValidators (
* new JwtIssuerValidator ( issuer ) , JwtTypeValidator . jwt ( ) ) ;
* < / code >
*
* < p >
* The difference is that by setting this to { @code false } , it allows you to
* provide validation by type , like for { @code at + jwt } :
*
* < code >
* NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder . withJwkSource ( key )
* . validateType ( false )
* . build ( ) ;
* jwtDecoder . setJwtValidator ( new MyAtJwtValidator ( ) ) ;
* < / code >
* @param shouldValidateTypHeader whether Nimbus should validate the typ header or
* not
* @return a { @link JwkSourceReactiveJwtDecoderBuilder } for further configurations
* @since 6 . 5
* /
public JwkSourceReactiveJwtDecoderBuilder validateType ( boolean shouldValidateTypHeader ) {
this . typeVerifier = shouldValidateTypHeader ? JWT_TYPE_VERIFIER : NO_TYPE_VERIFIER ;
return this ;
}
/ * *
/ * *
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* Use the given { @link Consumer } to customize the { @link JWTProcessor
* ConfigurableJWTProcessor } before passing it to the build
* ConfigurableJWTProcessor } before passing it to the build
@ -681,6 +916,7 @@ public final class NimbusReactiveJwtDecoder implements ReactiveJwtDecoder {
jwkSource ) ;
jwkSource ) ;
DefaultJWTProcessor < JWKSecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
DefaultJWTProcessor < JWKSecurityContext > jwtProcessor = new DefaultJWTProcessor < > ( ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSKeySelector ( jwsKeySelector ) ;
jwtProcessor . setJWSTypeVerifier ( this . typeVerifier ) ;
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
jwtProcessor . setJWTClaimsSetVerifier ( ( claims , context ) - > {
} ) ;
} ) ;
this . jwtProcessorCustomizer . accept ( jwtProcessor ) ;
this . jwtProcessorCustomizer . accept ( jwtProcessor ) ;