You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jl...@apache.org on 2018/12/10 14:47:05 UTC

[02/38] tomee git commit: TOMEE-2247 - Added support for MP Configuration.

TOMEE-2247 - Added support for MP Configuration.


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/458da041
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/458da041
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/458da041

Branch: refs/heads/master
Commit: 458da0419c8225a7a4b6af9da03921b3ef388b9d
Parents: 3b717d9
Author: Roberto Cortez <ra...@yahoo.com>
Authored: Wed Sep 12 12:30:48 2018 +0100
Committer: Roberto Cortez <ra...@yahoo.com>
Committed: Fri Dec 7 18:08:35 2018 +0000

----------------------------------------------------------------------
 .../tomee/microprofile/jwt/MPJWTFilter.java     | 22 ++++--
 .../microprofile/jwt/cdi/MPJWTCDIExtension.java |  2 +
 .../config/ConfigurableJWTAuthContextInfo.java  | 78 ++++++++++++++++++++
 .../jwt/AppDeploymentExtension.java             | 18 ++++-
 4 files changed, 113 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/458da041/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
index 78f059e..ee3be1b 100644
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomee.microprofile.jwt;
 
+import org.apache.tomee.microprofile.jwt.config.ConfigurableJWTAuthContextInfo;
 import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
 import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory;
 import org.eclipse.microprofile.jwt.JsonWebToken;
@@ -41,6 +42,7 @@ import java.security.Principal;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Locale;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.function.Function;
@@ -49,10 +51,6 @@ import java.util.stream.Collectors;
 // async is supported because we only need to do work on the way in
 @WebFilter(asyncSupported = true, urlPatterns = "/*")
 public class MPJWTFilter implements Filter {
-
-    @Inject
-    private Instance<JWTAuthContextInfo> authContextInfo;
-
     @Override
     public void init(final FilterConfig filterConfig) throws ServletException {
         // nothing so far
@@ -60,7 +58,8 @@ public class MPJWTFilter implements Filter {
 
     @Override
     public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
-        if (authContextInfo.isUnsatisfied()) {
+        final Optional<JWTAuthContextInfo> authContextInfo = getAuthContextInfo();
+        if (!authContextInfo.isPresent()) {
             chain.doFilter(request,response);
             return;
         }
@@ -91,6 +90,19 @@ public class MPJWTFilter implements Filter {
         // nothing to do
     }
 
+    @Inject
+    private Instance<JWTAuthContextInfo> authContextInfo;
+    @Inject
+    private ConfigurableJWTAuthContextInfo configurableJWTAuthContextInfo;
+
+    private Optional<JWTAuthContextInfo> getAuthContextInfo() {
+        if (!authContextInfo.isUnsatisfied()) {
+            return Optional.of(authContextInfo.get());
+        }
+
+        return configurableJWTAuthContextInfo.getJWTAuthContextInfo();
+    }
+
     private static Function<HttpServletRequest, JsonWebToken> token(final HttpServletRequest httpServletRequest, final JWTAuthContextInfo authContextInfo) {
 
         return new Function<HttpServletRequest, JsonWebToken>() {

http://git-wip-us.apache.org/repos/asf/tomee/blob/458da041/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
index f93fab4..0d7b95a 100644
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/MPJWTCDIExtension.java
@@ -19,6 +19,7 @@ package org.apache.tomee.microprofile.jwt.cdi;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.tomee.microprofile.jwt.MPJWTFilter;
 import org.apache.tomee.microprofile.jwt.MPJWTInitializer;
+import org.apache.tomee.microprofile.jwt.config.ConfigurableJWTAuthContextInfo;
 import org.apache.tomee.microprofile.jwt.jaxrs.MPJWPProviderRegistration;
 import org.eclipse.microprofile.jwt.Claim;
 
@@ -96,6 +97,7 @@ public class MPJWTCDIExtension implements Extension {
     }
 
     public void observeBeforeBeanDiscovery(@Observes final BeforeBeanDiscovery bbd, final BeanManager beanManager) {
+        bbd.addAnnotatedType(beanManager.createAnnotatedType(ConfigurableJWTAuthContextInfo.class));
         bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.class));
         bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
         bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));

http://git-wip-us.apache.org/repos/asf/tomee/blob/458da041/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
new file mode 100644
index 0000000..59af1d6
--- /dev/null
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/ConfigurableJWTAuthContextInfo.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Optional;
+
+@RequestScoped
+public class ConfigurableJWTAuthContextInfo {
+    @Inject
+    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);
+
+        if (publicKey.isPresent()) {
+            final Optional<RSAPublicKey> rsaPublicKey = parsePCKS8(publicKey.get());
+            if (rsaPublicKey.isPresent()) {
+                return Optional.of(new JWTAuthContextInfo(rsaPublicKey.get(), issuer.orElse("")));
+            }
+        }
+
+        return Optional.empty();
+    }
+
+    private Optional<RSAPublicKey> parsePCKS8(final String publicKey) {
+        isPrivatePCKS8(publicKey);
+        try {
+            final X509EncodedKeySpec spec = new X509EncodedKeySpec(normalizeAndDecodePCKS8(publicKey));
+            final KeyFactory kf = KeyFactory.getInstance("RSA");
+            return Optional.of((RSAPublicKey) kf.generatePublic(spec));
+        } catch (final NoSuchAlgorithmException | InvalidKeySpecException e) {
+            return Optional.empty();
+        }
+    }
+
+    private void isPrivatePCKS8(final String publicKey) {
+        if (publicKey.contains("PRIVATE KEY")) {
+            throw new DeploymentException("MicroProfile JWT Public Key is Private.");
+        }
+    }
+
+    private byte[] normalizeAndDecodePCKS8(final String publicKey) {
+        final String normalizedKey =
+                publicKey.replaceAll("-----BEGIN (.*)-----", "")
+                         .replaceAll("-----END (.*)----", "")
+                         .replaceAll("\r\n", "")
+                         .replaceAll("\n", "");
+
+        return Base64.getDecoder().decode(normalizedKey);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/458da041/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 f5f2183..8b9df7f 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.PublicKeyAsPEMTest;
 import org.eclipse.microprofile.jwt.tck.util.TokenUtils;
 import org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription;
 import org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDeploymentScenarioGenerator;
@@ -11,14 +12,15 @@ import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScena
 import org.jboss.arquillian.core.spi.LoadableExtension;
 import org.jboss.arquillian.test.spi.TestClass;
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
 import org.jboss.shrinkwrap.api.Node;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.asset.EmptyAsset;
 import org.jboss.shrinkwrap.api.spec.WebArchive;
 
-import java.net.URL;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Logger;
 
 public class AppDeploymentExtension implements LoadableExtension {
@@ -71,7 +73,19 @@ public class AppDeploymentExtension implements LoadableExtension {
             final WebArchive war = WebArchive.class.cast(appArchive);
             war.addClass(JWTAuthContextInfoProvider.class);
 
+            // MP Config in wrong place - See https://github.com/eclipse/microprofile/issues/46.
+            final Map<ArchivePath, Node> content =
+                    war.getContent(
+                            object -> object.get().matches(".*META-INF/.*"));
+            content.forEach((archivePath, node) -> war.addAsResource(node.getAsset(), node.getPath()));
+
+            // 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);
+            }
+
             log.info("Augmented war: \n"+war.toString(true));
         }
     }
-}
\ No newline at end of file
+}