WIP
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/deb17d98 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/deb17d98 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/deb17d98 Branch: refs/heads/master Commit: deb17d989939597afca7ba8c46b3b4840e1ca8a2 Parents: a1747db Author: Jonathan Gallimore <[email protected]> Authored: Fri Oct 19 22:22:07 2018 +0100 Committer: Roberto Cortez <[email protected]> Committed: Fri Dec 7 18:11:19 2018 +0000 ---------------------------------------------------------------------- .../openejb/cdi/ThreadSingletonServiceImpl.java | 2 ++ mp-jwt/pom.xml | 6 +++++ .../tomee/microprofile/jwt/MPJWTFilter.java | 28 +++++++++++++++++++- .../tomee/microprofile/jwt/cdi/ClaimBean.java | 19 ++++++++----- .../microprofile/jwt/cdi/MPJWTCDIExtension.java | 2 +- .../principal/DefaultJWTCallerPrincipal.java | 2 ++ .../jwt/principal/JWTCallerPrincipal.java | 2 ++ tck/microprofile-tck/jwt/pom.xml | 7 +++++ .../jwt/src/test/resources/arquillian.xml | 3 +++ .../jwt/src/test/resources/dev.xml | 12 +++------ .../tomee/catalina/TomcatSecurityService.java | 6 ++++- 11 files changed, 72 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java b/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java index 9b90d2e..d0a24c2 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/cdi/ThreadSingletonServiceImpl.java @@ -124,6 +124,8 @@ public class ThreadSingletonServiceImpl implements ThreadSingletonService { properties.put(ContextsService.class.getName(), CdiAppContextsService.class.getName()); properties.put(ResourceInjectionService.class.getName(), CdiResourceInjectionService.class.getName()); properties.put(TransactionService.class.getName(), OpenEJBTransactionService.class.getName()); + properties.put("org.apache.webbeans.component.PrincipalBean.proxy", "false"); + // NOTE: ensure user can extend/override all the services = set it only if not present in properties, see WebBeansContext#getService() final Map<Class<?>, Object> services = new HashMap<>(); http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/mp-jwt/pom.xml ---------------------------------------------------------------------- diff --git a/mp-jwt/pom.xml b/mp-jwt/pom.xml index 975a025..ea40901 100644 --- a/mp-jwt/pom.xml +++ b/mp-jwt/pom.xml @@ -75,6 +75,12 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>tomee-catalina</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.bitbucket.b_c</groupId> <artifactId>jose4j</artifactId> <version>0.6.0</version> http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java ---------------------------------------------------------------------- diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java index ee3be1b..a26bca6 100644 --- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java +++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/MPJWTFilter.java @@ -16,6 +16,10 @@ */ package org.apache.tomee.microprofile.jwt; +import org.apache.openejb.loader.SystemInstance; +import org.apache.openejb.spi.SecurityService; +import org.apache.tomee.catalina.OpenEJBSecurityListener; +import org.apache.tomee.catalina.TomcatSecurityService; import org.apache.tomee.microprofile.jwt.config.ConfigurableJWTAuthContextInfo; import org.apache.tomee.microprofile.jwt.config.JWTAuthContextInfo; import org.apache.tomee.microprofile.jwt.principal.JWTCallerPrincipalFactory; @@ -68,7 +72,26 @@ public class MPJWTFilter implements Filter { // now wrap the httpServletRequest and override the principal so CXF can propagate into the SecurityContext try { - chain.doFilter(new MPJWTServletRequestWrapper(httpServletRequest, authContextInfo.get()), response); + + + final org.apache.catalina.connector.Request req = OpenEJBSecurityListener.requests.get(); + final MPJWTServletRequestWrapper wrappedRequest = new MPJWTServletRequestWrapper(httpServletRequest, authContextInfo.get()); + + Object state = null; + + final SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class); + if (TomcatSecurityService.class.isInstance(securityService)) { + final TomcatSecurityService tomcatSecurityService = TomcatSecurityService.class.cast(securityService); + state = tomcatSecurityService.enterWebApp(req.getWrapper().getRealm(), wrappedRequest.getUserPrincipal(), req.getWrapper().getRunAs()); + } + + chain.doFilter(wrappedRequest, response); + + if (TomcatSecurityService.class.isInstance(securityService)) { + final TomcatSecurityService tomcatSecurityService = TomcatSecurityService.class.cast(securityService); + tomcatSecurityService.exitWebApp(state); + } + } catch (final Exception e) { // this is an alternative to the @Provider bellow which requires registration on the fly @@ -135,6 +158,9 @@ public class MPJWTFilter implements Filter { throw new InvalidTokenException(token, e); } + // TODO - do the login here, save the state to the request so we can recover it later. + // TODO Also check if it is an async request and add a listener to close off the state + return jsonWebToken; } http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java ---------------------------------------------------------------------- diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java index 31093c8..1f5e2ed 100644 --- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java +++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/cdi/ClaimBean.java @@ -43,6 +43,7 @@ import javax.json.bind.Jsonb; import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.security.Principal; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -277,16 +278,22 @@ public class ClaimBean<T> implements Bean<T>, PassivationCapable { } private T getClaimValue(final String name) { - final Bean<?> bean = bm.resolve(bm.getBeans(JsonWebToken.class)); - JsonWebToken jsonWebToken = null; - if (RequestScoped.class.equals(bean.getScope())) { - jsonWebToken = JsonWebToken.class.cast(bm.getReference(bean, JsonWebToken.class, null)); - } - if (jsonWebToken == null || !bean.getScope().equals(RequestScoped.class)) { + final Bean<?> bean = bm.resolve(bm.getBeans(Principal.class)); + final Principal principal = Principal.class.cast(bm.getReference(bean, Principal.class, null)); + + if (principal == null) { logger.warning(String.format("Can't retrieve claim %s. No active principal.", name)); return null; } + JsonWebToken jsonWebToken = null; + if (! JsonWebToken.class.isInstance(principal)) { + logger.warning(String.format("Can't retrieve claim %s. Active principal is not a JWT.", name)); + return null; + } + + jsonWebToken = JsonWebToken.class.cast(principal); + final Optional<T> claimValue = jsonWebToken.claim(name); logger.finest(String.format("Found ClaimValue=%s for name=%s", claimValue, name)); return claimValue.orElse(null); http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/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 0d7b95a..b7305be 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 @@ -101,7 +101,7 @@ 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(MPJWTProducer.class)); +// bbd.addAnnotatedType(beanManager.createAnnotatedType(MPJWTProducer.class)); } static { http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java ---------------------------------------------------------------------- diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java index 661fbde..991fd4f 100644 --- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java +++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/DefaultJWTCallerPrincipal.java @@ -16,6 +16,7 @@ */ package org.apache.tomee.microprofile.jwt.principal; +import org.apache.openejb.spi.CallerPrincipal; import org.eclipse.microprofile.jwt.Claims; import org.jose4j.jwt.JwtClaims; import org.jose4j.jwt.MalformedClaimException; @@ -40,6 +41,7 @@ import java.util.logging.Logger; * A default implementation of JWTCallerPrincipal using jose4j * Another implementation could use nimbus and another plain JSON-P */ +@CallerPrincipal public class DefaultJWTCallerPrincipal extends JWTCallerPrincipal { private static final Logger logger = Logger.getLogger(DefaultJWTCallerPrincipal.class.getName()); http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java ---------------------------------------------------------------------- diff --git a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java index d8e3c4c..e56b6d3 100644 --- a/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java +++ b/mp-jwt/src/main/java/org/apache/tomee/microprofile/jwt/principal/JWTCallerPrincipal.java @@ -17,6 +17,7 @@ package org.apache.tomee.microprofile.jwt.principal; +import org.apache.openejb.spi.CallerPrincipal; import org.eclipse.microprofile.jwt.JsonWebToken; import java.util.Optional; @@ -25,6 +26,7 @@ import java.util.Optional; * An abstract CallerPrincipal implementation that provides access to the JWT claims that are required by * the microprofile token. */ +@CallerPrincipal public abstract class JWTCallerPrincipal implements JsonWebToken { private String name; http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/tck/microprofile-tck/jwt/pom.xml ---------------------------------------------------------------------- diff --git a/tck/microprofile-tck/jwt/pom.xml b/tck/microprofile-tck/jwt/pom.xml index e979b99..a57756e 100644 --- a/tck/microprofile-tck/jwt/pom.xml +++ b/tck/microprofile-tck/jwt/pom.xml @@ -41,6 +41,13 @@ </dependency> <dependency> + <groupId>org.apache.tomee</groupId> + <artifactId>tomee-catalina</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-client</artifactId> <version>${cxf.version}</version> http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml ---------------------------------------------------------------------- diff --git a/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml b/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml index e14a14b..ec0be8a 100644 --- a/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml +++ b/tck/microprofile-tck/jwt/src/test/resources/arquillian.xml @@ -32,6 +32,9 @@ <property name="dir">target/tomee</property> <property name="appWorkingDir">target/workdir</property> <property name="cleanOnStartUp">true</property> + <property name="properties"> + org.apache.webbeans.component.PrincipalBean.proxy=false + </property> </configuration> </container> </arquillian> http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/tck/microprofile-tck/jwt/src/test/resources/dev.xml ---------------------------------------------------------------------- diff --git a/tck/microprofile-tck/jwt/src/test/resources/dev.xml b/tck/microprofile-tck/jwt/src/test/resources/dev.xml index 04685d7..9ebcb6b 100644 --- a/tck/microprofile-tck/jwt/src/test/resources/dev.xml +++ b/tck/microprofile-tck/jwt/src/test/resources/dev.xml @@ -48,19 +48,15 @@ <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.RolesAllowedTest" /> <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.InvalidTokenTest" /> <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.PrimitiveInjectionTest" /> - <!-- TODO - Required deep integration with TomEE Security - See org.apache.tomee.catalina.TomcatSecurityService.getCallerPrincipal --> - <!-- <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.PrincipalInjectionTest" /> --> + <class name="org.eclipse.microprofile.jwt.tck.container.jaxrs.PrincipalInjectionTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMLocationTest" /> - <!-- TODO - Always get a 404 because when we try to read the key the app is not started yet. Figure this out. --> - <!-- <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMLocationURLTest" /> --> + <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsPEMLocationURLTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKLocationTest" /> - <!-- TODO - Always get a 404 because when we try to read the key the app is not started yet. Figure this out. --> - <!-- <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKLocationURLTest" /> --> + <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKLocationURLTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKSTest" /> - <!-- TODO - Always get a 404 because when we try to read the key the app is not started yet. Figure this out. --> - <!-- <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKSLocationTest" /> --> + <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsJWKSLocationTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsBase64JWKTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.PublicKeyAsFileLocationURLTest" /> <class name="org.eclipse.microprofile.jwt.tck.config.IssNoValidationNoIssTest" /> http://git-wip-us.apache.org/repos/asf/tomee/blob/deb17d98/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java index 69975ba..f21261c 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java @@ -120,7 +120,11 @@ public class TomcatSecurityService extends AbstractSecurityService { private Subject createSubject(final Realm realm, final Principal principal) { final Set<Principal> principals = new HashSet<>(); - principals.add(new TomcatUser(realm, principal)); + if (principal.getClass().isAnnotationPresent(CallerPrincipal.class)) { + principals.add(principal); + } else { + principals.add(new TomcatUser(realm, principal)); + } return new Subject(true, principals, new HashSet(), new HashSet()); }
