diff --git a/implementation/jwt-auth/pom.xml b/implementation/jwt-auth/pom.xml index 8eac6e0a..675c490e 100644 --- a/implementation/jwt-auth/pom.xml +++ b/implementation/jwt-auth/pom.xml @@ -72,6 +72,10 @@ io.smallrye smallrye-jwt-common + + io.smallrye.converters + smallrye-converters + org.jboss.logging jboss-logging diff --git a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipal.java b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipal.java index c30b2bb5..5ed9e6c7 100644 --- a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipal.java +++ b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipal.java @@ -16,15 +16,20 @@ package io.smallrye.jwt.auth.principal; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import javax.json.JsonObject; + import org.eclipse.microprofile.jwt.Claims; import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.MalformedClaimException; +import io.smallrye.converters.api.Converter; import io.smallrye.jwt.JsonUtils; /** @@ -34,6 +39,7 @@ */ public class DefaultJWTCallerPrincipal extends JWTCallerPrincipal { private final JwtClaims claimsSet; + private Map, Converter> converters = Collections.emptyMap(); /** * Create the DefaultJWTCallerPrincipal from the parsed JWT token and the extracted principal name @@ -52,6 +58,11 @@ public DefaultJWTCallerPrincipal(String tokenType, JwtClaims claimsSet) { this(getRawToken(claimsSet), tokenType, claimsSet); } + public DefaultJWTCallerPrincipal(String tokenType, JwtClaims claimsSet, Map, Converter> converters) { + this(getRawToken(claimsSet), tokenType, claimsSet); + this.converters = converters; + } + public DefaultJWTCallerPrincipal(JwtClaims claimsSet) { this("JWT", claimsSet); } @@ -166,9 +177,15 @@ protected Set filterCustomClaimNames(Collection claimNames) { protected void replaceClaimValueWithJsonValue(String name) { try { - final Object object = claimsSet.getClaimValue(name, Object.class); + Object object = claimsSet.getClaimValue(name, Object.class); if (!(object instanceof String)) { - claimsSet.setClaim(name, JsonUtils.wrapValue(object)); + + object = JsonUtils.wrapValue(object); + if (object instanceof JsonObject && converters.containsKey(JsonObject.class)) { + object = converters.get(JsonObject.class).convert(object.toString()); + } + + claimsSet.setClaim(name, object); } } catch (MalformedClaimException e) { PrincipalLogging.log.replaceClaimValueWithJsonFailure(name, e); diff --git a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipalFactory.java b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipalFactory.java index c308d2e7..75103ad6 100644 --- a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipalFactory.java +++ b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/DefaultJWTCallerPrincipalFactory.java @@ -19,7 +19,7 @@ import org.jose4j.jwt.consumer.JwtContext; /** - * A default implementation of the abstract JWTCallerPrincipalFactory that uses the Keycloak token parsing classes. + * A default implementation of the abstract JWTCallerPrincipalFactory. */ public class DefaultJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory { @@ -30,7 +30,7 @@ public JWTCallerPrincipal parse(final String token, final JWTAuthContextInfo aut JwtContext jwtContext = parser.parse(token, authContextInfo); String type = jwtContext.getJoseObjects().get(0).getHeader("typ"); - return new DefaultJWTCallerPrincipal(type, jwtContext.getJwtClaims()); + return new DefaultJWTCallerPrincipal(type, jwtContext.getJwtClaims(), authContextInfo.getConverters()); } } diff --git a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/JWTAuthContextInfo.java b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/JWTAuthContextInfo.java index c15f26d3..21146449 100644 --- a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/JWTAuthContextInfo.java +++ b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/auth/principal/JWTAuthContextInfo.java @@ -20,10 +20,12 @@ import java.security.interfaces.RSAPublicKey; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import javax.crypto.SecretKey; +import io.smallrye.converters.api.Converter; import io.smallrye.jwt.KeyFormat; import io.smallrye.jwt.algorithm.KeyEncryptionAlgorithm; import io.smallrye.jwt.algorithm.SignatureAlgorithm; @@ -64,6 +66,7 @@ public class JWTAuthContextInfo { private Set requiredClaims; private boolean relaxVerificationKeyValidation = true; private boolean verifyCertificateThumbprint; + private Map, Converter> converters = Collections.emptyMap(); public JWTAuthContextInfo() { } @@ -121,6 +124,7 @@ public JWTAuthContextInfo(JWTAuthContextInfo orig) { this.requiredClaims = orig.requiredClaims; this.relaxVerificationKeyValidation = orig.relaxVerificationKeyValidation; this.verifyCertificateThumbprint = orig.verifyCertificateThumbprint; + this.converters = orig.converters; } @Deprecated @@ -406,6 +410,7 @@ public String toString() { ", groupsSeparator='" + groupsSeparator + '\'' + ", relaxVerificationKeyValidation=" + relaxVerificationKeyValidation + ", verifyCertificateThumbprint=" + verifyCertificateThumbprint + + ", converters=" + converters + '}'; } @@ -424,4 +429,12 @@ public boolean isVerifyCertificateThumbprint() { public void setVerifyCertificateThumbprint(boolean verifyCertificateThumbprint) { this.verifyCertificateThumbprint = verifyCertificateThumbprint; } + + public Map, Converter> getConverters() { + return converters; + } + + public void setConverters(Map, Converter> converters) { + this.converters = converters; + } } diff --git a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/config/JWTAuthContextInfoProvider.java b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/config/JWTAuthContextInfoProvider.java index 29b08b2b..f849a6cd 100644 --- a/implementation/jwt-auth/src/main/java/io/smallrye/jwt/config/JWTAuthContextInfoProvider.java +++ b/implementation/jwt-auth/src/main/java/io/smallrye/jwt/config/JWTAuthContextInfoProvider.java @@ -17,17 +17,23 @@ package io.smallrye.jwt.config; import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; import java.util.Optional; import java.util.Set; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Instance; import javax.enterprise.inject.Produces; import javax.inject.Inject; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.jwt.config.Names; +import io.smallrye.converters.api.Converter; import io.smallrye.jwt.KeyFormat; import io.smallrye.jwt.SmallryeJwtUtils; import io.smallrye.jwt.algorithm.KeyEncryptionAlgorithm; @@ -46,6 +52,9 @@ public class JWTAuthContextInfoProvider { private static final String NONE = "NONE"; private static final String DEFAULT_GROUPS_SEPARATOR = " "; + @Inject + Instance> converters; + /** * Create JWTAuthContextInfoProvider with the public key and issuer * @@ -526,9 +535,25 @@ Optional getOptionalContextInfo() { contextInfo.setRequiredClaims(requiredClaims.orElse(null)); contextInfo.setRelaxVerificationKeyValidation(relaxVerificationKeyValidation); contextInfo.setVerifyCertificateThumbprint(verifyCertificateThumbprint); + + Map, Converter> converterMap = createConverterMap(); + contextInfo.setConverters(converterMap); return Optional.of(contextInfo); } + private Map, Converter> createConverterMap() { + if (converters != null && converters.isResolvable()) { + Map, Converter> map = new HashMap<>(); + for (Iterator> it = converters.iterator(); it.hasNext();) { + Converter converter = it.next(); + map.put(String.class, converter); + } + return map; + } else { + return Collections.emptyMap(); + } + } + @Produces @ApplicationScoped public JWTAuthContextInfo getContextInfo() { diff --git a/pom.xml b/pom.xml index 8a7102e1..bd1a5605 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,7 @@ 0.7.8 4.6.0.Final 3.11.1 + 1.0.0 @@ -115,6 +116,12 @@ ${version.jose4j} + + io.smallrye.converters + smallrye-converters + ${version.smallrye.converters} + + io.smallrye