Hi. I would like to ask for help. I receive “Could not obtain the keys” error, but when I tried to test with NimbusJwtDecoder or decode it with a custom method, it gave back the correct output. What is the issue with my code using NimbusReactiveJwtDecoder?
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.server.WebFilter;
import reactor.core.publisher.Mono;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.InvalidParameterException;
import java.security.interfaces.RSAPublicKey;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.auth0.jwk.JwkException;
import com.auth0.jwk.JwkProvider;
import com.auth0.jwk.UrlJwkProvider;
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {
private final String issuerUri = "https://dev-mycustomurl.us.auth0.com/";
private final String jwkSetUri = issuerUri + ".well-known/jwks.json";
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity serverHttpSecurity) {
serverHttpSecurity
.csrf().disable()
.authorizeExchange(exchange ->
exchange.pathMatchers("/eureka/**", "/discovery-server/**")
.permitAll()
.anyExchange()
.authenticated())
.oauth2ResourceServer().jwt()
.and()
.and()
.addFilterAt(logJwtFilter(), SecurityWebFiltersOrder.AUTHENTICATION);
return serverHttpSecurity.build();
}
private WebFilter logJwtFilter() {
NimbusReactiveJwtDecoder jwtDecoder = NimbusReactiveJwtDecoder.withJwkSetUri(issuerUri + ".well-known/jwks.json").build();
JwtDecoder decoder = NimbusJwtDecoder.withJwkSetUri(jwkSetUri).build();
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String authorizationHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
String jwtToken = authorizationHeader.substring(7);
System.out.println("JWT: " + jwtToken);
try {
Jwt jwt = decoder.decode(jwtToken);
Map<String, Object> claims = jwt.getClaims();
System.out.println("Decoded JWT using Nimbus: " + claims);
} catch (JwtException e) {
System.err.println("Failed to decode JWT using Nimbus: " + e.getMessage());
}
try {
DecodedJWT jwt = validateJwt(jwtToken);
System.out.println("Decoded JWT using custom decoder: " + jwt.getClaims());
} catch (JwtException e) {
System.err.println("Failed to decode JWT using custom decoder: " + e.getMessage());
}
try {
Mono<Jwt> reactiveJwt = jwtDecoder.decode(jwtToken);
reactiveJwt.subscribe(jwt -> {
Map<String, Object> claims = jwt.getClaims();
System.out.println("Decoded JWT using NimbusReactive: " + claims);
});
} catch (JwtException e) {
System.err.println("Failed to decode JWT using NimbusReactive: " + e.getMessage());
}
}
return chain.filter(exchange);
};
}
private RSAPublicKey loadPublicKey(DecodedJWT token) throws JwkException, MalformedURLException {
final String url = jwkSetUri;
JwkProvider provider = new UrlJwkProvider(new URL(url));
return (RSAPublicKey) provider.get(token.getKeyId()).getPublicKey();
}
public DecodedJWT validateJwt(String token) {
try {
final DecodedJWT jwt = JWT.decode(token);
RSAPublicKey publicKey = loadPublicKey(jwt);
Algorithm algorithm = Algorithm.RSA256(publicKey, null);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(jwt.getIssuer())
.build();
verifier.verify(token);
return jwt;
} catch (Exception e) {
logger.error("Failed to validate JWT", e);
throw new InvalidParameterException("JWT validation failed: " + e.getMessage());
}
}
}