From 5b5957eeaad24dee57960a7784d5552e2618185c Mon Sep 17 00:00:00 2001 From: Cato Olsen Date: Thu, 27 Feb 2025 21:05:55 +0100 Subject: [PATCH] Both decoders refactored (identical code). --- .../jwt/MultipleIssuersJwtDecoder.java | 6 +- .../jwt/MultipleIssuersJwtDecoder.java | 74 ++++++++++++------- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/libs/servlet-insecure-security/src/main/java/no/nav/testnav/libs/standalone/servletsecurity/jwt/MultipleIssuersJwtDecoder.java b/libs/servlet-insecure-security/src/main/java/no/nav/testnav/libs/standalone/servletsecurity/jwt/MultipleIssuersJwtDecoder.java index 9a84ab5fb9..3883c8f1ac 100644 --- a/libs/servlet-insecure-security/src/main/java/no/nav/testnav/libs/standalone/servletsecurity/jwt/MultipleIssuersJwtDecoder.java +++ b/libs/servlet-insecure-security/src/main/java/no/nav/testnav/libs/standalone/servletsecurity/jwt/MultipleIssuersJwtDecoder.java @@ -24,11 +24,11 @@ class MultipleIssuersJwtDecoder implements JwtDecoder { .stream() .collect(Collectors.toMap( ResourceServerProperties::getIssuerUri, - this::getValidatingDecoder + MultipleIssuersJwtDecoder::getValidatingDecoder )); } - private NimbusJwtDecoder getValidatingDecoder(ResourceServerProperties properties) { + private static NimbusJwtDecoder getValidatingDecoder(ResourceServerProperties properties) { NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(properties.getIssuerUri()); jwtDecoder.setJwtValidator(oAuth2TokenValidator(properties)); return jwtDecoder; @@ -61,7 +61,7 @@ public Jwt decode(String token) throws JwtException { } } - private OAuth2TokenValidator oAuth2TokenValidator(ResourceServerProperties properties) { + private static OAuth2TokenValidator oAuth2TokenValidator(ResourceServerProperties properties) { return new DelegatingOAuth2TokenValidator<>( issuerValidator(properties.getIssuerUri()), audienceValidator(properties.getAcceptedAudience()) diff --git a/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/jwt/MultipleIssuersJwtDecoder.java b/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/jwt/MultipleIssuersJwtDecoder.java index d5efecdb4c..938738f29e 100644 --- a/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/jwt/MultipleIssuersJwtDecoder.java +++ b/libs/servlet-security/src/main/java/no/nav/testnav/libs/servletsecurity/jwt/MultipleIssuersJwtDecoder.java @@ -16,54 +16,76 @@ @Slf4j class MultipleIssuersJwtDecoder implements JwtDecoder { + private final Map decoderMap; MultipleIssuersJwtDecoder(List properties) { - this.decoderMap = properties.stream().collect(Collectors.toMap( - ResourceServerProperties::getIssuerUri, - props -> { - NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(props.getIssuerUri()); - jwtDecoder.setJwtValidator(oAuth2TokenValidator(props)); - return jwtDecoder; - } - )); + decoderMap = properties + .stream() + .collect(Collectors.toMap( + ResourceServerProperties::getIssuerUri, + MultipleIssuersJwtDecoder::getValidatingDecoder + )); + } + + private static NimbusJwtDecoder getValidatingDecoder(ResourceServerProperties properties) { + NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(properties.getIssuerUri()); + jwtDecoder.setJwtValidator(oAuth2TokenValidator(properties)); + return jwtDecoder; } @Override public Jwt decode(String token) throws JwtException { try { + var issuer = JWTParser .parse(token) .getJWTClaimsSet() .getIssuer(); - return decoderMap - .get(issuer) - .decode(token); + if (issuer == null || !decoderMap.containsKey(issuer)) { + throw new JwtException("JWT decoder for issuer %s not found".formatted(issuer)); + } + var decoder = decoderMap.get(issuer); + log.info("Decoding token with issuer {} using decoder {}", issuer, decoder.getClass().getSimpleName()); + return decoder.decode(token); + } catch (ParseException e) { - log.error("Feil ved parsing av token", e); + log.error("Error in offset {} when parsing token", e.getErrorOffset(), e); throw new JwtException("Feil ved parsing av token", e); } catch (JwtValidationException e) { - log.error("Feil ved validering av token", e); + log.error("Error(s) validating token: {}", e.getErrors(), e); throw e; } catch (Exception e) { - log.error("Ukjent feil", e); - throw e; + log.error("Unexpected failure", e); + throw new JwtException("Unexpected failure", e); } } - private OAuth2TokenValidator oAuth2TokenValidator(ResourceServerProperties properties) { - OAuth2TokenValidator issuerValidator = JwtValidators.createDefaultWithIssuer(properties.getIssuerUri()); - OAuth2TokenValidator audienceValidator = token -> - token.getAudience().stream().anyMatch(audience -> properties.getAcceptedAudience().contains(audience)) ? - OAuth2TokenValidatorResult.success() : - OAuth2TokenValidatorResult.failure(createError( - String.format("Fant ikke pÄkrevd audience %s i tokenet.", properties.getAcceptedAudience()) - )); - return new DelegatingOAuth2TokenValidator<>(issuerValidator, audienceValidator); + private static OAuth2TokenValidator oAuth2TokenValidator(ResourceServerProperties properties) { + return new DelegatingOAuth2TokenValidator<>( + issuerValidator(properties.getIssuerUri()), + audienceValidator(properties.getAcceptedAudience()) + ); + } + + private static OAuth2TokenValidator issuerValidator(String issuerUri) { + return JwtValidators.createDefaultWithIssuer(issuerUri); // Note that this creates and adds a default audience validator. } - private OAuth2Error createError(String msg) { - return new OAuth2Error("invalid_token", msg, null); + private static OAuth2TokenValidator audienceValidator(List acceptedAudience) { + return token -> { + var audience = token.getAudience(); + var audienceIsAccepted = audience + .stream() + .anyMatch(acceptedAudience::contains); + if (audienceIsAccepted) { + log.info("Token audience {} is accepted by {}", audience, acceptedAudience); + return OAuth2TokenValidatorResult.success(); + } + var message = "Token audience %s is not accepted by %s".formatted(audience, acceptedAudience); + log.warn(message); + return OAuth2TokenValidatorResult.failure(new OAuth2Error("invalid_token", message, null)); + }; } }