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:20 UTC

[17/38] tomee git commit: TOMEE-2247 - Refactor to support multiple keys.

TOMEE-2247 - Refactor to support multiple keys.


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

Branch: refs/heads/master
Commit: be942d5012a432d2be92e27cc272469bddbb679c
Parents: 46934a0
Author: Roberto Cortez <ra...@yahoo.com>
Authored: Tue Sep 25 19:00:47 2018 +0100
Committer: Roberto Cortez <ra...@yahoo.com>
Committed: Fri Dec 7 18:11:18 2018 +0000

----------------------------------------------------------------------
 .../tomee/microprofile/jwt/MPJWTFilter.java     |  1 -
 .../config/ConfigurableJWTAuthContextInfo.java  | 55 ++++++++++----------
 .../jwt/config/JWTAuthContextInfo.java          | 43 +++++++--------
 .../DefaultJWTCallerPrincipalFactory.java       |  4 +-
 .../tck/jwt/JWTAuthContextInfoProvider.java     |  9 +---
 .../microprofile/tck/jwt/TCKTokenParser.java    | 40 --------------
 ...lipse.microprofile.jwt.tck.util.ITokenParser |  1 -
 7 files changed, 51 insertions(+), 102 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/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 9633819..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,7 +16,6 @@
  */
 package org.apache.tomee.microprofile.jwt;
 
-import org.apache.openejb.loader.SystemInstance;
 import org.apache.tomee.microprofile.jwt.config.ConfigurableJWTAuthContextInfo;
 import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
 import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory;

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/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 3705448..d5e302e 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
@@ -41,6 +41,7 @@ import java.io.StringReader;
 import java.io.StringWriter;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.security.Key;
 import java.security.KeyFactory;
 import java.security.NoSuchAlgorithmException;
 import java.security.interfaces.RSAPublicKey;
@@ -48,6 +49,7 @@ import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.Arrays;
 import java.util.Base64;
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Supplier;
@@ -91,51 +93,50 @@ public class ConfigurableJWTAuthContextInfo {
     }
 
     private JWTAuthContextInfo createJWTAuthContextInfo() {
-        final Stream<Supplier<Optional<RSAPublicKey>>> possiblePublicKeys =
-                Stream.of(() -> getVerifierPublicKey().map(this::readPublicKey),
-                          () -> getPublicKeyLocation().map(this::readPublicKeyFromLocation));
+        final Stream<Supplier<Optional<List<Key>>>> possiblePublicKeys =
+                Stream.of(() -> getVerifierPublicKey().map(this::readPublicKeys),
+                          () -> getPublicKeyLocation().map(this::readPublicKeysFromLocation));
 
         return possiblePublicKeys
                 .map(Supplier::get)
                 .filter(Optional::isPresent)
                 .map(Optional::get)
                 .findFirst()
-                .map(key -> new JWTAuthContextInfo(key, getIssuer().orElse(null)))
+                .map(keys -> JWTAuthContextInfo.authContextInfo(keys, getIssuer().orElse(null)))
                 .orElse(null);
     }
 
-    private RSAPublicKey readPublicKey(final String publicKey) {
-        final Stream<Supplier<Optional<RSAPublicKey>>> possiblePublicKeysParses =
+    private List<Key> readPublicKeys(final String publicKey) {
+        final Stream<Supplier<List<Key>>> possiblePublicKeysParses =
                 Stream.of(() -> parsePCKS8(publicKey),
                           () -> parseJwk(publicKey),
                           () -> parseJwk(new String(Base64.getDecoder().decode(publicKey))));
 
         return possiblePublicKeysParses
                 .map(Supplier::get)
-                .filter(Optional::isPresent)
-                .map(Optional::get)
+                .filter(keys -> !keys.isEmpty())
                 .findFirst()
                 .orElseThrow(() -> new DeploymentException("Could not read MicroProfile Public Key: " + publicKey));
     }
 
-    private RSAPublicKey readPublicKeyFromLocation(final String publicKeyLocation) {
+    private List<Key> readPublicKeysFromLocation(final String publicKeyLocation) {
         final Stream<Supplier<Optional<String>>> possiblePublicKeysLocations =
-                Stream.of(() -> readPublicKeyFromClasspath(publicKeyLocation),
-                          () -> readPublicKeyFromFile(publicKeyLocation),
-                          () -> readPublicKeyFromHttp(publicKeyLocation),
-                          () -> readPublicKeyFromUrl(publicKeyLocation));
+                Stream.of(() -> readPublicKeysFromClasspath(publicKeyLocation),
+                          () -> readPublicKeysFromFile(publicKeyLocation),
+                          () -> readPublicKeysFromHttp(publicKeyLocation),
+                          () -> readPublicKeysFromUrl(publicKeyLocation));
 
         return possiblePublicKeysLocations
                 .map(Supplier::get)
                 .filter(Optional::isPresent)
                 .map(Optional::get)
                 .findFirst()
-                .map(this::readPublicKey)
+                .map(this::readPublicKeys)
                 .orElseThrow(() -> new DeploymentException("Could not read MicroProfile Public Key from Location: " +
                                                            publicKeyLocation));
     }
 
-    private Optional<String> readPublicKeyFromClasspath(final String publicKeyLocation) {
+    private Optional<String> readPublicKeysFromClasspath(final String publicKeyLocation) {
         try {
             final InputStream is =
                     Thread.currentThread().getContextClassLoader().getResourceAsStream(publicKeyLocation);
@@ -149,7 +150,7 @@ public class ConfigurableJWTAuthContextInfo {
         }
     }
 
-    private Optional<String> readPublicKeyFromFile(final String publicKeyLocation) {
+    private Optional<String> readPublicKeysFromFile(final String publicKeyLocation) {
         if (!publicKeyLocation.startsWith("file")) {
             return Optional.empty();
         }
@@ -171,7 +172,7 @@ public class ConfigurableJWTAuthContextInfo {
         }
     }
 
-    private Optional<String> readPublicKeyFromHttp(final String publicKeyLocation) {
+    private Optional<String> readPublicKeysFromHttp(final String publicKeyLocation) {
         if (!publicKeyLocation.startsWith("http")) {
             return Optional.empty();
         }
@@ -185,7 +186,7 @@ public class ConfigurableJWTAuthContextInfo {
         }
     }
 
-    private Optional<String> readPublicKeyFromUrl(final String publicKeyLocation) {
+    private Optional<String> readPublicKeysFromUrl(final String publicKeyLocation) {
         try {
             final URL locationURL = new URL(publicKeyLocation);
             return Optional.of(readPublicKeyFromInputStream(locationURL.openStream()));
@@ -208,39 +209,39 @@ public class ConfigurableJWTAuthContextInfo {
         return content.toString();
     }
 
-    private Optional<RSAPublicKey> parsePCKS8(final String publicKey) {
+    private List<Key> parsePCKS8(final String publicKey) {
         try {
             final X509EncodedKeySpec spec = new X509EncodedKeySpec(normalizeAndDecodePCKS8(publicKey));
             final KeyFactory kf = KeyFactory.getInstance("RSA");
-            return Optional.of((RSAPublicKey) kf.generatePublic(spec));
+            return Collections.singletonList(kf.generatePublic(spec));
         } catch (final NoSuchAlgorithmException | InvalidKeySpecException | IllegalArgumentException e) {
-            return Optional.empty();
+            return Collections.emptyList();
         }
     }
 
-    private Optional<RSAPublicKey> parseJwk(final String publicKey) {
+    private List<Key> parseJwk(final String publicKey) {
         final JsonObject jwk;
         try {
             jwk = Json.createReader(new StringReader(publicKey)).readObject();
         } catch (final JsonParsingException e) {
-            return Optional.empty();
+            return Collections.emptyList();
         }
 
         validateJwk(jwk);
 
         try {
-            return Optional.of((RSAPublicKey) JsonWebKey.Factory.newJwk(publicKey).getKey());
+            return Collections.singletonList(JsonWebKey.Factory.newJwk(publicKey).getKey());
         } catch (final JoseException e) {
             throw new DeploymentException("Could not read MicroProfile Public Key JWK.", e);
         }
     }
 
-    private Optional<List<RSAPublicKey>> parseJwks(final String publicKey) {
+    private List<Key> parseJwks(final String publicKey) {
         final JsonObject jwks;
         try {
             jwks = Json.createReader(new StringReader(publicKey)).readObject();
         } catch (final JsonParsingException e) {
-            return Optional.empty();
+            return Collections.emptyList();
         }
 
         try {
@@ -260,7 +261,7 @@ public class ConfigurableJWTAuthContextInfo {
                           .map(JsonWebKey::getKey)
                           .map(key -> (RSAPublicKey) key)
                           .collect(Collectors.toList());
-            return Optional.of(keys);
+            return Collections.unmodifiableList(keys);
         } catch (final JoseException e) {
             throw new DeploymentException("Could not read MicroProfile Public Key JWK.", e);
         }

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
index a969515..02132c0 100644
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfo.java
@@ -16,52 +16,49 @@
  */
 package org.apache.tomee.microprofile.jwt.config;
 
-import java.security.interfaces.RSAPublicKey;
+import java.security.Key;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * The public key and expected issuer needed to validate a token.
  */
 public class JWTAuthContextInfo {
-
-    private RSAPublicKey signerKey;
+    private List<Key> signerKeys;
     private String issuedBy;
     private int expGracePeriodSecs = 60;
 
-    public JWTAuthContextInfo() {
+    private JWTAuthContextInfo(final Key signerKey, final String issuedBy) {
+        this.signerKeys = Collections.singletonList(signerKey);
+        this.issuedBy = issuedBy;
     }
 
-    public JWTAuthContextInfo(final RSAPublicKey signerKey, final String issuedBy) {
-        this.signerKey = signerKey;
+    private JWTAuthContextInfo(final List<Key> signerKeys, final String issuedBy) {
+        this.signerKeys = Collections.unmodifiableList(signerKeys);
         this.issuedBy = issuedBy;
     }
 
-    public JWTAuthContextInfo(final JWTAuthContextInfo orig) {
-        this.signerKey = orig.signerKey;
-        this.issuedBy = orig.issuedBy;
-        this.expGracePeriodSecs = orig.expGracePeriodSecs;
+    public static JWTAuthContextInfo authContextInfo(final Key signerKey, final String issuedBy) {
+        return new JWTAuthContextInfo(signerKey, issuedBy);
     }
 
-    public RSAPublicKey getSignerKey() {
-        return signerKey;
+    public static JWTAuthContextInfo authContextInfo(final List<Key> signerKeys, final String issuedBy) {
+        return new JWTAuthContextInfo(signerKeys, issuedBy);
     }
 
-    public void setSignerKey(final RSAPublicKey signerKey) {
-        this.signerKey = signerKey;
+    public List<Key> getSignerKeys() {
+        return signerKeys;
     }
 
-    public String getIssuedBy() {
-        return issuedBy;
+    public Key getSignerKey(final String kid) {
+        return signerKeys.get(0);
     }
 
-    public void setIssuedBy(final String issuedBy) {
-        this.issuedBy = issuedBy;
+    public String getIssuedBy() {
+        return issuedBy;
     }
 
     public int getExpGracePeriodSecs() {
         return expGracePeriodSecs;
     }
-
-    public void setExpGracePeriodSecs(final int expGracePeriodSecs) {
-        this.expGracePeriodSecs = expGracePeriodSecs;
-    }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
index feb2008..f19b108 100644
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
+++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipalFactory.java
@@ -50,7 +50,7 @@ public class DefaultJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory
                     .setRequireSubject()
                     .setSkipDefaultAudienceValidation()
                     .setExpectedIssuer(authContextInfo.getIssuedBy())
-                    .setVerificationKey(authContextInfo.getSignerKey())
+                    .setVerificationKey(authContextInfo.getSignerKey(""))
                     .setJwsAlgorithmConstraints(
                             new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST,
                                     AlgorithmIdentifiers.RSA_USING_SHA256));
@@ -89,4 +89,4 @@ public class DefaultJWTCallerPrincipalFactory extends JWTCallerPrincipalFactory
 
         return principal;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/JWTAuthContextInfoProvider.java b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/JWTAuthContextInfoProvider.java
index 6dc1a8f..ee38e49 100644
--- a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/JWTAuthContextInfoProvider.java
+++ b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/JWTAuthContextInfoProvider.java
@@ -33,11 +33,6 @@ public class JWTAuthContextInfoProvider {
 
     @Produces
     Optional<JWTAuthContextInfo> getOptionalContextInfo() throws NoSuchAlgorithmException, InvalidKeySpecException {
-        JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
-
-        // todo use MP Config to load the configuration
-        contextInfo.setIssuedBy("https://server.example.com");
-
         final String pemEncoded = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq" +
                 "Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR" +
                 "TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e" +
@@ -51,9 +46,7 @@ public class JWTAuthContextInfoProvider {
         final KeyFactory kf = KeyFactory.getInstance("RSA");
         final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
 
-        contextInfo.setSignerKey(pk);
-
-        return Optional.of(contextInfo);
+        return Optional.of(JWTAuthContextInfo.authContextInfo(pk, "https://server.example.com"));
     }
 
     @Produces

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/TCKTokenParser.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/TCKTokenParser.java b/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/TCKTokenParser.java
deleted file mode 100644
index e13709d..0000000
--- a/tck/microprofile-tck/jwt/src/test/java/org/apache/tomee/microprofile/tck/jwt/TCKTokenParser.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *     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.tck.jwt;
-
-import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
-import org.apache.tomee.microprofile.jwt.principal.DefaultJWTCallerPrincipalFactory;
-import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory;
-import org.eclipse.microprofile.jwt.JsonWebToken;
-import org.eclipse.microprofile.jwt.tck.util.ITokenParser;
-
-import java.security.PublicKey;
-import java.security.interfaces.RSAPublicKey;
-
-/**
- * MP-JWT TCK harness class to parse a token string
- */
-public class TCKTokenParser implements ITokenParser {
-
-    @Override
-    public JsonWebToken parse(final String bearerToken, final String issuer, final PublicKey publicKey) throws Exception {
-        final JWTAuthContextInfo authContextInfo = new JWTAuthContextInfo((RSAPublicKey) publicKey, issuer);
-        final JWTCallerPrincipalFactory factory = DefaultJWTCallerPrincipalFactory.instance();
-        return factory.parse(bearerToken, authContextInfo);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/tomee/blob/be942d50/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser b/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
deleted file mode 100644
index f8d8098..0000000
--- a/tck/microprofile-tck/jwt/src/test/resources/META-INF/services/org.eclipse.microprofile.jwt.tck.util.ITokenParser
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.tomee.microprofile.tck.jwt.TCKTokenParser