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/04/26 15:13:39 UTC
[4/8] tomee git commit: Make a simple test case to wire up everything
and start adding a simple UI on top
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
new file mode 100644
index 0000000..73a57f1
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/container.js
@@ -0,0 +1,62 @@
+/**
+ *
+ * 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.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'app/js/i18n', 'lib/backbone'];
+ define(deps, function (templates) {
+
+ var View = Backbone.View.extend({
+ el: 'body',
+
+ showView: function (view) {
+ var me = this;
+ var contentarea = me.$('.ux-contentarea');
+ if (me.currentView) {
+ me.currentView.$el.detach();
+ }
+ me.currentView = view;
+ me.currentView.render();
+ contentarea.append(me.currentView.el);
+ if (view.renderCallback) {
+ view.renderCallback();
+ }
+ me.$('.ux-app-menu-item').removeClass('active');
+ var myMenuItem = me.$('li.ux-app-menu-item.' + view.className);
+ myMenuItem.addClass('active');
+ },
+
+ render: function () {
+ if (this.options.isRendered) {
+ return this;
+ }
+ var html = templates.getValue('container', {
+ userName: ''
+ });
+ this.$el.html(html);
+
+ // render it only once
+ this.options.isRendered = true;
+ return this;
+ }
+ });
+
+ return new View({});
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js b/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
new file mode 100644
index 0000000..0417945
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/app/js/view/movie.js
@@ -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.
+ */
+
+(function () {
+ 'use strict';
+
+ var deps = ['app/js/templates', 'lib/underscore', 'lib/backbone', 'app/js/id'];
+ define(deps, function (templates, underscore) {
+
+ var View = Backbone.View.extend({
+ tagName: 'div',
+ className: 'modal ux-movie-window',
+ events: {
+ 'click .ux-application': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.trigger('show-application', {});
+ },
+ 'click .ux-close': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ me.remove();
+ },
+ 'click .ux-save': function (evt) {
+ evt.preventDefault();
+ var me = this;
+ var model = me.model;
+
+ function set(name) {
+ var field = $(me.$el.find('.ux-' + name).get(0));
+ model.set(name, field.val());
+ }
+
+ set('title');
+ set('director');
+ set('genre');
+ set('rating');
+ set('year');
+ me.trigger('save-model', {
+ model: model
+ });
+ }
+ },
+ render: function () {
+ var me = this;
+ me.$el.empty();
+ me.$el.append(templates.getValue('movie', {
+ title: me.model.get('title'),
+ director: me.model.get('director'),
+ genre: me.model.get('genre'),
+ rating: me.model.get('rating'),
+ year: me.model.get('year'),
+ currentYear: new Date().getFullYear()
+ }));
+ return me;
+ }
+ });
+ return View;
+ });
+}());
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/main/webapp/index.jsp
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/main/webapp/index.jsp b/examples/rest-mp-jwt/src/main/webapp/index.jsp
new file mode 100644
index 0000000..63d3e42
--- /dev/null
+++ b/examples/rest-mp-jwt/src/main/webapp/index.jsp
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!--
+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.
+-->
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Moviefun</title>
+ <link href="<c:url value='/webjars/bootstrap/3.1.0/css/bootstrap.min.css'/>" rel="stylesheet">
+ <link href="<c:url value='/app/app.less'/>" rel="stylesheet/less" type="text/css">
+ <script src="<c:url value='/webjars/requirejs/2.1.10/require.min.js'/>"></script>
+ <script type="text/javascript">
+ window.ux = window.ux || {};
+ window.ux.SESSION_ID = "<%=request.getSession().getId()%>";
+ window.ux.ROOT_URL = "<c:url value='/'/>".replace(';jsessionid=' + window.ux.SESSION_ID, '');
+ </script>
+ <script src="<c:url value='/app/config.js'/>"></script>
+ <script src="<c:url value='/app/js/start.js'/>"></script>
+</head>
+<body></body>
+</html>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
new file mode 100644
index 0000000..b18e64e
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/MoviesTest.java
@@ -0,0 +1,88 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.superbiz.moviefun;
+
+import org.apache.cxf.feature.LoggingFeature;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.johnzon.jaxrs.JohnzonProvider;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.superbiz.moviefun.rest.ApplicationConfig;
+import org.superbiz.moviefun.rest.LoadRest;
+import org.superbiz.moviefun.rest.MoviesMPJWTConfigurationProvider;
+import org.superbiz.moviefun.rest.MoviesRest;
+import org.superbiz.rest.GreetingService;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+
+import static java.util.Collections.singletonList;
+
+@RunWith(Arquillian.class)
+public class MoviesTest {
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(Movie.class, MoviesBean.class, MoviesTest.class, LoadRest.class)
+ .addClasses(MoviesRest.class, GreetingService.class, ApplicationConfig.class)
+ .addClass(MoviesMPJWTConfigurationProvider.class)
+ .addAsWebInfResource(new StringAsset("<beans/>"), "beans.xml")
+ .addAsResource(new ClassLoaderAsset("META-INF/persistence.xml"), "META-INF/persistence.xml");
+
+ System.out.println(webArchive.toString(true));
+
+ return webArchive;
+ }
+
+ @ArquillianResource
+ private URL base;
+
+ @Test
+ public void sthg() throws Exception {
+
+ final WebClient webClient = WebClient
+ .create(base.toExternalForm(), singletonList(new JohnzonProvider<>()), singletonList(new LoggingFeature()), null);
+
+ webClient
+ .reset()
+ .path("/rest/greeting/")
+ .get(String.class);
+
+ final Collection<? extends Movie> movies = webClient
+ .reset()
+ .path("/rest/movies/")
+ .header("Authorization", "Bearer " + token())
+ .getCollection(Movie.class);
+
+ System.out.println(movies);
+ }
+
+ private String token() throws Exception {
+ HashMap<String, Long> timeClaims = new HashMap<>();
+ return TokenUtils.generateTokenString("/Token1.json", null, timeClaims);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
new file mode 100644
index 0000000..5aa34b4
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/moviefun/TokenUtils.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016-2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Licensed 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.superbiz.moviefun;
+
+import com.nimbusds.jose.JOSEObjectType;
+import com.nimbusds.jose.JWSAlgorithm;
+import com.nimbusds.jose.JWSHeader;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.crypto.MACSigner;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import net.minidev.json.JSONObject;
+import net.minidev.json.parser.JSONParser;
+import org.eclipse.microprofile.jwt.Claims;
+
+import java.io.InputStream;
+import java.math.BigInteger;
+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.SecureRandom;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import static net.minidev.json.parser.JSONParser.DEFAULT_PERMISSIVE_MODE;
+
+/**
+ * Utilities for generating a JWT for testing
+ */
+public class TokenUtils {
+ private TokenUtils() {
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key.
+ *
+ * @param jsonResName - name of test resources file
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName) throws Exception {
+ return generateTokenString(jsonResName, Collections.emptySet());
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key, possibly with invalid fields.
+ *
+ * @param jsonResName - name of test resources file
+ * @param invalidClaims - the set of claims that should be added with invalid values to test failure modes
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName, Set<InvalidClaims> invalidClaims) throws Exception {
+ return generateTokenString(jsonResName, invalidClaims, null);
+ }
+
+ /**
+ * Utility method to generate a JWT string from a JSON resource file that is signed by the privateKey.pem
+ * test resource key, possibly with invalid fields.
+ *
+ * @param jsonResName - name of test resources file
+ * @param invalidClaims - the set of claims that should be added with invalid values to test failure modes
+ * @param timeClaims - used to return the exp, iat, auth_time claims
+ * @return the JWT string
+ * @throws Exception on parse failure
+ */
+ public static String generateTokenString(String jsonResName, Set<InvalidClaims> invalidClaims, Map<String, Long> timeClaims) throws Exception {
+ if (invalidClaims == null) {
+ invalidClaims = Collections.emptySet();
+ }
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(jsonResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ byte[] content = new byte[length];
+ System.arraycopy(tmp, 0, content, 0, length);
+
+ JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE);
+ JSONObject jwtContent = (JSONObject) parser.parse(content);
+ // Change the issuer to INVALID_ISSUER for failure testing if requested
+ if (invalidClaims.contains(InvalidClaims.ISSUER)) {
+ jwtContent.put(Claims.iss.name(), "INVALID_ISSUER");
+ }
+ long currentTimeInSecs = currentTimeInSecs();
+ long exp = currentTimeInSecs + 300;
+ // Check for an input exp to override the default of now + 300 seconds
+ if (timeClaims != null && timeClaims.containsKey(Claims.exp.name())) {
+ exp = timeClaims.get(Claims.exp.name());
+ }
+ jwtContent.put(Claims.iat.name(), currentTimeInSecs);
+ jwtContent.put(Claims.auth_time.name(), currentTimeInSecs);
+ // If the exp claim is not updated, it will be an old value that should be seen as expired
+ if (!invalidClaims.contains(InvalidClaims.EXP)) {
+ jwtContent.put(Claims.exp.name(), exp);
+ }
+ if (timeClaims != null) {
+ timeClaims.put(Claims.iat.name(), currentTimeInSecs);
+ timeClaims.put(Claims.auth_time.name(), currentTimeInSecs);
+ timeClaims.put(Claims.exp.name(), exp);
+ }
+
+ PrivateKey pk;
+ if (invalidClaims.contains(InvalidClaims.SIGNER)) {
+ // Generate a new random private key to sign with to test invalid signatures
+ KeyPair keyPair = generateKeyPair(2048);
+ pk = keyPair.getPrivate();
+ } else {
+ // Use the test private key associated with the test public key for a valid signature
+ pk = readPrivateKey("/privateKey.pem");
+ }
+
+ // Create RSA-signer with the private key
+ JWSSigner signer = new RSASSASigner(pk);
+ JWTClaimsSet claimsSet = JWTClaimsSet.parse(jwtContent);
+ JWSAlgorithm alg = JWSAlgorithm.RS256;
+ if (invalidClaims.contains(InvalidClaims.ALG)) {
+ alg = JWSAlgorithm.HS256;
+ SecureRandom random = new SecureRandom();
+ BigInteger secret = BigInteger.probablePrime(256, random);
+ signer = new MACSigner(secret.toByteArray());
+ }
+ JWSHeader jwtHeader = new JWSHeader.Builder(alg)
+ .keyID("/privateKey.pem")
+ .type(JOSEObjectType.JWT)
+ .build();
+ SignedJWT signedJWT = new SignedJWT(jwtHeader, claimsSet);
+ signedJWT.sign(signer);
+ return signedJWT.serialize();
+ }
+
+ /**
+ * Read a PEM encoded private key from the classpath
+ *
+ * @param pemResName - key file resource name
+ * @return PrivateKey
+ * @throws Exception on decode failure
+ */
+ public static PrivateKey readPrivateKey(String pemResName) throws Exception {
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(pemResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ return decodePrivateKey(new String(tmp, 0, length));
+ }
+
+ /**
+ * Read a PEM encoded public key from the classpath
+ *
+ * @param pemResName - key file resource name
+ * @return PublicKey
+ * @throws Exception on decode failure
+ */
+ public static PublicKey readPublicKey(String pemResName) throws Exception {
+ InputStream contentIS = TokenUtils.class.getResourceAsStream(pemResName);
+ byte[] tmp = new byte[4096];
+ int length = contentIS.read(tmp);
+ return decodePublicKey(new String(tmp, 0, length));
+ }
+
+ /**
+ * Generate a new RSA keypair.
+ *
+ * @param keySize - the size of the key
+ * @return KeyPair
+ * @throws NoSuchAlgorithmException on failure to load RSA key generator
+ */
+ public static KeyPair generateKeyPair(int keySize) throws NoSuchAlgorithmException {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+ keyPairGenerator.initialize(keySize);
+ return keyPairGenerator.genKeyPair();
+ }
+
+ /**
+ * Decode a PEM encoded private key string to an RSA PrivateKey
+ *
+ * @param pemEncoded - PEM string for private key
+ * @return PrivateKey
+ * @throws Exception on decode failure
+ */
+ 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");
+ return kf.generatePrivate(keySpec);
+ }
+
+ /**
+ * Decode a PEM encoded public key string to an RSA PublicKey
+ *
+ * @param pemEncoded - PEM string for private key
+ * @return PublicKey
+ * @throws Exception on decode failure
+ */
+ 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 (.*)-----", "");
+ pem = pem.replaceAll("-----END (.*)----", "");
+ pem = pem.replaceAll("\r\n", "");
+ pem = pem.replaceAll("\n", "");
+ return pem.trim();
+ }
+
+ /**
+ * @return the current time in seconds since epoch
+ */
+ public static int currentTimeInSecs() {
+ long currentTimeMS = System.currentTimeMillis();
+ return (int) (currentTimeMS / 1000);
+ }
+
+ /**
+ * Enums to indicate which claims should be set to invalid values for testing failure modes
+ */
+ public enum InvalidClaims {
+ ISSUER, // Set an invalid issuer
+ EXP, // Set an invalid expiration
+ SIGNER, // Sign the token with the incorrect private key
+ ALG, // Sign the token with the correct private key, but HS
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java b/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
new file mode 100644
index 0000000..f38063f
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/java/org/superbiz/rest/GreetingServiceTest.java
@@ -0,0 +1,61 @@
+/**
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.superbiz.rest;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.EnableServices;
+import org.apache.openejb.testing.Module;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+@EnableServices(value = "jaxrs", httpDebug = true)
+@RunWith(ApplicationComposer.class)
+public class GreetingServiceTest {
+
+ @Module
+ @Classes(GreetingService.class)
+ public WebApp app() {
+ return new WebApp().contextRoot("test");
+ }
+
+ @Test
+ public void get() throws IOException {
+ final String message = WebClient.create("http://localhost:4204")
+ .path("/test/greeting/")
+ .accept(MediaType.APPLICATION_JSON_TYPE)
+ .get(String.class);
+ assertEquals("Hi Microprofile JWT!", message);
+ }
+
+ @Test
+ public void post() throws IOException {
+ final String message = WebClient.create("http://localhost:4204")
+ .path("/test/greeting/")
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .accept(MediaType.APPLICATION_JSON_TYPE)
+ .post("Hi REST!", String.class);
+ assertEquals("hi rest!", message);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml b/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
new file mode 100644
index 0000000..1e91dca
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/META-INF/application-client.xml
@@ -0,0 +1 @@
+<application-client/>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/Token1.json
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/Token1.json b/examples/rest-mp-jwt/src/test/resources/Token1.json
new file mode 100644
index 0000000..32b03c8
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/Token1.json
@@ -0,0 +1,20 @@
+{
+ "iss": "https://server.example.com",
+ "jti": "a-123",
+ "sub": "24400320",
+ "upn": "jdoe@example.com",
+ "preferred_username": "jdoe",
+ "aud": "s6BhdRkqt3",
+ "exp": 1311281970,
+ "iat": 1311280970,
+ "auth_time": 1311280969,
+ "roles": [
+ "Echoer"
+ ],
+ "groups": [
+ "Echoer",
+ "Tester",
+ "group1",
+ "group2"
+ ]
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/Token2.json
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/Token2.json b/examples/rest-mp-jwt/src/test/resources/Token2.json
new file mode 100644
index 0000000..d69f61a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/Token2.json
@@ -0,0 +1,12 @@
+{
+ "iss": "https://server.example.com",
+ "jti": "a-123.2",
+ "sub": "24400320#2",
+ "upn": "jdoe2@example.com",
+ "preferred_username": "jdoe",
+ "aud": "s6BhdRkqt3.2",
+ "exp": 1311281970,
+ "iat": 1311280970,
+ "auth_time": 1311280969,
+ "groups": ["Echoer2", "Tester", "Token2Role", "group1.2", "group2.2"]
+}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/arquillian.xml
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/arquillian.xml b/examples/rest-mp-jwt/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..4744e7a
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/arquillian.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+
+ 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.
+-->
+<arquillian
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ >
+
+ <container qualifier="tomee" default="true">
+ <configuration>
+ <property name="httpPort">-1</property>
+ <property name="stopPort">-1</property>
+ <property name="classifier">microprofile</property>
+ <property name="dir">target/apache-tomee-remote</property>
+ <property name="appWorkingDir">target/arquillian-test-working-dir</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/privateKey.pem
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/privateKey.pem b/examples/rest-mp-jwt/src/test/resources/privateKey.pem
new file mode 100644
index 0000000..e20d80b
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/privateKey.pem
@@ -0,0 +1,28 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCWK8UjyoHgPTLa
+PLQJ8SoXLLjpHSjtLxMqmzHnFscqhTVVaDpCRCb6e3Ii/WniQTWw8RA7vf4djz4H
+OzvlfBFNgvUGZHXDwnmGaNVaNzpHYFMEYBhE8VGGiveSkzqeLZI+Y02G6sQAfDtN
+qqzM/l5QX8X34oQFaTBW1r49nftvCpITiwJvWyhkWtXP9RP8sXi1im5Vi3dhupOh
+nelk5n0BfajUYIbfHA6ORzjHRbt7NtBl0L2J+0/FUdHyKs6KMlFGNw8O0Dq88qnM
+uXoLJiewhg9332W3DFMeOveel+//cvDnRsCRtPgd4sXFPHh+UShkso7+DRsChXa6
+oGGQD3GdAgMBAAECggEAAjfTSZwMHwvIXIDZB+yP+pemg4ryt84iMlbofclQV8hv
+6TsI4UGwcbKxFOM5VSYxbNOisb80qasb929gixsyBjsQ8284bhPJR7r0q8h1C+jY
+URA6S4pk8d/LmFakXwG9Tz6YPo3pJziuh48lzkFTk0xW2Dp4SLwtAptZY/+ZXyJ6
+96QXDrZKSSM99Jh9s7a0ST66WoxSS0UC51ak+Keb0KJ1jz4bIJ2C3r4rYlSu4hHB
+Y73GfkWORtQuyUDa9yDOem0/z0nr6pp+pBSXPLHADsqvZiIhxD/O0Xk5I6/zVHB3
+zuoQqLERk0WvA8FXz2o8AYwcQRY2g30eX9kU4uDQAQKBgQDmf7KGImUGitsEPepF
+KH5yLWYWqghHx6wfV+fdbBxoqn9WlwcQ7JbynIiVx8MX8/1lLCCe8v41ypu/eLtP
+iY1ev2IKdrUStvYRSsFigRkuPHUo1ajsGHQd+ucTDf58mn7kRLW1JGMeGxo/t32B
+m96Af6AiPWPEJuVfgGV0iwg+HQKBgQCmyPzL9M2rhYZn1AozRUguvlpmJHU2DpqS
+34Q+7x2Ghf7MgBUhqE0t3FAOxEC7IYBwHmeYOvFR8ZkVRKNF4gbnF9RtLdz0DMEG
+5qsMnvJUSQbNB1yVjUCnDAtElqiFRlQ/k0LgYkjKDY7LfciZl9uJRl0OSYeX/qG2
+tRW09tOpgQKBgBSGkpM3RN/MRayfBtmZvYjVWh3yjkI2GbHA1jj1g6IebLB9SnfL
+WbXJErCj1U+wvoPf5hfBc7m+jRgD3Eo86YXibQyZfY5pFIh9q7Ll5CQl5hj4zc4Y
+b16sFR+xQ1Q9Pcd+BuBWmSz5JOE/qcF869dthgkGhnfVLt/OQzqZluZRAoGAXQ09
+nT0TkmKIvlza5Af/YbTqEpq8mlBDhTYXPlWCD4+qvMWpBII1rSSBtftgcgca9XLB
+MXmRMbqtQeRtg4u7dishZVh1MeP7vbHsNLppUQT9Ol6lFPsd2xUpJDc6BkFat62d
+Xjr3iWNPC9E9nhPPdCNBv7reX7q81obpeXFMXgECgYEAmk2Qlus3OV0tfoNRqNpe
+Mb0teduf2+h3xaI1XDIzPVtZF35ELY/RkAHlmWRT4PCdR0zXDidE67L6XdJyecSt
+FdOUH8z5qUraVVebRFvJqf/oGsXc4+ex1ZKUTbY0wqY1y9E39yvB3MaTmZFuuqk8
+f3cg+fr8aou7pr9SHhJlZCU=
+-----END RSA PRIVATE KEY-----
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/examples/rest-mp-jwt/src/test/resources/publicKey.pem
----------------------------------------------------------------------
diff --git a/examples/rest-mp-jwt/src/test/resources/publicKey.pem b/examples/rest-mp-jwt/src/test/resources/publicKey.pem
new file mode 100644
index 0000000..a1dc20c
--- /dev/null
+++ b/examples/rest-mp-jwt/src/test/resources/publicKey.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlivFI8qB4D0y2jy0CfEq
+Fyy46R0o7S8TKpsx5xbHKoU1VWg6QkQm+ntyIv1p4kE1sPEQO73+HY8+Bzs75XwR
+TYL1BmR1w8J5hmjVWjc6R2BTBGAYRPFRhor3kpM6ni2SPmNNhurEAHw7TaqszP5e
+UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9
+AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn
+sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x
+nQIDAQAB
+-----END RSA PUBLIC KEY-----
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/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 051f05a..ca69b0a 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
@@ -18,7 +18,6 @@ package org.apache.tomee.microprofile.jwt.cdi;
import org.apache.tomee.microprofile.jwt.MPJWTFilter;
import org.apache.tomee.microprofile.jwt.MPJWTInitializer;
-import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfoProvider;
import org.eclipse.microprofile.jwt.Claim;
import javax.enterprise.event.Observes;
@@ -37,24 +36,13 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
-import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class MPJWTCDIExtension implements Extension {
- private static final Predicate<InjectionPoint> NOT_PROVIDERS = new Predicate<InjectionPoint>() {
- @Override
- public boolean test(final InjectionPoint ip) {
- return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Provider.class);
- }
- };
- private static final Predicate<InjectionPoint> NOT_INSTANCES = new Predicate<InjectionPoint>() {
- @Override
- public boolean test(final InjectionPoint ip) {
- return (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Instance.class);
- }
- };
+ private static final Predicate<InjectionPoint> NOT_PROVIDERS = ip -> (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Provider.class);
+ private static final Predicate<InjectionPoint> NOT_INSTANCES = ip -> (Class.class.isInstance(ip.getType())) || (ParameterizedType.class.isInstance(ip.getType()) && ((ParameterizedType) ip.getType()).getRawType() != Instance.class);
private static final Map<Type, Type> REPLACED_TYPES = new HashMap<>();
static {
@@ -79,44 +67,24 @@ public class MPJWTCDIExtension implements Extension {
final Set<Type> types = injectionPoints.stream()
.filter(NOT_PROVIDERS)
.filter(NOT_INSTANCES)
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType());
- }
- })
+ .map(ip -> REPLACED_TYPES.getOrDefault(ip.getType(), ip.getType()))
.collect(Collectors.<Type>toSet());
final Set<Type> providerTypes = injectionPoints.stream()
.filter(NOT_PROVIDERS.negate())
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
- }
- })
+ .map(ip -> ((ParameterizedType) ip.getType()).getActualTypeArguments()[0])
.collect(Collectors.<Type>toSet());
final Set<Type> instanceTypes = injectionPoints.stream()
.filter(NOT_INSTANCES.negate())
- .map(new Function<InjectionPoint, Type>() {
- @Override
- public Type apply(final InjectionPoint ip) {
- return ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
- }
- })
+ .map(ip -> ((ParameterizedType) ip.getType()).getActualTypeArguments()[0])
.collect(Collectors.<Type>toSet());
types.addAll(providerTypes);
types.addAll(instanceTypes);
types.stream()
- .map(new Function<Type, ClaimBean>() {
- @Override
- public ClaimBean apply(final Type type) {
- return new ClaimBean<>(bm, type);
- }
- })
+ .map(type -> new ClaimBean<>(bm, type))
.forEach(new Consumer<ClaimBean>() {
@Override
public void accept(final ClaimBean claimBean) {
@@ -129,7 +97,6 @@ public class MPJWTCDIExtension implements Extension {
bbd.addAnnotatedType(beanManager.createAnnotatedType(JsonbProducer.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));
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
deleted file mode 100644
index 9247e04..0000000
--- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/config/JWTAuthContextInfoProvider.java
+++ /dev/null
@@ -1,61 +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.jwt.config;
-
-import javax.enterprise.context.Dependent;
-import javax.enterprise.inject.Produces;
-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;
-
-@Dependent
-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" +
- "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
- "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
- "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
- "nQIDAQAB";
- byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
-
- final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
- final KeyFactory kf = KeyFactory.getInstance("RSA");
- final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
-
- contextInfo.setSignerKey(pk);
-
- return Optional.of(contextInfo);
- }
-
- @Produces
- JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
- return getOptionalContextInfo().get();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
----------------------------------------------------------------------
diff --git a/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
new file mode 100644
index 0000000..bf0a07f
--- /dev/null
+++ b/tck/microprofile-tck/jwt/src/main/java/org/apache/tomee/microprofile/jwt/JWTAuthContextInfoProvider.java
@@ -0,0 +1,63 @@
+/*
+ * 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.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+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;
+
+@Dependent
+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" +
+ "UF/F9+KEBWkwVta+PZ37bwqSE4sCb1soZFrVz/UT/LF4tYpuVYt3YbqToZ3pZOZ9" +
+ "AX2o1GCG3xwOjkc4x0W7ezbQZdC9iftPxVHR8irOijJRRjcPDtA6vPKpzLl6CyYn" +
+ "sIYPd99ltwxTHjr3npfv/3Lw50bAkbT4HeLFxTx4flEoZLKO/g0bAoV2uqBhkA9x" +
+ "nQIDAQAB";
+ byte[] encodedBytes = Base64.getDecoder().decode(pemEncoded);
+
+ final X509EncodedKeySpec spec = new X509EncodedKeySpec(encodedBytes);
+ final KeyFactory kf = KeyFactory.getInstance("RSA");
+ final RSAPublicKey pk = (RSAPublicKey) kf.generatePublic(spec);
+
+ contextInfo.setSignerKey(pk);
+
+ return Optional.of(contextInfo);
+ }
+
+ @Produces
+ JWTAuthContextInfo getContextInfo() throws InvalidKeySpecException, NoSuchAlgorithmException {
+ return getOptionalContextInfo().get();
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tomee/blob/b4a44e40/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 cf4e837..f5f2183 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
@@ -68,7 +68,8 @@ public class AppDeploymentExtension implements LoadableExtension {
if (!(appArchive instanceof WebArchive)) {
return;
}
- WebArchive war = WebArchive.class.cast(appArchive);
+ final WebArchive war = WebArchive.class.cast(appArchive);
+ war.addClass(JWTAuthContextInfoProvider.class);
log.info("Augmented war: \n"+war.toString(true));
}