Add more implementations and TCK coverage

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

Branch: refs/heads/master
Commit: 830b372981330bf028b576b155e497b24c85bf9a
Parents: 9c69190
Author: Jean-Louis Monteiro <jeano...@gmail.com>
Authored: Tue Feb 27 09:16:44 2018 +0100
Committer: Jean-Louis Monteiro <jeano...@gmail.com>
Committed: Tue Feb 27 09:16:44 2018 +0100

----------------------------------------------------------------------
 tck/mp-jwt-embedded/pom.xml                     |  11 +
 .../tomee/microprofile/jwt/ClaimLiteral.java    |  32 ++
 .../jwt/ClaimProviderBeanAttributes.java        |  83 ++++
 .../microprofile/jwt/ClaimValueProducer.java    |  75 ++++
 .../microprofile/jwt/ClaimValueWrapper.java     |  54 +++
 .../jwt/JWTAuthContextInfoProvider.java         |  59 +++
 .../jwt/JWTCallerPrincipalFactory.java          |   2 +-
 .../microprofile/jwt/JsonValueProducer.java     | 111 ++++++
 .../apache/tomee/microprofile/jwt/KeyUtils.java |  84 ++++
 .../microprofile/jwt/MPJWTCDIExtension.java     | 391 +++++++++++++++++++
 .../tomee/microprofile/jwt/MPJWTContext.java    |   9 +-
 .../tomee/microprofile/jwt/MPJWTFilter.java     |  25 +-
 .../microprofile/jwt/MPJWTInitializer.java      |   7 +-
 .../tomee/microprofile/jwt/MPJWTProducer.java   | 196 ++++++++++
 .../microprofile/jwt/RawClaimTypeProducer.java  |  69 ++++
 .../javax.enterprise.inject.spi.Extension       |   1 +
 ...e.microprofile.jwt.JWTCallerPrincipalFactory |   1 +
 ...file.jwt.principal.JWTCallerPrincipalFactory |   1 -
 .../jwt/AppDeploymentExtension.java             |  37 ++
 ....jboss.arquillian.core.spi.LoadableExtension |   1 +
 tck/mp-jwt-embedded/src/test/resources/dev.xml  |   8 +-
 21 files changed, 1237 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/pom.xml
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/pom.xml b/tck/mp-jwt-embedded/pom.xml
index ddbccec..272f4ad 100644
--- a/tck/mp-jwt-embedded/pom.xml
+++ b/tck/mp-jwt-embedded/pom.xml
@@ -112,6 +112,16 @@
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.6.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>JwSecTest
+        </configuration>
+      </plugin>
+      <!--
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-dependency-plugin</artifactId>
         <version>2.10</version>
         <executions>
@@ -136,6 +146,7 @@
           </execution>
         </executions>
       </plugin>
+      -->
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimLiteral.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimLiteral.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimLiteral.java
new file mode 100644
index 0000000..5471b2e
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimLiteral.java
@@ -0,0 +1,32 @@
+/*
+ *     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;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.Claims;
+
+public class ClaimLiteral extends AnnotationLiteral<Claim> implements Claim {
+    public String value() {
+        return "";
+    }
+
+    public Claims standard() {
+        return Claims.UNKNOWN;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimProviderBeanAttributes.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimProviderBeanAttributes.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimProviderBeanAttributes.java
new file mode 100644
index 0000000..ce6e97c
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimProviderBeanAttributes.java
@@ -0,0 +1,83 @@
+/*
+ *     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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.enterprise.inject.spi.BeanAttributes;
+
+/**
+ * An implementation of BeanAttributes<Object> that wraps the generic producer 
BeanAttributes
+ * to allow the MPJWTExtension to collect the types of all corresponding 
injection sites
+ *
+ */
+public class ClaimProviderBeanAttributes implements BeanAttributes<Object> {
+    /**
+     * Decorate the ConfigPropertyProducer BeanAttributes to set the types the 
producer applies to. This set is collected
+     * from all injection points annotated with @ConfigProperty.
+     *
+     * @param delegate - the original producer method BeanAttributes
+     * @param types    - the full set of @Claim injection point types
+     */
+    public ClaimProviderBeanAttributes(BeanAttributes<Object> delegate, 
Set<Type> types, Set<Annotation> qualifiers) {
+        this.delegate = delegate;
+        this.types = types;
+        this.qualifiers = qualifiers;
+        if (types.size() == 0) {
+            Thread.dumpStack();
+        }
+    }
+
+    @Override
+    public Set<Type> getTypes() {
+        return types;
+    }
+
+    @Override
+    public Set<Annotation> getQualifiers() {
+        return qualifiers;
+    }
+
+    @Override
+    public Class<? extends Annotation> getScope() {
+        return delegate.getScope();
+    }
+
+    @Override
+    public String getName() {
+        return delegate.getName();
+    }
+
+    @Override
+    public Set<Class<? extends Annotation>> getStereotypes() {
+        return delegate.getStereotypes();
+    }
+
+    @Override
+    public boolean isAlternative() {
+        return delegate.isAlternative();
+    }
+
+    private BeanAttributes<Object> delegate;
+
+    private Set<Type> types;
+
+    private Set<Annotation> qualifiers;
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueProducer.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueProducer.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueProducer.java
new file mode 100644
index 0000000..ae2338f
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueProducer.java
@@ -0,0 +1,75 @@
+/*
+ *     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;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Optional;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.Claims;
+
+/**
+ * A producer for the ClaimValue<T> wrapper injection sites.
+ * @param <T> the raw claim type
+ */
+public class ClaimValueProducer<T> {
+
+    @Produces
+    @Claim("")
+    ClaimValue<T> produce(InjectionPoint ip) {
+        String name = getName(ip);
+        ClaimValue<Optional<T>> cv = 
MPJWTProducer.generalClaimValueProducer(name);
+        ClaimValue<T> returnValue = (ClaimValue<T>) cv;
+        Optional<T> value = cv.getValue();
+        // Pull out the ClaimValue<T> T type,
+        Type matchType = ip.getType();
+        Type actualType = Object.class;
+        boolean isOptional = false;
+        if (matchType instanceof ParameterizedType) {
+            actualType = ((ParameterizedType) 
matchType).getActualTypeArguments()[0];
+            isOptional = 
matchType.getTypeName().equals(Optional.class.getTypeName());
+            if (isOptional) {
+                actualType = ((ParameterizedType) 
matchType).getActualTypeArguments()[0];
+            }
+        }
+
+        if 
(!actualType.getTypeName().startsWith(Optional.class.getTypeName())) {
+            T nestedValue = value.orElse(null);
+            ClaimValueWrapper<T> wrapper = new 
ClaimValueWrapper<>(cv.getName());
+            wrapper.setValue(nestedValue);
+            returnValue = wrapper;
+        }
+        return returnValue;
+    }
+
+    String getName(InjectionPoint ip) {
+        String name = null;
+        for (Annotation ann : ip.getQualifiers()) {
+            if (ann instanceof Claim) {
+                Claim claim = (Claim) ann;
+                name = claim.standard() == Claims.UNKNOWN ? claim.value() : 
claim.standard().name();
+            }
+        }
+        return name;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueWrapper.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueWrapper.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueWrapper.java
new file mode 100644
index 0000000..cc16771
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/ClaimValueWrapper.java
@@ -0,0 +1,54 @@
+/*
+ *     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;
+
+import org.eclipse.microprofile.jwt.ClaimValue;
+
+/**
+ * An implementation of the ClaimValue interface
+ *
+ * @param <T> the claim value type
+ */
+public class ClaimValueWrapper<T> implements ClaimValue<T> {
+    private String name;
+
+    private T value;
+
+    public ClaimValueWrapper(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public T getValue() {
+        return value;
+    }
+
+    public void setValue(T value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ClaimValueWrapper[@%s], name=%s, value[%s]=%s", 
Integer.toHexString(hashCode()),
+                name, value.getClass(), value);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
new file mode 100644
index 0000000..a173ea2
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
@@ -0,0 +1,59 @@
+/*
+ *     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;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Optional;
+
+@Dependent
+public class JWTAuthContextInfoProvider {
+
+    @Produces
+    Optional<JWTAuthContextInfo> getOptionalContextInfo() {
+        JWTAuthContextInfo contextInfo = new JWTAuthContextInfo();
+
+        // todo use MP Config to load the configuration
+        contextInfo.setIssuedBy("https://server.example.com";);
+        RSAPublicKey pk = null;
+        try {
+            pk = (RSAPublicKey) KeyUtils.decodePublicKey("-----BEGIN RSA 
PUBLIC KEY-----\n" +
+                    
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq\n" +
+                    
"Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR\n" +
+                    
"TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e\n" +
+                    
"UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9\n" +
+                    
"AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn\n" +
+                    
"sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x\n" +
+                    "nQIDAQAB\n" +
+                    "-----END RSA PUBLIC KEY-----\n");
+
+        } catch (final Exception e) {
+            e.printStackTrace();
+            // todo better handling
+            throw new RuntimeException(e);
+        }
+        contextInfo.setSignerKey(pk);
+
+        return Optional.of(contextInfo);
+    }
+
+    @Produces
+    JWTAuthContextInfo getContextInfo() {
+        return getOptionalContextInfo().get();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTCallerPrincipalFactory.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTCallerPrincipalFactory.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTCallerPrincipalFactory.java
index a64f95a..cb00cc5 100644
--- 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTCallerPrincipalFactory.java
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JWTCallerPrincipalFactory.java
@@ -83,7 +83,7 @@ public abstract class JWTCallerPrincipalFactory {
 
         if (instance == null) {
             ServiceLoader<JWTCallerPrincipalFactory> sl = 
ServiceLoader.load(JWTCallerPrincipalFactory.class, cl);
-            URL u = 
cl.getResource("/META-INF/services/org.eclipse.microprofile.jwt.principal.JWTCallerPrincipalFactory");
+            URL u = 
cl.getResource("/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory");
             System.out.printf("JWTCallerPrincipalFactory, cl=%s, u=%s, 
sl=%s\n", cl, u, sl);
             try {
                 for (JWTCallerPrincipalFactory spi : sl) {

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JsonValueProducer.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JsonValueProducer.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JsonValueProducer.java
new file mode 100644
index 0000000..355b1d5
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/JsonValueProducer.java
@@ -0,0 +1,111 @@
+/*
+ *     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;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.Claims;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * A producer for JsonValue injection types
+ */
+public class JsonValueProducer {
+    private static Logger log = 
Logger.getLogger(JsonValueProducer.class.getName());
+
+    @Produces
+    @Claim("")
+    public JsonString getJsonString(InjectionPoint ip) {
+        return getValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public Optional<JsonString> getOptionalJsonString(InjectionPoint ip) {
+        return getOptionalValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public JsonNumber getJsonNumber(InjectionPoint ip) {
+        return getValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public Optional<JsonNumber> getOptionalJsonNumber(InjectionPoint ip) {
+        return getOptionalValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public JsonArray getJsonArray(InjectionPoint ip) {
+        return getValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public Optional<JsonArray> getOptionalJsonArray(InjectionPoint ip) {
+        return getOptionalValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public JsonObject getJsonObject(InjectionPoint ip) {
+        return getValue(ip);
+    }
+
+    @Produces
+    @Claim("")
+    public Optional<JsonObject> getOptionalJsonObject(InjectionPoint ip) {
+        return getOptionalValue(ip);
+    }
+
+    public <T extends JsonValue> T getValue(InjectionPoint ip) {
+        log.fine(String.format("JsonValueProducer(%s).produce", ip));
+        String name = getName(ip);
+        T jsonValue = (T) MPJWTProducer.generalJsonValueProducer(name);
+        return jsonValue;
+    }
+
+    public <T extends JsonValue> Optional<T> getOptionalValue(InjectionPoint 
ip) {
+        log.fine(String.format("JsonValueProducer(%s).produce", ip));
+        String name = getName(ip);
+        T jsonValue = (T) MPJWTProducer.generalJsonValueProducer(name);
+        return Optional.ofNullable(jsonValue);
+    }
+
+    String getName(InjectionPoint ip) {
+        String name = null;
+        for (Annotation ann : ip.getQualifiers()) {
+            if (ann instanceof Claim) {
+                Claim claim = (Claim) ann;
+                name = claim.standard() == Claims.UNKNOWN ? claim.value() : 
claim.standard().name();
+            }
+        }
+        return name;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/KeyUtils.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/KeyUtils.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/KeyUtils.java
new file mode 100644
index 0000000..07e00f2
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/KeyUtils.java
@@ -0,0 +1,84 @@
+/*
+ *     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;
+
+import java.io.InputStream;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+public class KeyUtils {
+    public static PrivateKey readPrivateKey(String pemResName) throws 
Exception {
+        InputStream contentIS = KeyUtils.class.getResourceAsStream(pemResName);
+        byte[] tmp = new byte[4096];
+        int length = contentIS.read(tmp);
+        PrivateKey privateKey = decodePrivateKey(new String(tmp, 0, length));
+        return privateKey;
+    }
+
+    public static PublicKey readPublicKey(String pemResName) throws Exception {
+        InputStream contentIS = KeyUtils.class.getResourceAsStream(pemResName);
+        byte[] tmp = new byte[4096];
+        int length = contentIS.read(tmp);
+        PublicKey publicKey = decodePublicKey(new String(tmp, 0, length));
+        return publicKey;
+    }
+
+    public static KeyPair generateKeyPair(int keySize) throws 
NoSuchAlgorithmException {
+        KeyPairGenerator keyPairGenerator = 
KeyPairGenerator.getInstance("RSA");
+        keyPairGenerator.initialize(keySize);
+        KeyPair keyPair = keyPairGenerator.genKeyPair();
+        return keyPair;
+    }
+
+    public static PrivateKey decodePrivateKey(String pemEncoded) throws 
Exception {
+        pemEncoded = removeBeginEnd(pemEncoded);
+        byte[] pkcs8EncodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+        // extract the private key
+
+        PKCS8EncodedKeySpec keySpec = new 
PKCS8EncodedKeySpec(pkcs8EncodedBytes);
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        PrivateKey privKey = kf.generatePrivate(keySpec);
+        return privKey;
+    }
+
+    public static PublicKey decodePublicKey(String pemEncoded) throws 
Exception {
+        pemEncoded = removeBeginEnd(pemEncoded);
+        byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+        X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+        KeyFactory kf = KeyFactory.getInstance("RSA");
+        return kf.generatePublic(spec);
+    }
+
+    private static String removeBeginEnd(String pem) {
+        pem = pem.replaceAll("-----BEGIN(.*)KEY-----", "");
+        pem = pem.replaceAll("-----END(.*)KEY-----", "");
+        pem = pem.replaceAll("\r\n", "");
+        pem = pem.replaceAll("\n", "");
+        return pem.trim();
+    }
+    private KeyUtils() {
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTCDIExtension.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTCDIExtension.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTCDIExtension.java
new file mode 100644
index 0000000..aa15a33
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTCDIExtension.java
@@ -0,0 +1,391 @@
+/*
+ *     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;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.Claims;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.BeanAttributes;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.DeploymentException;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.ProcessBeanAttributes;
+import javax.enterprise.inject.spi.ProcessInjectionPoint;
+import javax.enterprise.inject.spi.ProcessProducer;
+import javax.inject.Provider;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+import java.util.logging.Logger;
+
+/**
+ * A CDI extension that provides a producer for the current authenticated 
JsonWebToken based on a thread
+ * local value that is managed by the {@link JWTAuthMechanism} request
+ * authentication handler.
+ * <p>
+ * This also installs the producer methods for the discovered:
+ * <ul>
+ * <li>@Claim ClaimValue<T> injection sites.</li>
+ * <li>@Claim raw type<T> injection sites.</li>
+ * <li>@Claim JsonValue injection sites.</li>
+ * </ul>
+ *
+ * @see JWTAuthMechanism
+ */
+public class MPJWTCDIExtension implements Extension {
+    private static Logger log = 
Logger.getLogger(MPJWTCDIExtension.class.getName());
+
+    /**
+     * Register the MPJWTProducer JsonWebToken producer bean
+     *
+     * @param bbd         before discovery event
+     * @param beanManager cdi bean manager
+     */
+    public void observeBeforeBeanDiscovery(@Observes BeforeBeanDiscovery bbd, 
BeanManager beanManager) {
+        log.fine(String.format("MPJWTExtension(), added 
JWTPrincipalProducer"));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(TCKTokenParser.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTFilter.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTInitializer.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(JWTAuthContextInfoProvider.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(RawClaimTypeProducer.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(ClaimValueProducer.class));
+        
bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonValueProducer.class));
+    }
+
+    /**
+     * Replace the general producer method BeanAttributes with one bound to 
the collected injection site
+     * types to properly reflect all of the type locations the producer method 
applies to.
+     *
+     * @param pba the ProcessBeanAttributes
+     * @see ClaimProviderBeanAttributes
+     */
+    public void addTypeToClaimProducer(@Observes ProcessBeanAttributes pba) {
+        if (pba.getAnnotated().isAnnotationPresent(Claim.class)) {
+            Claim claim = pba.getAnnotated().getAnnotation(Claim.class);
+            if (claim.value().length() == 0 && claim.standard() == 
Claims.UNKNOWN) {
+                log.fine(String.format("addTypeToClaimProducer: %s\n", 
pba.getAnnotated()));
+                BeanAttributes delegate = pba.getBeanAttributes();
+                String name = delegate.getName();
+                if (delegate.getTypes().contains(Optional.class)) {
+                    if (providerOptionalTypes.size() == 0) {
+                        providerOptionalTypes.add(Optional.class);
+                    }
+                    pba.setBeanAttributes(new 
ClaimProviderBeanAttributes(delegate, providerOptionalTypes, 
providerQualifiers));
+                    // This is
+                } else if (name != null && 
name.startsWith("RawClaimTypeProducer#")) {
+                    if (rawTypes.size() == 0) {
+                        rawTypes.add(Object.class);
+                    }
+                    pba.setBeanAttributes(new 
ClaimProviderBeanAttributes(delegate, rawTypes, rawTypeQualifiers));
+                    log.fine(String.format("Setup RawClaimTypeProducer 
BeanAttributes"));
+                }
+            }
+        }
+    }
+
+    public void afterDeploymentValidation(@Observes AfterDeploymentValidation 
event, BeanManager beanManager) {
+    }
+
+    void doProcessProducers(@Observes ProcessProducer pp) {
+    }
+
+    /**
+     * Handle the non-{@linkplain Provider}, {@linkplain 
org.eclipse.microprofile.jwt.ClaimValue}, and
+     * {@linkplain javax.json.JsonValue} claim injection types.
+     *
+     * @param pip - the injection point event information
+     * @see RawClaimTypeProducer
+     */
+    void processClaimInjections(@Observes ProcessInjectionPoint pip) {
+        log.fine(String.format("pipRaw: %s", pip.getInjectionPoint()));
+        InjectionPoint ip = pip.getInjectionPoint();
+        if (ip.getAnnotated().isAnnotationPresent(Claim.class)) {
+            Claim claim = ip.getAnnotated().getAnnotation(Claim.class);
+            if (ip.getType() instanceof Class) {
+                Class rawClass = (Class) ip.getType();
+                // Primative types
+                if (Modifier.isFinal(rawClass.getModifiers())) {
+                    rawTypes.add(ip.getType());
+                    rawTypeQualifiers.add(claim);
+                    log.fine(String.format("+++ Added Claim raw type: %s", 
ip.getType()));
+                    Class declaringClass = ip.getMember().getDeclaringClass();
+                    Annotation[] appScoped = 
declaringClass.getAnnotationsByType(ApplicationScoped.class);
+                    Annotation[] sessionScoped = 
declaringClass.getAnnotationsByType(SessionScoped.class);
+                    if ((appScoped != null && appScoped.length > 0) || 
(sessionScoped != null && sessionScoped.length > 0)) {
+                        String err = String.format("A raw type cannot be 
injected into application/session scope: IP=%s", ip);
+                        pip.addDefinitionError(new DeploymentException(err));
+                    }
+                }
+                // This handles collections of primative types
+            } else if (isRawParameterizedType(ip.getType())) {
+                log.fine(String.format("+++ Added Claim ParameterizedType: 
%s", ip.getType()));
+                rawTypes.add(ip.getType());
+                rawTypeQualifiers.add(claim);
+            }
+        } else {
+            log.fine(String.format("Skipping pip: %s, type: %s/%s", ip, 
ip.getType(), ip.getType().getClass()));
+        }
+    }
+
+    /**
+     * Collect the types of all {@linkplain Provider} injection points 
annotated with {@linkplain Claim}.
+     *
+     * @param pip - the injection point event information
+     */
+    void processClaimProviderInjections(@Observes ProcessInjectionPoint<?, ? 
extends Provider> pip) {
+        log.fine(String.format("pip: %s", pip.getInjectionPoint()));
+        final InjectionPoint ip = pip.getInjectionPoint();
+        if (ip.getAnnotated().isAnnotationPresent(Claim.class)) {
+            Claim claim = ip.getAnnotated().getAnnotation(Claim.class);
+            if (claim.value().length() == 0 && claim.standard() == 
Claims.UNKNOWN) {
+                pip.addDefinitionError(new DeploymentException("@Claim at: " + 
ip + " has no name or valid standard enum setting"));
+            }
+            boolean usesEnum = claim.standard() != Claims.UNKNOWN;
+            final String claimName = usesEnum ? claim.standard().name() : 
claim.value();
+            log.fine(String.format("Checking Provider Claim(%s), ip: %s", 
claimName, ip));
+            ClaimIP claimIP = claims.get(claimName);
+            Type matchType = ip.getType();
+            // The T from the Provider<T> injection site
+            Type actualType = ((ParameterizedType) 
matchType).getActualTypeArguments()[0];
+            // Don't add Optional or JsonValue as this is handled specially
+            if (!optionalOrJsonValue(actualType)) {
+                rawTypes.add(actualType);
+            } else if 
(!actualType.getTypeName().startsWith("javax.json.Json")) {
+                // Validate that this is not an Optional<JsonValue>
+                Type innerType = ((ParameterizedType) 
actualType).getActualTypeArguments()[0];
+                if (!innerType.getTypeName().startsWith("javax.json.Json")) {
+                    providerOptionalTypes.add(actualType);
+                    providerQualifiers.add(claim);
+                }
+            }
+            rawTypeQualifiers.add(claim);
+            ClaimIPType key = new ClaimIPType(claimName, actualType);
+            if (claimIP == null) {
+                claimIP = new ClaimIP(actualType, actualType, false, claim);
+                claimIP.setProviderSite(true);
+                claims.put(key, claimIP);
+            }
+            claimIP.getInjectionPoints().add(ip);
+            log.fine(String.format("+++ Added Provider Claim(%s) ip: %s", 
claimName, ip));
+
+        }
+    }
+
+    /**
+     * Create producer methods for each ClaimValue injection site
+     *
+     * @param event       - AfterBeanDiscovery
+     * @param beanManager - CDI bean manager
+     */
+    void observesAfterBeanDiscovery(@Observes final AfterBeanDiscovery event, 
final BeanManager beanManager) {
+        log.fine(String.format("observesAfterBeanDiscovery, %s", claims));
+        installClaimValueProducerMethodsViaSyntheticBeans(event, beanManager);
+
+        //installClaimValueProducesViaTemplateType(event, beanManager);
+    }
+
+    /**
+     * Create a synthetic bean with a custom Producer for the non-Provider 
injection sites.
+     *
+     * @param event       - AfterBeanDiscovery
+     * @param beanManager - CDI bean manager
+     */
+    private void installClaimValueProducerMethodsViaSyntheticBeans(final 
AfterBeanDiscovery event, final BeanManager beanManager) {
+
+    }
+
+    private boolean optionalOrJsonValue(Type type) {
+        boolean isOptionOrJson = 
type.getTypeName().startsWith(Optional.class.getTypeName())
+                | type.getTypeName().startsWith("javax.json.Json");
+        return isOptionOrJson;
+    }
+
+    private boolean isRawParameterizedType(Type type) {
+        boolean isRawParameterizedType = false;
+        if (type instanceof ParameterizedType) {
+            ParameterizedType ptype = ParameterizedType.class.cast(type);
+            Type rawType = ptype.getRawType();
+            String rawTypeName = rawType.getTypeName();
+            isRawParameterizedType = 
!rawTypeName.startsWith("org.eclipse.microprofile.jwt");
+        }
+        return isRawParameterizedType;
+    }
+
+    /**
+     * A map of claim,type pairs to the injection site information
+     */
+    private HashMap<ClaimIPType, ClaimIP> claims = new HashMap<>();
+
+    private Set<Type> providerOptionalTypes = new HashSet<>();
+
+    private Set<Type> providerTypes = new HashSet<>();
+
+    private Set<Type> rawTypes = new HashSet<>();
+
+    private Set<Annotation> rawTypeQualifiers = new HashSet<>();
+
+    private Set<Annotation> providerQualifiers = new HashSet<>();
+
+    /**
+     * A key for a claim,injection site type pair
+     */
+    public static class ClaimIPType implements Comparable<ClaimIPType> {
+        public ClaimIPType(String claimName, Type ipType) {
+            this.claimName = claimName;
+            this.ipType = ipType;
+        }
+
+        /**
+         * Order the @Claim ClaimValue<T> on the @Claim.value and then T type 
name
+         *
+         * @param o - ClaimIP to compare to
+         * @return the ordering of this claim relative to o
+         */
+        @Override
+        public int compareTo(ClaimIPType o) {
+            int compareTo = claimName.compareTo(o.claimName);
+            if (compareTo == 0) {
+                compareTo = 
ipType.getTypeName().compareTo(o.ipType.getTypeName());
+            }
+            return compareTo;
+        }
+
+        private String claimName;
+
+        private Type ipType;
+    }
+
+    /**
+     * The representation of an @Claim annotated injection site
+     */
+    public static class ClaimIP {
+        /**
+         * Create a ClaimIP from the injection site information
+         *
+         * @param matchType  - the outer type of the injection site
+         * @param valueType  - the parameterized type of the injection site
+         * @param isOptional - is the injection site an Optional
+         * @param claim      - the Claim qualifier
+         */
+        public ClaimIP(Type matchType, Type valueType, boolean isOptional, 
Claim claim) {
+            this.matchType = matchType;
+            this.valueType = valueType;
+            this.claim = claim;
+        }
+
+        public Type getMatchType() {
+            return matchType;
+        }
+
+        public String getClaimName() {
+            return claim.standard() == Claims.UNKNOWN ? claim.value() : 
claim.standard().name();
+        }
+
+        public Claim getClaim() {
+            return claim;
+        }
+
+        public Type getValueType() {
+            return valueType;
+        }
+
+        public boolean isOptional() {
+            return isOptional;
+        }
+
+        public boolean isProviderSite() {
+            return isProviderSite;
+        }
+
+        public void setProviderSite(boolean providerSite) {
+            this.isProviderSite = providerSite;
+        }
+
+        public boolean isNonStandard() {
+            return isNonStandard;
+        }
+
+        public void setNonStandard(boolean nonStandard) {
+            isNonStandard = nonStandard;
+        }
+
+        public boolean isJsonValue() {
+            return isJsonValue;
+        }
+
+        public void setJsonValue(boolean jsonValue) {
+            isJsonValue = jsonValue;
+        }
+
+        public Set<InjectionPoint> getInjectionPoints() {
+            return injectionPoints;
+        }
+
+        @Override
+        public String toString() {
+            return "ClaimIP{" +
+                    "type=" + matchType +
+                    ", claim=" + claim +
+                    ", ips=" + injectionPoints +
+                    '}';
+        }
+
+        /**
+         * The injection site value type
+         */
+        private Type matchType;
+
+        /**
+         * The actual type of of the ParameterizedType matchType
+         */
+        private Type valueType;
+
+        /**
+         * Is valueType actually wrapped in an Optional
+         */
+        private boolean isOptional;
+
+        private boolean isProviderSite;
+
+        private boolean isNonStandard;
+
+        private boolean isJsonValue;
+
+        /**
+         * The injection site @Claim annotation value
+         */
+        private Claim claim;
+
+        /**
+         * The location that share the @Claim/type combination
+         */
+        private HashSet<InjectionPoint> injectionPoints = new HashSet<>();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTContext.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTContext.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTContext.java
index bffccf2..07dfe0b 100644
--- 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTContext.java
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTContext.java
@@ -27,12 +27,11 @@ import java.util.function.Predicate;
 /**
  * Responsible for holding the runtime model
  */
-@ApplicationScoped
 public class MPJWTContext {
 
-    private final ConcurrentMap<MPJWTConfigKey, MPJWTConfigValue> 
configuration = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<MPJWTConfigKey, MPJWTConfigValue> 
configuration = new ConcurrentHashMap<>();
 
-    public MPJWTConfigValue addMapping(final MPJWTConfigKey key, final 
MPJWTConfigValue value) {
+    public static MPJWTConfigValue addMapping(final MPJWTConfigKey key, final 
MPJWTConfigValue value) {
         Objects.requireNonNull(key, "MP JWT Key is required");
         Objects.requireNonNull(value, "MP JWT Value is required");
 
@@ -44,12 +43,12 @@ public class MPJWTContext {
         return value;
     }
 
-    public Optional<MPJWTConfigValue> get(final MPJWTConfigKey key) {
+    public static Optional<MPJWTConfigValue> get(final MPJWTConfigKey key) {
         Objects.requireNonNull(key, "MP JWT Key is required to retrieve the 
configuration");
         return Optional.ofNullable(configuration.get(key));
     }
 
-    public Optional<Map.Entry<MPJWTConfigKey, MPJWTConfigValue>> 
findFirst(final String path) {
+    public static Optional<Map.Entry<MPJWTConfigKey, MPJWTConfigValue>> 
findFirst(final String path) {
         return configuration.entrySet()
                 .stream()
                 .filter(new Predicate<ConcurrentMap.Entry<MPJWTConfigKey, 
MPJWTConfigValue>>() {

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
index 092ad9d..a8f7cb4 100644
--- 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java
@@ -38,9 +38,6 @@ import java.util.Optional;
 public class MPJWTFilter implements Filter {
 
     @Inject
-    private MPJWTContext context;
-
-    @Inject
     private JWTAuthContextInfo authContextInfo;
 
     @Override
@@ -54,16 +51,31 @@ public class MPJWTFilter implements Filter {
 
         final HttpServletRequest httpServletRequest = (HttpServletRequest) 
request;
         final Optional<Map.Entry<MPJWTContext.MPJWTConfigKey, 
MPJWTContext.MPJWTConfigValue>> first =
-                context.findFirst(httpServletRequest.getRequestURI());
+                MPJWTContext.findFirst(httpServletRequest.getRequestURI());
 
-        if (first.isPresent()) { // nothing found in the context
+        if (!first.isPresent()) { // nothing found in the context
             chain.doFilter(request, response);
+            return;
         }
 
         // todo get JWT and do validation
         // todo not sure what to do with the realm
 
-        final JsonWebToken jsonWebToken = null; // will be build during 
validation
+        final String authorizationHeader = ((HttpServletRequest) 
request).getHeader("Authorization");
+        final String token = authorizationHeader.substring("bearer ".length());
+        final JsonWebToken jsonWebToken;
+        try {
+            jsonWebToken = 
DefaultJWTCallerPrincipalFactory.instance().parse(token, authContextInfo);
+
+        } catch (final ParseException e) {
+            // todo properly handle the exception as required per spec
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+
+        // associate with the producer. Should not be needed.
+        // todo We should be able to retrieve it based on the HTTP Servlet 
Request in the producer
+        MPJWTProducer.setJWTPrincipal(jsonWebToken);
 
         // now wrap the httpServletRequest and override the principal so CXF 
can propagate into the SecurityContext
         chain.doFilter(new HttpServletRequestWrapper(httpServletRequest) {
@@ -85,6 +97,7 @@ public class MPJWTFilter implements Filter {
 
         }, response);
 
+
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
index dc3d7ba..bb8bb16 100644
--- 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTInitializer.java
@@ -34,9 +34,6 @@ import java.util.Set;
 @HandlesTypes(LoginConfig.class)
 public class MPJWTInitializer implements ServletContainerInitializer {
 
-    @Inject
-    private MPJWTContext context;
-
     @Override
     public void onStartup(final Set<Class<?>> classes, final ServletContext 
ctx) throws ServletException {
 
@@ -59,11 +56,13 @@ public class MPJWTInitializer implements 
ServletContainerInitializer {
 
             final FilterRegistration.Dynamic mpJwtFilter = 
ctx.addFilter("mp-jwt-filter", MPJWTFilter.class);
             mpJwtFilter.setAsyncSupported(true);
+            mpJwtFilter.addMappingForUrlPatterns(null, false, "/*");
 
-            context.addMapping(
+            MPJWTContext.addMapping(
                     new MPJWTContext.MPJWTConfigKey(
                             ctx.getContextPath(),
                             applicationPath == null ? "" : 
applicationPath.value()),
+
                     new MPJWTContext.MPJWTConfigValue(
                             loginConfig.authMethod(),
                             loginConfig.realmName())

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTProducer.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTProducer.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTProducer.java
new file mode 100644
index 0000000..195f323
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTProducer.java
@@ -0,0 +1,196 @@
+/*
+ *     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;
+
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Destroyed;
+import javax.enterprise.context.Initialized;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Produces;
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import javax.json.JsonValue;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ * A class that tracks the current validated MP-JWT and associated 
JsonWebToken via a thread
+ * local to provide a @RequestScoped JsonWebToken producer method.
+ * <p>
+ * It also provides utility methods for access the current JsonWebToken claim 
values.
+ */
+@ApplicationScoped
+public class MPJWTProducer {
+    private static Logger log = 
Logger.getLogger(MPJWTProducer.class.getName());
+    private static final String TMP = "tmp";
+    private static ThreadLocal<JsonWebToken> currentPrincipal = new 
ThreadLocal<>();
+
+    public static void setJWTPrincipal(JsonWebToken principal) {
+        currentPrincipal.set(principal);
+    }
+
+    public static JsonWebToken getJWTPrincpal() {
+        return currentPrincipal.get();
+    }
+
+    @PostConstruct
+    void init() {
+        log.fine("MPJWTProducer initialized");
+    }
+
+    void observeRequestInitialized(@Observes @Initialized(RequestScoped.class) 
Object event) {
+        log.finest(String.format("observeRequestInitialized, event=%s", 
event));
+    }
+
+    void observeRequestDestroyed(@Observes @Destroyed(RequestScoped.class) 
Object event) {
+        log.finest(String.format("observeRequestDestroyed, event=%s", event));
+    }
+
+    /**
+     * The @RequestScoped producer method for the current JsonWebToken
+     *
+     * @return
+     */
+    @Produces
+    @RequestScoped
+    JsonWebToken currentPrincipalOrNull() {
+        return currentPrincipal.get();
+    }
+
+    /**
+     * A utility method for accessing a claim from the current JsonWebToken as 
a ClaimValue<Optional<T>> object.
+     *
+     * @param name - name of the claim
+     * @param <T>  expected actual type of the claim
+     * @return the claim value wrapper object
+     */
+    static <T> ClaimValue<Optional<T>> generalClaimValueProducer(String name) {
+        ClaimValueWrapper<Optional<T>> wrapper = new ClaimValueWrapper<>(name);
+        T value = getValue(name, false);
+        Optional<T> optValue = Optional.ofNullable(value);
+        wrapper.setValue(optValue);
+        return wrapper;
+    }
+
+    /**
+     * Return the indicated claim value as a JsonValue
+     *
+     * @param name - name of the claim
+     * @return a JsonValue wrapper
+     */
+    static JsonValue generalJsonValueProducer(String name) {
+        Object value = getValue(name, false);
+        JsonValue jsonValue = wrapValue(value);
+        return jsonValue;
+    }
+
+    public static <T> T getValue(String name, boolean isOptional) {
+        JsonWebToken jwt = getJWTPrincpal();
+        if (jwt == null) {
+            log.fine(String.format("getValue(%s), null JsonWebToken", name));
+            return null;
+        }
+
+        Optional<T> claimValue = jwt.claim(name);
+        if (!isOptional && !claimValue.isPresent()) {
+            log.fine(String.format("Failed to find Claim for: %s", name));
+        }
+        log.fine(String.format("getValue(%s), isOptional=%s, claimValue=%s", 
name, isOptional, claimValue));
+        return claimValue.orElse(null);
+    }
+
+    static JsonObject replaceMap(Map<String, Object> map) {
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            Object entryValue = entry.getValue();
+            if (entryValue instanceof Map) {
+                JsonObject entryJsonObject = replaceMap((Map<String, Object>) 
entryValue);
+                builder.add(entry.getKey(), entryJsonObject);
+            } else if (entryValue instanceof List) {
+                JsonArray array = (JsonArray) wrapValue(entryValue);
+                builder.add(entry.getKey(), array);
+            } else if (entryValue instanceof Long || entryValue instanceof 
Integer) {
+                long lvalue = ((Number) entryValue).longValue();
+                builder.add(entry.getKey(), lvalue);
+            } else if (entryValue instanceof Double || entryValue instanceof 
Float) {
+                double dvalue = ((Number) entryValue).doubleValue();
+                builder.add(entry.getKey(), dvalue);
+            } else if (entryValue instanceof Boolean) {
+                boolean flag = ((Boolean) entryValue).booleanValue();
+                builder.add(entry.getKey(), flag);
+            } else if (entryValue instanceof String) {
+                builder.add(entry.getKey(), entryValue.toString());
+            }
+        }
+        return builder.build();
+    }
+
+    static JsonValue wrapValue(Object value) {
+        JsonValue jsonValue = null;
+        if (value instanceof JsonValue) {
+            // This may already be a JsonValue
+            jsonValue = (JsonValue) value;
+        } else if (value instanceof String) {
+            jsonValue = Json.createObjectBuilder()
+                    .add(TMP, value.toString())
+                    .build()
+                    .getJsonString(TMP);
+        } else if (value instanceof Number) {
+            Number number = (Number) value;
+            if ((number instanceof Long) || (number instanceof Integer)) {
+                jsonValue = Json.createObjectBuilder()
+                        .add(TMP, number.longValue())
+                        .build()
+                        .getJsonNumber(TMP);
+            } else {
+                jsonValue = Json.createObjectBuilder()
+                        .add(TMP, number.doubleValue())
+                        .build()
+                        .getJsonNumber(TMP);
+            }
+        } else if (value instanceof Boolean) {
+            Boolean flag = (Boolean) value;
+            jsonValue = flag ? JsonValue.TRUE : JsonValue.FALSE;
+        } else if (value instanceof Collection) {
+            JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+            Collection list = (Collection) value;
+            for (Object element : list) {
+                if (element instanceof String) {
+                    arrayBuilder.add(element.toString());
+                } else {
+                    JsonValue jvalue = wrapValue(element);
+                    arrayBuilder.add(jvalue);
+                }
+            }
+            jsonValue = arrayBuilder.build();
+        } else if (value instanceof Map) {
+            jsonValue = replaceMap((Map) value);
+        }
+        return jsonValue;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/RawClaimTypeProducer.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/RawClaimTypeProducer.java
 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/RawClaimTypeProducer.java
new file mode 100644
index 0000000..b52912c
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/java/org/apache/tomee/microprofile/jwt/RawClaimTypeProducer.java
@@ -0,0 +1,69 @@
+/*
+ *     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;
+
+import org.eclipse.microprofile.jwt.Claim;
+import org.eclipse.microprofile.jwt.ClaimValue;
+import org.eclipse.microprofile.jwt.Claims;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.inject.Named;
+import java.lang.annotation.Annotation;
+import java.util.Optional;
+import java.util.logging.Logger;
+
+/**
+ *
+ */
+public class RawClaimTypeProducer {
+    private static Logger log = 
Logger.getLogger(RawClaimTypeProducer.class.getName());
+
+    @Produces
+    @Claim("")
+    @Named("RawClaimTypeProducer#getValue")
+    public Object getValue(InjectionPoint ip) {
+        log.fine(String.format("getValue(%s)", ip));
+        String name = getName(ip);
+        ClaimValue<Optional<Object>> cv = 
MPJWTProducer.generalClaimValueProducer(name);
+        Optional<Object> value = cv.getValue();
+        Object returnValue = value.orElse(null);
+        return returnValue;
+    }
+
+    @Produces
+    @Claim("")
+    @Named("RawClaimTypeProducer#getOptionalValue")
+    public Optional getOptionalValue(InjectionPoint ip) {
+        log.fine(String.format("getOptionalValue(%s)", ip));
+        String name = getName(ip);
+        ClaimValue<Optional<Object>> cv = 
MPJWTProducer.generalClaimValueProducer(name);
+        Optional<Object> value = cv.getValue();
+        return value;
+    }
+
+    String getName(InjectionPoint ip) {
+        String name = null;
+        for (Annotation ann : ip.getQualifiers()) {
+            if (ann instanceof Claim) {
+                Claim claim = (Claim) ann;
+                name = claim.standard() == Claims.UNKNOWN ? claim.value() : 
claim.standard().name();
+            }
+        }
+        return name;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
 
b/tck/mp-jwt-embedded/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
new file mode 100644
index 0000000..5e3bccc
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.MPJWTCDIExtension
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory
 
b/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory
new file mode 100644
index 0000000..67f39db
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.apache.tomee.microprofile.jwt.JWTCallerPrincipalFactory
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.DefaultJWTCallerPrincipalFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.eclipse.microprofile.jwt.principal.JWTCallerPrincipalFactory
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.eclipse.microprofile.jwt.principal.JWTCallerPrincipalFactory
 
b/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.eclipse.microprofile.jwt.principal.JWTCallerPrincipalFactory
deleted file mode 100644
index 67f39db..0000000
--- 
a/tck/mp-jwt-embedded/src/main/resources/META-INF/services/org.eclipse.microprofile.jwt.principal.JWTCallerPrincipalFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.apache.tomee.microprofile.jwt.DefaultJWTCallerPrincipalFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
 
b/tck/mp-jwt-embedded/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
new file mode 100644
index 0000000..4ade364
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/test/java/org/apache/tomee/microprofile/jwt/AppDeploymentExtension.java
@@ -0,0 +1,37 @@
+package org.apache.tomee.microprofile.jwt;
+
+import 
org.jboss.arquillian.container.spi.client.deployment.DeploymentDescription;
+import 
org.jboss.arquillian.container.test.impl.client.deployment.AnnotationDeploymentScenarioGenerator;
+import 
org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
+import org.jboss.arquillian.core.spi.LoadableExtension;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+
+import java.util.Collections;
+import java.util.List;
+
+public class AppDeploymentExtension implements LoadableExtension {
+    @Override
+    public void register(final ExtensionBuilder extensionBuilder) {
+        extensionBuilder.service(DeploymentScenarioGenerator.class, 
SimpleDeploymentScenarioGenerator.class);
+    }
+
+    public static class SimpleDeploymentScenarioGenerator implements 
DeploymentScenarioGenerator {
+
+        private final DeploymentScenarioGenerator standard = new 
AnnotationDeploymentScenarioGenerator();
+
+        @Override
+        public List<DeploymentDescription> generate(final TestClass testClass) 
{
+            final List<DeploymentDescription> stdDeploymentDescriptions = 
standard.generate(testClass);
+
+            if (stdDeploymentDescriptions != null && 
!stdDeploymentDescriptions.isEmpty()) {
+                return stdDeploymentDescriptions;
+            }
+
+            return Collections.singletonList(new 
DeploymentDescription("test.war",
+                    ShrinkWrap.create(WebArchive.class, 
"test.war").add(EmptyAsset.INSTANCE, "WEB-INF/beans.xml")));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
----------------------------------------------------------------------
diff --git 
a/tck/mp-jwt-embedded/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
 
b/tck/mp-jwt-embedded/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
new file mode 100644
index 0000000..98a4867
--- /dev/null
+++ 
b/tck/mp-jwt-embedded/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
@@ -0,0 +1 @@
+org.apache.tomee.microprofile.jwt.AppDeploymentExtension
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/830b3729/tck/mp-jwt-embedded/src/test/resources/dev.xml
----------------------------------------------------------------------
diff --git a/tck/mp-jwt-embedded/src/test/resources/dev.xml 
b/tck/mp-jwt-embedded/src/test/resources/dev.xml
index 16038c9..f6c4fbd 100644
--- a/tck/mp-jwt-embedded/src/test/resources/dev.xml
+++ b/tck/mp-jwt-embedded/src/test/resources/dev.xml
@@ -41,8 +41,9 @@
       </run>
     </groups>
     <classes>
+      <!-- OK
+      -->
       <class 
name="org.eclipse.microprofile.jwt.tck.parsing.TokenValidationTest" />
-      <!--
       <class name="org.eclipse.microprofile.jwt.tck.util.TokenUtilsTest" />
       <class 
name="org.eclipse.microprofile.jwt.tck.parsing.TestTokenClaimTypesTest" />
       <class 
name="org.eclipse.microprofile.jwt.tck.container.jaxrs.UnsecuredPingTest" />
@@ -52,10 +53,11 @@
       <class 
name="org.eclipse.microprofile.jwt.tck.container.jaxrs.ProviderInjectionTest" />
       <class 
name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RolesAllowedTest" />
       <class 
name="org.eclipse.microprofile.jwt.tck.container.jaxrs.InvalidTokenTest" />
+      <!-- KO
       -->
     </classes>
   </test>
-  <!--
+
   <test name="extended-tests" verbose="10">
     <groups>
       <define name="extended-groups">
@@ -79,5 +81,5 @@
       <class 
name="org.eclipse.microprofile.jwt.tck.container.servlet.ServletTest" />
     </classes>
   </test>
-  -->
+
 </suite>

Reply via email to