TOMEE-2247 - Load public key from classpath Location.
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/2ca6e59f Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/2ca6e59f Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/2ca6e59f Branch: refs/heads/master Commit: 2ca6e59fa35f85831ab697377595965a93af6a5a Parents: 458da04 Author: Roberto Cortez <[email protected]> Authored: Wed Sep 12 15:53:35 2018 +0100 Committer: Roberto Cortez <[email protected]> Committed: Fri Dec 7 18:08:36 2018 +0000 ---------------------------------------------------------------------- .../config/ConfigurableJWTAuthContextInfo.java | 80 +++++++++++++++++++- .../jwt/AppDeploymentExtension.java | 11 ++- 2 files changed, 84 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/2ca6e59f/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java ---------------------------------------------------------------------- diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java index 59af1d6..cd7f2ec 100644 --- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java +++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java @@ -17,11 +17,15 @@ package org.apache.tomee.microprofile.jwt.config; import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.jwt.config.Names; import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.spi.DeploymentException; import javax.inject.Inject; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; @@ -29,6 +33,11 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; import java.util.Optional; +import java.util.stream.Stream; + +import static org.eclipse.microprofile.jwt.config.Names.ISSUER; +import static org.eclipse.microprofile.jwt.config.Names.VERIFIER_PUBLIC_KEY; +import static org.eclipse.microprofile.jwt.config.Names.VERIFIER_PUBLIC_KEY_LOCATION; @RequestScoped public class ConfigurableJWTAuthContextInfo { @@ -36,16 +45,79 @@ public class ConfigurableJWTAuthContextInfo { private Config config; public Optional<JWTAuthContextInfo> getJWTAuthContextInfo() { - final Optional<String> publicKey = config.getOptionalValue(Names.VERIFIER_PUBLIC_KEY, String.class); - final Optional<String> issuer = config.getOptionalValue(Names.ISSUER, String.class); + final Optional<String> publicKey = config.getOptionalValue(VERIFIER_PUBLIC_KEY, String.class); + final Optional<String> publicKeyLocation = config.getOptionalValue(VERIFIER_PUBLIC_KEY_LOCATION, String.class); + final Optional<String> issuer = config.getOptionalValue(ISSUER, String.class); if (publicKey.isPresent()) { - final Optional<RSAPublicKey> rsaPublicKey = parsePCKS8(publicKey.get()); + final Optional<RSAPublicKey> rsaPublicKey = readPublicKey(publicKey.get()); if (rsaPublicKey.isPresent()) { return Optional.of(new JWTAuthContextInfo(rsaPublicKey.get(), issuer.orElse(""))); } } + if (publicKeyLocation.isPresent()) { + final Optional<RSAPublicKey> rsaPublicKey = readPublicKey(readPublicKeyFromLocation(publicKeyLocation.get())); + if (rsaPublicKey.isPresent()) { + return Optional.of(new JWTAuthContextInfo(rsaPublicKey.get(), issuer.orElse(""))); + } + } + + return Optional.empty(); + } + + private Optional<RSAPublicKey> readPublicKey(final String publicKey) { + return parsePCKS8(publicKey); + } + + private String readPublicKeyFromLocation(final String publicKeyLocation) { + final Stream<Optional<String>> possiblePublicKeysLocations = + Stream.of(readPublicKeyFromClasspath(publicKeyLocation), + readPublicKeyFromFile(publicKeyLocation), + readPublicKeyFromHttp(publicKeyLocation), + readPublicKeyFromUrl(publicKeyLocation)); + + return possiblePublicKeysLocations + .filter(Optional::isPresent) + .map(Optional::get) + .findFirst() + .orElseThrow(() -> new DeploymentException("Could not read MicroProfile Public Key from Location: " + + publicKeyLocation)); + } + + private Optional<String> readPublicKeyFromClasspath(final String publicKeyLocation) { + try { + final InputStream is = + Thread.currentThread().getContextClassLoader().getResourceAsStream(publicKeyLocation); + if (is == null) { + return Optional.empty(); + } + + final StringWriter sw = new StringWriter(); + try (final BufferedReader br = new BufferedReader(new InputStreamReader(is))) { + String line = br.readLine(); + while (line != null) { + sw.write(line); + sw.write('\n'); + line = br.readLine(); + } + } + return Optional.of(sw.toString()); + } catch (final IOException e) { + throw new DeploymentException( + "Could not read MicroProfile Public Key from Location: " + publicKeyLocation, e); + } + } + + private Optional<String> readPublicKeyFromFile(final String publicKeyLocation) { + return Optional.empty(); + } + + private Optional<String> readPublicKeyFromHttp(final String publicKeyLocation) { + return Optional.empty(); + } + + private Optional<String> readPublicKeyFromUrl(final String publicKeyLocation) { return Optional.empty(); } http://git-wip-us.apache.org/repos/asf/tomee/blob/2ca6e59f/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java ---------------------------------------------------------------------- diff --git a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java index 8b9df7f..bf79556 100644 --- a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java +++ b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java @@ -3,6 +3,7 @@ package org.apache.tomee.microprofile.jwt; import com.nimbusds.jose.JWSSigner; import org.apache.openejb.loader.JarLocation; import org.eclipse.microprofile.jwt.tck.TCKConstants; +import org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMLocationTest; import org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMTest; import org.eclipse.microprofile.jwt.tck.util.TokenUtils; import org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription; @@ -22,6 +23,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.logging.Logger; +import java.util.stream.Stream; public class AppDeploymentExtension implements LoadableExtension { @Override @@ -81,9 +83,12 @@ public class AppDeploymentExtension implements LoadableExtension { // Spec says that vendor specific ways to load the keys take precedence, so we need to remove it in test // cases that use the Config approach. - if (testClass.getJavaClass().equals(PublicKeyAsPEMTest.class)) { - war.deleteClass(JWTAuthContextInfoProvider.class); - } + Stream.of( + PublicKeyAsPEMTest.class, + PublicKeyAsPEMLocationTest.class) + .filter(c -> c.equals(testClass.getJavaClass())) + .findAny() + .ifPresent(c -> war.deleteClass(JWTAuthContextInfoProvider.class)); log.info("Augmented war: \n"+war.toString(true)); }
