This is an automated email from the ASF dual-hosted git repository.

jlmonteiro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git


The following commit(s) were added to refs/heads/master by this push:
     new 23df129  Finish tomee-security to implement fully Jakarta Security 
API. Some other fixes included. Test cases, etc
     new 40fd970  Merge pull request #786 from jeanouii/tomee-security_end
23df129 is described below

commit 23df129e2cf6fa52c6827ad66a13eec572b7073c
Author: Jean-Louis Monteiro <[email protected]>
AuthorDate: Tue Apr 20 11:24:04 2021 +0200

    Finish tomee-security to implement fully Jakarta Security API. Some other 
fixes included. Test cases, etc
---
 .../assembler/classic/JaccPermissionsBuilder.java  |  13 +-
 .../openejb/assembler/classic/PolicyContext.java   |   9 +-
 .../core/security/AbstractSecurityService.java     |  83 ++++-
 .../apache/openejb/core/security/JaccProvider.java |   2 +
 .../core/security/jacc/BasicJaccProvider.java      |  15 +-
 .../openejb/ri/sp/PseudoSecurityService.java       |  11 +
 .../org/apache/openejb/spi/SecurityService.java    |   5 +
 .../authenticator/jaspic/CallbackHandlerImpl.java  |  14 +-
 .../java/org/apache/tomee/catalina/Contexts.java   |  10 +
 .../tomee/catalina/TomcatSecurityService.java      |  50 ++-
 .../apache/tomee/catalina/TomcatWebAppBuilder.java |  17 +
 .../tomee/catalina/security/HTTPMethods.java       | 163 ++++++++++
 ...rityConstaintsToJaccPermissionsTransformer.java | 352 +++++++++++++++++++++
 .../apache/tomee/catalina/security/URLPattern.java | 289 +++++++++++++++++
 .../tomee/catalina/security/URLPatternCheck.java   |  28 ++
 .../tomee/catalina/security/UncheckedItem.java     |  64 ++++
 .../tomee/security/TomEESecurityContext.java       |  22 +-
 .../tomee/security/cdi/TomEESecurityExtension.java |   8 +-
 .../identitystore/TomEEIdentityStoreHandler.java   |  17 +
 .../provider/TomEESecurityServerAuthConfig.java    |   2 +-
 .../TomEESecurityServletContainerInitializer.java  |  39 ++-
 .../servlet/JaccPermissionServletTest.java         | 141 +++++++++
 .../src/test/resources/conf/tomcat-users.xml       |   4 +
 23 files changed, 1326 insertions(+), 32 deletions(-)

diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JaccPermissionsBuilder.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JaccPermissionsBuilder.java
index f52b6de..14a20d0 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JaccPermissionsBuilder.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/JaccPermissionsBuilder.java
@@ -33,6 +33,7 @@ import javax.security.jacc.PolicyContextException;
 import java.lang.reflect.Method;
 import java.security.Permission;
 import java.security.PermissionCollection;
+import java.security.Permissions;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -55,10 +56,12 @@ public class JaccPermissionsBuilder {
             return;
         }
 
+        final String contextID = policyContext.getContextID();
         try {
             final PolicyConfigurationFactory factory = 
PolicyConfigurationFactory.getPolicyConfigurationFactory();
 
-            final PolicyConfiguration policy = 
factory.getPolicyConfiguration(policyContext.getContextID(), false);
+            // final boolean needsCommit = factory.inService(contextID);
+            final PolicyConfiguration policy = 
factory.getPolicyConfiguration(contextID, false);
 
             policy.addToExcludedPolicy(policyContext.getExcludedPermissions());
 
@@ -68,11 +71,15 @@ public class JaccPermissionsBuilder {
                 policy.addToRole(entry.getKey(), entry.getValue());
             }
 
-            policy.commit();
+            // not sure if this is required or not
+            // if (needsCommit) {
+                policy.commit();
+            // }
         } catch (final ClassNotFoundException e) {
             throw new OpenEJBException("PolicyConfigurationFactory class not 
found", e);
+
         } catch (final PolicyContextException e) {
-            throw new OpenEJBException("JACC PolicyConfiguration failed: 
ContextId=" + policyContext.getContextID(), e);
+            throw new OpenEJBException("JACC PolicyConfiguration failed: 
ContextId=" + contextID, e);
         }
     }
 
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PolicyContext.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PolicyContext.java
index a6407ce..3b0dd2d 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PolicyContext.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PolicyContext.java
@@ -17,13 +17,11 @@
 
 package org.apache.openejb.assembler.classic;
 
+import java.security.Permission;
 import java.security.PermissionCollection;
 import java.util.HashMap;
 import java.util.Map;
 
-/**
- * @version $Rev$ $Date$
- */
 public class PolicyContext {
 
     private final PermissionCollection excludedPermissions = new 
DelegatePermissionCollection();
@@ -47,6 +45,11 @@ public class PolicyContext {
         return rolePermissions;
     }
 
+    public void addRole(final String name, final Permission permission) {
+        rolePermissions.computeIfAbsent(name, (k) -> new 
DelegatePermissionCollection());
+        rolePermissions.get(name).add(permission);
+    }
+
     public String getContextID() {
         return contextId;
     }
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
index e86a2b0..399096b 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/AbstractSecurityService.java
@@ -29,20 +29,27 @@ import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.CallerPrincipal;
 import org.apache.openejb.spi.SecurityService;
 import org.apache.openejb.util.JavaSecurityManagers;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
 
 import javax.security.auth.Subject;
 import javax.security.auth.login.LoginException;
 import javax.security.jacc.EJBMethodPermission;
 import javax.security.jacc.PolicyConfigurationFactory;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.security.jacc.PolicyContextHandler;
 import javax.servlet.http.HttpServletRequest;
 import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.security.AccessControlContext;
 import java.security.AccessControlException;
 import java.security.AccessController;
+import java.security.CodeSource;
 import java.security.Policy;
 import java.security.Principal;
 import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -54,12 +61,22 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 
+import static java.util.Arrays.asList;
+
 /**
  * This security service chooses a UUID as its token as this can be serialized
  * to clients, is mostly secure, and can be deserialized in a client vm without
  * addition openejb-core classes.
  */
-public abstract class AbstractSecurityService implements DestroyableResource, 
SecurityService<UUID>, ThreadContextListener, 
BasicPolicyConfiguration.RoleResolver {
+public abstract class AbstractSecurityService implements DestroyableResource, 
SecurityService<UUID>, ThreadContextListener,
+                                                         
BasicPolicyConfiguration.RoleResolver, PolicyContextHandler {
+
+    private static final Logger LOGGER = 
Logger.getInstance(LogCategory.OPENEJB_SECURITY, 
"org.apache.openejb.util.resources");
+
+    protected static final String KEY_SUBJECT = 
"javax.security.auth.Subject.container";
+    protected static final String KEY_REQUEST = 
"javax.servlet.http.HttpServletRequest";
+    protected static final Set<String> KEYS = new 
HashSet<>(asList(KEY_REQUEST, KEY_SUBJECT));
+
     private static final Map<Object, Identity> identities = new 
ConcurrentHashMap<Object, Identity>();
     protected static final ThreadLocal<Identity> clientIdentity = new 
ThreadLocal<Identity>();
     protected String defaultUser = "guest";
@@ -81,7 +98,19 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
         // set the default subject and the default context
         updateSecurityContext();
 
+        // we can now add the role resolver for Jacc to convert into strings
         
SystemInstance.get().setComponent(BasicPolicyConfiguration.RoleResolver.class, 
this);
+
+        // and finally we can register ourself as a PolicyContextHandler
+        // we can register policy handlers and the role mapper
+        try {
+            for (String key : getKeys()) {
+                PolicyContext.registerHandler(key, this, false);
+            }
+        } catch (final PolicyContextException e) {
+            // best would probably to fail start if something wrong happens
+            LOGGER.warning("Can't register PolicyContextHandler", e);
+        }
     }
 
     @Override
@@ -278,6 +307,40 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
         return false;
     }
 
+    protected Subject getSubject() {
+        final ThreadContext threadContext = ThreadContext.getThreadContext();
+        if (threadContext == null) {
+            final Identity id = clientIdentity.get();
+            if (id != null) {
+                return id.getSubject();
+            }
+            return new Subject();
+        }
+
+        final SecurityContext securityContext = 
threadContext.get(SecurityContext.class);
+        if (securityContext == null) { // unlikely
+            return new Subject();
+        }
+        return securityContext.subject;
+    }
+
+    @Override
+    public <P extends Principal> Set<P> getPrincipalsByType(final Class<P> 
pType) {
+        if (pType == null) {
+            throw new IllegalArgumentException("Principal type can't be null");
+        }
+        return getSubject().getPrincipals(pType);
+    }
+
+    @Override
+    public ProtectionDomain getProtectionDomain() {
+        return new ProtectionDomain(
+            new CodeSource(null, (java.security.cert.Certificate[]) null),
+            null, null,
+            getSubject().getPrincipals().toArray(new Principal[0])
+        );
+    }
+
     @Override
     public Principal getCallerPrincipal() {
         final ThreadContext threadContext = ThreadContext.getThreadContext();
@@ -416,6 +479,24 @@ public abstract class AbstractSecurityService implements 
DestroyableResource, Se
         return defaultContext;
     }
 
+    @Override
+    public boolean supports(final String key) throws PolicyContextException {
+        return KEY_SUBJECT.equals(key);
+    }
+
+    @Override
+    public String[] getKeys() throws PolicyContextException {
+        return new String[] {KEY_SUBJECT};
+    }
+
+    @Override
+    public Object getContext(final String key, final Object data) throws 
PolicyContextException {
+        if (KEY_SUBJECT.equals(key)) {
+            return getSubject();
+        }
+        throw new PolicyContextException("Handler does not support key: " + 
key);
+    }
+
     public static final class ProvidedSecurityContext {
         public final SecurityContext context;
 
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/JaccProvider.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/JaccProvider.java
index 2eca8b4..50a13fe 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/JaccProvider.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/JaccProvider.java
@@ -136,4 +136,6 @@ public abstract class JaccProvider {
     public abstract void refresh();
 
     public abstract boolean implies(ProtectionDomain domain, Permission 
permission);
+
+    public abstract boolean hasAccessToWebResource(final String resource, 
final String... methods);
 }
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
index 3c733ae..9b53637 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/core/security/jacc/BasicJaccProvider.java
@@ -18,6 +18,8 @@
 package org.apache.openejb.core.security.jacc;
 
 import org.apache.openejb.core.security.JaccProvider;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.SecurityService;
 
 import javax.security.jacc.EJBMethodPermission;
 import javax.security.jacc.EJBRoleRefPermission;
@@ -40,6 +42,7 @@ import java.util.Set;
  * @version $Rev$ $Date$
  */
 public class BasicJaccProvider extends JaccProvider {
+
     private static final Set<Class> JACC_PERMISSIONS = new HashSet<Class>() {
         {
             add(EJBMethodPermission.class);
@@ -112,6 +115,16 @@ public class BasicJaccProvider extends JaccProvider {
             }
         }
 
-        return systemPolicy != null ? systemPolicy.implies(domain, permission) 
: false;
+        return systemPolicy != null && systemPolicy.implies(domain, 
permission);
+    }
+
+    public boolean hasAccessToWebResource(final String resource, final 
String... methods) {
+        final SecurityService securityService = 
SystemInstance.get().getComponent(SecurityService.class);
+        if (securityService != null) {
+            return implies(securityService.getProtectionDomain(), new 
WebResourcePermission(resource, methods));
+        }
+        return false;
+
     }
+
 }
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
index a83b8dd..205f139 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/ri/sp/PseudoSecurityService.java
@@ -24,6 +24,7 @@ import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Method;
 import java.security.Principal;
+import java.security.ProtectionDomain;
 import java.util.Collections;
 import java.util.Properties;
 import java.util.Set;
@@ -85,4 +86,14 @@ public class PseudoSecurityService implements 
SecurityService {
     public void onLogout(final HttpServletRequest request) {
         // no-op
     }
+
+    @Override
+    public Set getPrincipalsByType(final Class pType) {
+        return Collections.emptySet();
+    }
+
+    @Override
+    public ProtectionDomain getProtectionDomain() {
+        return null;
+    }
 }
\ No newline at end of file
diff --git 
a/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
 
b/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
index e1ed185..1b85d6a 100644
--- 
a/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
+++ 
b/container/openejb-core/src/main/java/org/apache/openejb/spi/SecurityService.java
@@ -23,6 +23,8 @@ import javax.security.auth.login.LoginException;
 import javax.servlet.http.HttpServletRequest;
 import java.lang.reflect.Method;
 import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.util.Set;
 
 /**
  * The generic value T is any serializable token of the SecurityService
@@ -69,6 +71,9 @@ public interface SecurityService<T> extends Service {
      */
     Principal getCallerPrincipal();
 
+    <P extends Principal> Set<P> getPrincipalsByType(final Class<P> pType);
+    ProtectionDomain getProtectionDomain();
+
     /**
      * Active
      */
diff --git 
a/tomee/apache-tomee/src/patch/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
 
b/tomee/apache-tomee/src/patch/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
index 45d6bf7..d785d4e 100644
--- 
a/tomee/apache-tomee/src/patch/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
+++ 
b/tomee/apache-tomee/src/patch/java/org/apache/catalina/authenticator/jaspic/CallbackHandlerImpl.java
@@ -52,8 +52,7 @@ import java.util.List;
  */
 public class CallbackHandlerImpl implements CallbackHandler, Contained {
 
-    private static final StringManager sm = StringManager.getManager(
-            
org.apache.catalina.authenticator.jaspic.CallbackHandlerImpl.class);
+    private static final StringManager sm = 
StringManager.getManager(org.apache.catalina.authenticator.jaspic.CallbackHandlerImpl.class);
     private final Log log = 
LogFactory.getLog(org.apache.catalina.authenticator.jaspic.CallbackHandlerImpl.class);
 // must not be static
 
     private Container container;
@@ -85,16 +84,16 @@ public class CallbackHandlerImpl implements 
CallbackHandler, Contained {
                         
log.warn(sm.getString("callbackHandlerImpl.containerMissing", 
callback.getClass().getName()));
                     } else if (container.getRealm() == null) {
                         
log.warn(sm.getString("callbackHandlerImpl.realmMissing",
-                                callback.getClass().getName(), 
container.getName()));
+                                              callback.getClass().getName(), 
container.getName()));
                     } else {
                         PasswordValidationCallback pvc = 
(PasswordValidationCallback) callback;
                         principal = 
container.getRealm().authenticate(pvc.getUsername(),
-                                String.valueOf(pvc.getPassword()));
+                                                                      
String.valueOf(pvc.getPassword()));
                         subject = pvc.getSubject();
                     }
                 } else {
                     
log.error(sm.getString("callbackHandlerImpl.jaspicCallbackMissing",
-                            callback.getClass().getName()));
+                                           callback.getClass().getName()));
                 }
             }
 
@@ -119,6 +118,11 @@ public class CallbackHandlerImpl implements 
CallbackHandler, Contained {
                 }
 
                 subject.getPrivateCredentials().add(new 
GenericPrincipal(mergeName, null, mergeRoles, mergePrincipal));
+
+                // may come from CallerPrincipalCallback and we need to being 
to get it from the Subject
+                if (principal != null) {
+                    subject.getPrincipals().add(principal);
+                }
             }
         }
     }
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/Contexts.java 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/Contexts.java
index 2208d91..c002279 100644
--- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/Contexts.java
+++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/Contexts.java
@@ -25,10 +25,20 @@ import org.apache.catalina.core.StandardEngine;
 import org.apache.catalina.core.StandardHost;
 import org.apache.catalina.util.ContextName;
 
+import javax.servlet.ServletContext;
 import java.io.File;
 import java.io.IOException;
 
 public class Contexts {
+
+    public static String toAppContext(final ServletContext servletContext, 
final String contextPath) {
+        return servletContext.getVirtualServerName() + " " + contextPath;
+    }
+
+    public static String toAppContext(final StandardContext standardContext) {
+        return toAppContext(standardContext.getServletContext(), 
standardContext.getPath());
+    }
+
     public static String getHostname(final StandardContext ctx) {
         String hostName = null;
         final Container parentHost = ctx.getParent();
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 f21261c..058367d 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
@@ -31,6 +31,7 @@ import org.apache.tomee.loader.TomcatHelper;
 import javax.security.auth.Subject;
 import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginException;
+import javax.security.jacc.PolicyContextException;
 import javax.servlet.http.HttpServletRequest;
 import java.io.Serializable;
 import java.security.Principal;
@@ -119,13 +120,27 @@ public class TomcatSecurityService extends 
AbstractSecurityService {
     }
 
     private Subject createSubject(final Realm realm, final Principal 
principal) {
-        final Set<Principal> principals = new HashSet<>();
-        if (principal.getClass().isAnnotationPresent(CallerPrincipal.class)) {
-            principals.add(principal);
-        } else {
-            principals.add(new TomcatUser(realm, principal));
+        final Subject subject = new Subject();
+
+        // 1. Add the principal as is
+        subject.getPrincipals().add(principal);
+        subject.getPrincipals().add(new TomcatUser(realm, principal));
+
+        Principal p = principal;
+        if (principal instanceof TomcatUser) { // should never happen
+            p = ((TomcatUser) principal).getTomcatPrincipal();
+            subject.getPrincipals().add(p);
         }
-        return new Subject(true, principals, new HashSet(), new HashSet());
+
+        if (p instanceof GenericPrincipal) {
+            final GenericPrincipal genericPrincipal = (GenericPrincipal) p;
+            subject.getPrincipals().add(genericPrincipal.getUserPrincipal());
+
+            // todo should we create credentials with the roles? groups?
+            subject.getPrivateCredentials().add(p);
+        }
+
+        return subject;
     }
 
     @Override
@@ -366,4 +381,27 @@ public class TomcatSecurityService extends 
AbstractSecurityService {
         return super.getDefaultSecurityContext();
     }
 
+    @Override
+    public boolean supports(final String key) throws PolicyContextException {
+        return KEYS.contains(key);
+    }
+
+    @Override
+    public String[] getKeys() throws PolicyContextException {
+        return KEYS.toArray(new String[0]);
+    }
+
+    @Override
+    public Object getContext(final String key, final Object data) throws 
PolicyContextException {
+        switch (key) {
+            case KEY_REQUEST:
+                return OpenEJBSecurityListener.requests.get();
+            case KEY_SUBJECT:
+                // quite obvious as internally we keep track of it
+                // but we could also grab the request and the principals and 
build a new Subject with the principals
+                return getSubject();
+            default:
+                throw new PolicyContextException("Handler does not support 
key: " + key);
+        }
+    }
 }
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
index f5da4f9..84fc828 100644
--- 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java
@@ -73,10 +73,12 @@ import org.apache.openejb.assembler.classic.ConnectorInfo;
 import org.apache.openejb.assembler.classic.DeploymentExceptionManager;
 import org.apache.openejb.assembler.classic.EjbJarInfo;
 import org.apache.openejb.assembler.classic.InjectionBuilder;
+import org.apache.openejb.assembler.classic.JaccPermissionsBuilder;
 import org.apache.openejb.assembler.classic.JndiEncBuilder;
 import org.apache.openejb.assembler.classic.OpenEjbConfiguration;
 import org.apache.openejb.assembler.classic.OpenEjbConfigurationFactory;
 import org.apache.openejb.assembler.classic.PersistenceUnitInfo;
+import org.apache.openejb.assembler.classic.PolicyContext;
 import org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory;
 import org.apache.openejb.assembler.classic.ResourceInfo;
 import org.apache.openejb.assembler.classic.ServletInfo;
@@ -122,6 +124,7 @@ import 
org.apache.tomcat.util.descriptor.web.ContextTransaction;
 import org.apache.tomcat.util.descriptor.web.FilterDef;
 import org.apache.tomcat.util.descriptor.web.FilterMap;
 import org.apache.tomcat.util.descriptor.web.ResourceBase;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
 import org.apache.tomcat.util.http.CookieProcessor;
 import org.apache.tomcat.util.scan.StandardJarScanFilter;
 import org.apache.tomee.catalina.cdi.ServletContextHandler;
@@ -131,6 +134,7 @@ import 
org.apache.tomee.catalina.cluster.TomEEClusterListener;
 import org.apache.tomee.catalina.environment.Hosts;
 import org.apache.tomee.catalina.event.AfterApplicationCreated;
 import org.apache.tomee.catalina.routing.RouterValve;
+import 
org.apache.tomee.catalina.security.TomcatSecurityConstaintsToJaccPermissionsTransformer;
 import org.apache.tomee.common.NamingUtil;
 import org.apache.tomee.common.UserTransactionFactory;
 import org.apache.tomee.config.TomEESystemConfig;
@@ -145,6 +149,8 @@ import javax.naming.NameNotFoundException;
 import javax.naming.NamingException;
 import javax.naming.Reference;
 import javax.naming.StringRefAddr;
+import javax.security.jacc.PolicyConfiguration;
+import javax.security.jacc.PolicyConfigurationFactory;
 import javax.servlet.ServletContext;
 import javax.servlet.SessionTrackingMode;
 import javax.servlet.http.HttpServletRequest;
@@ -597,6 +603,17 @@ public class TomcatWebAppBuilder implements WebAppBuilder, 
ContextListener, Pare
                     } else { // force a normal deployment with lazy building 
of AppInfo
                         deployWar(standardContext, host, null);
                     }
+
+                    // TODO should we copy the information in the appInfo 
using the jee object tree or add more to the info tree
+                    // this might then move to the assembler after webapp is 
deployed so we can read information from info tree
+                    // and build up all policy context from there instead of 
from Tomcat internal objects
+                    final TomcatSecurityConstaintsToJaccPermissionsTransformer 
transformer =
+                        new 
TomcatSecurityConstaintsToJaccPermissionsTransformer(standardContext);
+                    final PolicyContext policyContext = 
transformer.createResourceAndDataPermissions();
+
+                    final JaccPermissionsBuilder jaccPermissionsBuilder = new 
JaccPermissionsBuilder();
+                    jaccPermissionsBuilder.install(policyContext);
+
                 }
             }
         } finally { // cleanup temp var passing
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/HTTPMethods.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/HTTPMethods.java
new file mode 100644
index 0000000..1356e69
--- /dev/null
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/HTTPMethods.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2018 OmniFaces.
+ * Copyright 2003-2011 The Apache Software Foundation.
+ *
+ * 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.apache.tomee.catalina.security;
+
+/**
+ *
+ * @author Guillermo González de Agüero
+ */
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Tracks sets of HTTP actions for use while computing permissions during web
+ * deployment.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HTTPMethods {
+
+    private final Set<String> methods = new HashSet<String>();
+
+    private boolean isExcluded = false;
+
+    public HTTPMethods(Set<String> httpMethods, boolean isExcluded) {
+        this.isExcluded = isExcluded;
+        methods.addAll(httpMethods);
+    }
+
+    public HTTPMethods(HTTPMethods httpMethods, boolean complemented) {
+        isExcluded = httpMethods.isExcluded ^ complemented;
+        methods.addAll(httpMethods.methods);
+    }
+
+    /**
+     * Generally speaking, add method is to perform a union action between the
+     * caller and the parameters
+     *
+     * @param httpMethods
+     * @param addedMethodsExcluded
+     */
+    public void add(Set<String> httpMethods, boolean addedMethodsExcluded) {
+        //JACC 3.1.3.2 Combining HTTP Methods
+        //An empty list combines with any other list to yield the empty list.
+        if (isExcluded && httpMethods.isEmpty()) {
+            return;
+        }
+        if (httpMethods.size() == 0) {
+            isExcluded = addedMethodsExcluded;
+            methods.clear();
+            return;
+        }
+        //JACC 3.1.3.2 Combing HTTP Methods
+        //Lists of http-method elements combine to yield a list of http-method 
elements containing the union (without duplicates) of the http-method elements 
that occur in the individual lists.
+        //Lists of http-method-omission elements combine to yield a list 
containing only the http-method-omission elements that occur in all of the 
individual lists (i.e., the intersection).
+        //A list of http-method-omission elements combines with a list of 
http-method elements to yield the list of http-method-omission elements minus 
any elements whose method name occurs in the http-method list
+        if (isExcluded) {
+            if (addedMethodsExcluded) {
+                //ExceptionList + ExceptionList
+                methods.retainAll(httpMethods);
+            } else {
+                //ExceptionList + List
+                methods.removeAll(httpMethods);
+            }
+        } else {
+            if (addedMethodsExcluded) {
+                //List + ExceptionList
+                Set<String> tempHttpMethods = new HashSet<String>(httpMethods);
+                tempHttpMethods.removeAll(methods);
+                methods.clear();
+                methods.addAll(tempHttpMethods);
+                isExcluded = true;
+            } else {
+                //List + List
+                methods.addAll(httpMethods);
+            }
+        }
+    }
+
+    public HTTPMethods add(HTTPMethods httpMethods) {
+        add(httpMethods.methods, httpMethods.isExcluded);
+        return this;
+    }
+
+    /**
+     * Remove methods is only used while we wish to remove those configurations
+     * in role/unchecked constraints, which are also configured in excluded
+     * constraints
+     *
+     * @param httpMethods
+     * @return
+     */
+    public HTTPMethods remove(HTTPMethods httpMethods) {
+        if (isExcluded) {
+            if (httpMethods.isExcluded) {
+                //TODO questionable
+                isExcluded = false;
+                Set<String> toRemove = new HashSet<String>(methods);
+                methods.clear();
+                methods.addAll(httpMethods.methods);
+                methods.removeAll(toRemove);
+            } else {
+                methods.addAll(httpMethods.methods);
+            }
+        } else {
+            if (httpMethods.isExcluded) {
+                methods.retainAll(httpMethods.methods);
+            } else {
+                methods.removeAll(httpMethods.methods);
+            }
+        }
+        if (!isExcluded && methods.isEmpty()) {
+            return null;
+        }
+        return this;
+    }
+
+    public String getHttpMethods() {
+        return getHttpMethodsBuffer(isExcluded).toString();
+    }
+
+    public StringBuilder getHttpMethodsBuffer() {
+        return getHttpMethodsBuffer(isExcluded);
+    }
+
+    public String getComplementedHttpMethods() {
+        return getHttpMethodsBuffer(!isExcluded).toString();
+    }
+
+    private StringBuilder getHttpMethodsBuffer(boolean excluded) {
+        StringBuilder buffer = new StringBuilder();
+        if (excluded) {
+            buffer.append("!");
+        }
+        boolean afterFirst = false;
+        for (String method : methods) {
+            if (afterFirst) {
+                buffer.append(",");
+            } else {
+                afterFirst = true;
+            }
+            buffer.append(method);
+        }
+        return buffer;
+    }
+
+    public boolean isNone() {
+        return !isExcluded && methods.isEmpty();
+    }
+}
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/TomcatSecurityConstaintsToJaccPermissionsTransformer.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/TomcatSecurityConstaintsToJaccPermissionsTransformer.java
new file mode 100644
index 0000000..94d88f8
--- /dev/null
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/TomcatSecurityConstaintsToJaccPermissionsTransformer.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2018 OmniFaces.
+ * Copyright 2003-2011 The Apache Software Foundation.
+ *
+ * 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.apache.tomee.catalina.security;
+
+import org.apache.catalina.Container;
+import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.core.StandardContext;
+import org.apache.openejb.assembler.classic.DelegatePermissionCollection;
+import org.apache.openejb.assembler.classic.PolicyContext;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+
+import javax.security.jacc.PolicyContextException;
+import javax.security.jacc.WebResourcePermission;
+import javax.security.jacc.WebRoleRefPermission;
+import javax.security.jacc.WebUserDataPermission;
+import javax.servlet.ServletContext;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+/**
+ * @author Guillermo González de Agüero
+ */
+public class TomcatSecurityConstaintsToJaccPermissionsTransformer {
+
+    // from context
+    final StandardContext standardContext;
+    private final List<SecurityConstraint> constraints;
+    private final List<String> declaredRoles;
+    private final boolean isDenyUncoveredHttpMethods;
+
+    // final result
+    private final PolicyContext policyContext;
+
+    // computed in various methods
+    private final Set<String> securityRoles = new HashSet<>();
+    private final Map<String, URLPattern> uncheckedPatterns = new HashMap<>();
+    private final Map<UncheckedItem, HTTPMethods> uncheckedResourcePatterns = 
new HashMap<>();
+    private final Map<UncheckedItem, HTTPMethods> uncheckedUserPatterns = new 
HashMap<>();
+    private final Map<String, URLPattern> excludedPatterns = new HashMap<>();
+    private final Map<String, Map<String, URLPattern>> rolesPatterns = new 
HashMap<>();
+    private final Set<URLPattern> allSet = new HashSet<>();
+    private final Map<String, URLPattern> allMap = new HashMap<>(); 
//uncheckedPatterns union excludedPatterns union rolesPatterns.
+
+    public TomcatSecurityConstaintsToJaccPermissionsTransformer(final 
StandardContext standardContext) {
+        this.standardContext = standardContext;
+
+        constraints = new 
ArrayList<>(asList(standardContext.findConstraints()));
+        declaredRoles = asList(standardContext.findSecurityRoles());
+        isDenyUncoveredHttpMethods = 
standardContext.getDenyUncoveredHttpMethods();
+
+        // todo move all host context id crap into something consistent like 
in Tomcat JASPIC`
+        // instead of only using host and context path - consistency and safe
+        final ServletContext servletContext = 
standardContext.getServletContext();
+        final String id = servletContext.getVirtualServerName() + " " + 
servletContext.getContextPath();
+        policyContext = new PolicyContext(id);
+    }
+
+    public PolicyContext createResourceAndDataPermissions() {
+
+            securityRoles.addAll(declaredRoles);
+
+            // todo, improve this part so roles are extracted in the 
constructor and we don't need standard context
+            // it should even receive in the constructor all required 
information from TomcatWebAppBuilder so it's more testable
+            // find all role ref permission - probably too wide
+            for (Container container : standardContext.findChildren()) {
+                if (container instanceof Wrapper) {
+                    processRoleRefPermissions((Wrapper) container);
+                }
+            }
+
+            addUnmappedJSPPermissions();
+            analyzeSecurityConstraints();
+            removeExcludedDups();
+            buildPermissions();
+
+            // all populated now
+            return policyContext;
+
+    }
+
+    private void analyzeSecurityConstraints() {
+        for (SecurityConstraint securityConstraint : constraints) {
+            Map<String, URLPattern> currentPatterns = null;
+            Set<String> roleNames = null;
+            if (securityConstraint.getAuthConstraint()) {
+                if (securityConstraint.findAuthRoles().length == 0) {
+                    currentPatterns = excludedPatterns;
+
+                } else {
+                    roleNames = new 
HashSet<String>(Arrays.asList(securityConstraint.findAuthRoles()));
+                    if (roleNames.remove("*")) {
+                        roleNames.addAll(securityRoles);
+                    }
+                }
+
+            } else {
+                currentPatterns = uncheckedPatterns;
+            }
+            String transport = securityConstraint.getUserConstraint() == null 
? "NONE" : securityConstraint.getUserConstraint();
+
+            boolean isRoleBasedPattern = (currentPatterns == null);
+
+            if (securityConstraint.findCollections() != null) {
+                for (SecurityCollection webResourceCollection : 
securityConstraint.findCollections()) {
+                    //Calculate HTTP methods list
+                    for (String urlPattern : 
webResourceCollection.findPatterns()) {
+
+                        if (isRoleBasedPattern) {
+                            for (String roleName : roleNames) {
+                                Map<String, URLPattern> currentRolePatterns = 
rolesPatterns.get(roleName);
+                                if (currentRolePatterns == null) {
+                                    currentRolePatterns = new HashMap<>();
+                                    rolesPatterns.put(roleName, 
currentRolePatterns);
+                                }
+
+                                boolean omission = false;
+                                String[] httpMethods = 
webResourceCollection.findMethods();
+                                if (httpMethods.length == 0) {
+                                    omission = true;
+                                    httpMethods = 
webResourceCollection.findOmittedMethods();
+                                }
+
+                                analyzeURLPattern(urlPattern, new 
HashSet<>(Arrays.asList(httpMethods)), omission, transport, 
currentRolePatterns);
+                            }
+
+                        } else {
+                            boolean omission = false;
+                            String[] httpMethods = 
webResourceCollection.findMethods();
+                            if (httpMethods.length == 0) {
+                                omission = true;
+                                httpMethods = 
webResourceCollection.findOmittedMethods();
+                            }
+
+                            analyzeURLPattern(urlPattern, new 
HashSet<>(Arrays.asList(httpMethods)), omission, transport, currentPatterns);
+                        }
+                        URLPattern allPattern = allMap.get(urlPattern);
+
+                        if (allPattern == null) {
+                            boolean omission = false;
+                            String[] httpMethods = 
webResourceCollection.findMethods();
+                            if (httpMethods.length == 0) {
+                                omission = true;
+                                httpMethods = 
webResourceCollection.findOmittedMethods();
+                            }
+
+                            allPattern = new URLPattern(urlPattern, new 
HashSet<>(Arrays.asList(httpMethods)), omission);
+                            allSet.add(allPattern);
+                            allMap.put(urlPattern, allPattern);
+
+                        } else {
+                            boolean omission = false;
+                            String[] httpMethods = 
webResourceCollection.findMethods();
+                            if (httpMethods.length == 0) {
+                                omission = true;
+                                httpMethods = 
webResourceCollection.findOmittedMethods();
+                            }
+
+                            allPattern.addMethods(new 
HashSet<>(Arrays.asList(httpMethods)), omission);
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+
+    private void analyzeURLPattern(final String urlPattern,
+                                final Set<String> httpMethods,
+                                final boolean omission,
+                                final String transport,
+                                final Map<String, URLPattern> currentPatterns) 
{
+
+        URLPattern pattern = currentPatterns.get(urlPattern);
+        if (pattern == null) {
+            pattern = new URLPattern(urlPattern, httpMethods, omission);
+            currentPatterns.put(urlPattern, pattern);
+
+        } else {
+            pattern.addMethods(httpMethods, omission);
+        }
+        pattern.setTransport(transport);
+    }
+
+    private void removeExcludedDups() {
+        for (Map.Entry<String, URLPattern> excluded : 
excludedPatterns.entrySet()) {
+            String url = excluded.getKey();
+            URLPattern pattern = excluded.getValue();
+            removeExcluded(url, pattern, uncheckedPatterns);
+            for (Map<String, URLPattern> rolePatterns : 
rolesPatterns.values()) {
+                removeExcluded(url, pattern, rolePatterns);
+            }
+        }
+    }
+
+    private void removeExcluded(final String url, final URLPattern pattern, 
final Map<String, URLPattern> patterns) {
+        URLPattern testPattern = patterns.get(url);
+        if (testPattern != null) {
+            if (!testPattern.removeMethods(pattern)) {
+                patterns.remove(url);
+            }
+        }
+    }
+
+    private void buildPermissions() {
+
+        for (URLPattern pattern : excludedPatterns.values()) {
+            String name = pattern.getQualifiedPattern(allSet);
+            String actions = pattern.getMethods();
+            policyContext.getExcludedPermissions().add(new 
WebResourcePermission(name, actions));
+            policyContext.getExcludedPermissions().add(new 
WebUserDataPermission(name, actions));
+        }
+
+        for (Map.Entry<String, Map<String, URLPattern>> entry : 
rolesPatterns.entrySet()) {
+            Set<URLPattern> currentRolePatterns = new 
HashSet<URLPattern>(entry.getValue().values());
+            for (URLPattern pattern : entry.getValue().values()) {
+                String name = pattern.getQualifiedPattern(currentRolePatterns);
+                String actions = pattern.getMethods();
+                WebResourcePermission permission = new 
WebResourcePermission(name, actions);
+                policyContext.addRole(entry.getKey(), permission);
+                HTTPMethods methods = pattern.getHTTPMethods();
+                int transportType = pattern.getTransport();
+                addOrUpdatePattern(uncheckedUserPatterns, name, methods, 
transportType);
+            }
+        }
+
+        for (URLPattern pattern : uncheckedPatterns.values()) {
+            String name = pattern.getQualifiedPattern(allSet);
+            HTTPMethods methods = pattern.getHTTPMethods();
+            addOrUpdatePattern(uncheckedResourcePatterns, name, methods, 
URLPattern.NA);
+            int transportType = pattern.getTransport();
+            addOrUpdatePattern(uncheckedUserPatterns, name, methods, 
transportType);
+        }
+
+        /*
+         * A <code>WebResourcePermission</code> and a
+         * <code>WebUserDataPermission</code> must be instantiated for each
+         * <tt>url-pattern</tt> in the deployment descriptor and the default
+         * pattern "/", that is not combined by the
+         * <tt>web-resource-collection</tt> elements of the deployment
+         * descriptor with ever HTTP method value. The permission objects must
+         * be contructed using the qualified pattern as their name and with
+         * actions defined by the subset of the HTTP methods that do not occur
+         * in combination with the pattern. The resulting permissions that must
+         * be added to the unchecked policy statements by calling the
+         * <code>addToUncheckedPolcy</code> method on the
+         * <code>PolicyConfiguration</code> object.
+         */
+        for (URLPattern pattern : allSet) {
+            String name = pattern.getQualifiedPattern(allSet);
+            HTTPMethods methods = pattern.getComplementedHTTPMethods();
+            if (methods.isNone()) {
+                continue;
+            }
+            addOrUpdatePattern(uncheckedResourcePatterns, name, methods, 
URLPattern.NA);
+            addOrUpdatePattern(uncheckedUserPatterns, name, methods, 
URLPattern.NA);
+        }
+
+        if (!allMap.containsKey("/")) {
+            URLPattern pattern = new URLPattern("/", 
Collections.<String>emptySet(), false);
+            String name = pattern.getQualifiedPattern(allSet);
+            HTTPMethods methods = pattern.getComplementedHTTPMethods();
+            addOrUpdatePattern(uncheckedResourcePatterns, name, methods, 
URLPattern.NA);
+            addOrUpdatePattern(uncheckedUserPatterns, name, methods, 
URLPattern.NA);
+        }
+
+        //Create the uncheckedPermissions for WebResourcePermissions
+        for (UncheckedItem item : uncheckedResourcePatterns.keySet()) {
+            HTTPMethods methods = uncheckedResourcePatterns.get(item);
+            String actions = URLPattern.getMethodsWithTransport(methods, 
item.getTransportType());
+            policyContext.getUncheckedPermissions().add(new 
WebResourcePermission(item.getName(), actions));
+        }
+
+        //Create the uncheckedPermissions for WebUserDataPermissions
+        for (UncheckedItem item : uncheckedUserPatterns.keySet()) {
+            HTTPMethods methods = uncheckedUserPatterns.get(item);
+            String actions = URLPattern.getMethodsWithTransport(methods, 
item.getTransportType());
+            policyContext.getUncheckedPermissions().add(new 
WebUserDataPermission(item.getName(), actions));
+        }
+    }
+
+    private void addOrUpdatePattern(final Map<UncheckedItem, HTTPMethods> 
patternMap,
+                            final String name,
+                            final HTTPMethods actions,
+                            final int transportType) {
+
+        final UncheckedItem item = new UncheckedItem(name, transportType);
+        final HTTPMethods existingActions = patternMap.get(item);
+        if (existingActions != null) {
+            patternMap.put(item, existingActions.add(actions));
+
+        } else {
+            patternMap.put(item, new HTTPMethods(actions, false));
+        }
+    }
+
+    protected void processRoleRefPermissions(Wrapper servlet) {
+
+        final String servletName = servlet.getName();
+
+        //WebRoleRefPermissions
+        Set<String> unmappedRoles = new HashSet<>(securityRoles);
+        for (String securityRoleRef : servlet.findSecurityReferences()) {
+            //jacc 3.1.3.2
+            /*   The name of the WebRoleRefPermission must be the servlet-name 
in whose
+             * context the security-role-ref is defined. The actions of the  
WebRoleRefPermission
+             * must be the value of the role-name (that is the  reference), 
appearing in the security-role-ref.
+             * The deployment tools must  call the addToRole method on the 
PolicyConfiguration object to add the
+             * WebRoleRefPermission object resulting from the translation to 
the role
+             * identified in the role-link appearing in the security-role-ref.
+             */
+            
policyContext.addRole(servlet.findSecurityReference(securityRoleRef),
+                                          new 
WebRoleRefPermission(servletName, securityRoleRef));
+            unmappedRoles.remove(securityRoleRef);
+        }
+
+        for (String roleName : unmappedRoles) {
+            policyContext.addRole(roleName, new 
WebRoleRefPermission(servletName, roleName));
+        }
+    }
+
+    protected void addUnmappedJSPPermissions() {
+        for (String roleName : securityRoles) {
+            policyContext.addRole(roleName, new WebRoleRefPermission("", 
roleName));
+        }
+    }
+
+}
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPattern.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPattern.java
new file mode 100644
index 0000000..e43023c
--- /dev/null
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPattern.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2018 OmniFaces.
+ * Copyright 2003-2011 The Apache Software Foundation.
+ *
+ * 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.apache.tomee.catalina.security;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ *
+ * @author Guillermo González de Agüero
+ */
+
+/**
+ * Utility class for <code>ModuleConfiguration</code>.  This class is used to 
generate qualified patterns, HTTP
+ * method sets, complements of HTTP method sets, and HTTP method sets w/ 
transport restrictions for URL patterns that
+ * are found in the web deployment descriptor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class URLPattern {
+    public final static int NA = 0x00;
+    public final static int INTEGRAL = 0x01;
+    public final static int CONFIDENTIAL = 0x02;
+
+    private final URLPatternCheck type;
+    private final String pattern;
+    private final HTTPMethods httpMethods;
+    private int transport;
+
+    /**
+     * Construct an instance of the utility class for 
<code>WebModuleConfiguration</code>.
+     *
+     * @param pat the URL pattern that this instance is to collect information 
on
+     * @see "JSR 115, section 3.1.3" Translating Servlet Deployment Descriptors
+     */
+    public URLPattern(String pat, Set<String> methods, boolean 
isHttpMethodExcluded) {
+        if (pat == null)
+            throw new IllegalArgumentException("URL pattern cannot be null");
+        if (pat.length() == 0)
+            throw new IllegalArgumentException("URL pattern cannot be empty");
+        if (pat.equals("/") || pat.equals("/*")) {
+            type = DEFAULT;
+            pat = "/";
+        } else if (pat.charAt(0) == '/' && pat.endsWith("/*")) {
+            type = PATH_PREFIX;
+        } else if (pat.charAt(0) == '*') {
+            type = EXTENSION;
+        } else {
+            type = EXACT;
+        }
+        pattern = pat;
+        httpMethods = new HTTPMethods(methods, isHttpMethodExcluded);
+    }
+
+    /**
+     * Get a qualifed URL pattern relative to a particular set of URL 
patterns.  This algorithm is described in
+     * JSR 115, section 3.1.3.1 "Qualified URL Pattern Names".
+     *
+     * @param patterns the set of possible URL patterns that could be used to 
qualify this pattern
+     * @return a qualifed URL pattern
+     */
+    public String getQualifiedPattern(Set<URLPattern> patterns) {
+        if (type == EXACT) {
+            return pattern;
+        } else {
+            HashSet<String> bucket = new HashSet<String>();
+            StringBuilder result = new StringBuilder(pattern);
+
+            // Collect a set of qualifying patterns, depending on the type of 
this pattern.
+            for (URLPattern p : patterns) {
+                if (type.check(this, p)) {
+                    bucket.add(p.pattern);
+                }
+            }
+            // append the set of qualifying patterns
+            for (String aBucket : bucket) {
+                result.append(':');
+                result.append(aBucket);
+            }
+            return result.toString();
+        }
+    }
+
+    /**
+     * Add a method to the union of HTTP methods associated with this URL 
pattern.  An empty Set  is short hand for
+     * the set of all HTTP methods.
+     *
+     * @param methods the HTTP methods to be added to the set.
+     */
+    public void addMethods(Set<String> methods, boolean isExcluded) {
+        httpMethods.add(methods, isExcluded);
+    }
+
+    public boolean removeMethods(URLPattern other) {
+        return httpMethods.remove(other.getHTTPMethods()) != null;
+    }
+
+    /**
+     * Return the set of HTTP methods that have been associated with this URL 
pattern.
+     *
+     * @return a set of HTTP methods
+     */
+    public String getMethods() {
+        return httpMethods.getHttpMethods();
+    }
+
+
+    public String getComplementedMethods() {
+        return httpMethods.getComplementedHttpMethods();
+    }
+
+    public HTTPMethods getHTTPMethods() {
+        return httpMethods;
+    }
+
+    public HTTPMethods getComplementedHTTPMethods() {
+        return new HTTPMethods(httpMethods, true);
+    }
+
+    public String getMethodsWithTransport() {
+        return getMethodsWithTransport(httpMethods, transport);
+    }
+
+    public static String getMethodsWithTransport(HTTPMethods methods, int 
transport) {
+        StringBuilder buffer = methods.getHttpMethodsBuffer();
+
+
+        if (transport != NA) {
+            buffer.append(":");
+
+            if (transport != 0x03) {
+                if (transport == INTEGRAL) {
+                    buffer.append("INTEGRAL");
+                } else {
+                    buffer.append("CONFIDENTIAL");
+                }
+            }
+        }
+
+        return buffer.toString();
+    }
+
+    public void setTransport(String trans) {
+        switch (transport) {
+            case NA: {
+                if ("INTEGRAL".equals(trans)) {
+                    transport = INTEGRAL;
+                } else if ("CONFIDENTIAL".equals(trans)) {
+                    transport = CONFIDENTIAL;
+                }
+                break;
+            }
+
+            case INTEGRAL: {
+                if ("CONFIDENTIAL".equals(trans)) {
+                    transport = CONFIDENTIAL;
+                }
+                break;
+            }
+        }
+    }
+
+    public int getTransport() {
+        return transport;
+    }
+
+    /**
+     * TODO this is kinda weird without an explanation
+     * @param obj object to compare with
+     * @return if this equals obj
+     */
+    public boolean equals(Object obj) {
+        if (!(obj instanceof URLPattern)) return false;
+
+        URLPattern test = (URLPattern) obj;
+
+        return pattern.equals(test.pattern);
+    }
+
+    public int hashCode() {
+        return pattern.hashCode();
+    }
+
+    boolean matches(URLPattern p) {
+        String test = p.pattern;
+
+        // their pattern values are String equivalent
+        if (pattern.equals(test)) return true;
+
+        return type.matches(pattern, test);
+    }
+
+    private final static URLPatternCheck EXACT = new URLPatternCheck() {
+        public boolean check(URLPattern base, URLPattern test) {
+            return matches(base.pattern, test.pattern);
+        }
+
+        public boolean matches(String base, String test) {
+            return base.equals(test);
+        }
+    };
+
+    private final static URLPatternCheck PATH_PREFIX = new URLPatternCheck() {
+        public boolean check(URLPattern base, URLPattern test) {
+            return ((test.type == PATH_PREFIX || test.type == EXACT)
+                    && base.matches(test)
+                    && !base.equals(test));
+        }
+
+        /**
+         * This pattern is a path-prefix pattern (that is, it starts with "/" 
and ends with "/*") and the argument
+         * pattern starts with the substring of this pattern, minus its last 2 
characters, and the next character of
+         * the argument pattern, if there is one, is "/"
+         *
+         * @param base the base pattern
+         * @param test the pattern to be tested
+         * @return <code>true</code> if <code>test</code> is matched by 
<code>base</code>
+         */
+        public boolean matches(String base, String test) {
+            int length = base.length() - 2;
+            if (length > test.length()) return false;
+
+            for (int i = 0; i < length; i++) {
+                if (base.charAt(i) != test.charAt(i)) return false;
+            }
+
+            if (test.length() == length)
+                return true;
+            else if (test.charAt(length) != '/') return false;
+
+            return true;
+        }
+    };
+
+    private final static URLPatternCheck EXTENSION = new URLPatternCheck() {
+        public boolean check(URLPattern base, URLPattern test) {
+            if (test.type == PATH_PREFIX) return true;
+
+            if (test.type == EXACT) return matches(base.pattern, test.pattern);
+
+            return false;
+        }
+
+        /**
+         * This pattern is an extension pattern (that is, it startswith "*.") 
and the argument pattern ends with
+         * this pattern.
+         *
+         * @param base the base pattern
+         * @param test the pattern to be tested
+         * @return <code>true</code> if <code>test</code> is matched by 
<code>base</code>
+         */
+        public boolean matches(String base, String test) {
+            return test.endsWith(base.substring(1));
+        }
+    };
+
+    private final static URLPatternCheck DEFAULT = new URLPatternCheck() {
+        public boolean check(URLPattern base, URLPattern test) {
+            return base.matches(test) && !base.equals(test);
+        }
+
+        /**
+         * This pattern is the path-prefix pattern "/*" or the reference 
pattern is the special default pattern,
+         * "/", which matches all argument patterns.
+         *
+         * @param base the base pattern
+         * @param test the pattern to be tested
+         * @return <code>true</code> if <code>test</code> is matched by 
<code>base</code>
+         * @see "JSR 115"
+         */
+        public boolean matches(String base, String test) {
+            return true;
+        }
+    };
+}
\ No newline at end of file
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPatternCheck.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPatternCheck.java
new file mode 100644
index 0000000..5620270
--- /dev/null
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/URLPatternCheck.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2018 OmniFaces.
+ * Copyright 2003-2011 The Apache Software Foundation.
+ *
+ * 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.apache.tomee.catalina.security;
+
+/**
+ *
+ * @author Guillermo González de Agüero
+ */
+public abstract class URLPatternCheck {
+
+    public abstract boolean check(URLPattern base, URLPattern test);
+
+    public abstract boolean matches(String base, String test);
+}
\ No newline at end of file
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/UncheckedItem.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/UncheckedItem.java
new file mode 100644
index 0000000..fb82bda
--- /dev/null
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/security/UncheckedItem.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 OmniFaces.
+ * Copyright 2003-2011 The Apache Software Foundation.
+ *
+ * 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.apache.tomee.catalina.security;
+
+/**
+ *
+ * @author Guillermo González de Agüero
+ */
+class UncheckedItem {
+    final static int NA = 0x00;
+    final static int INTEGRAL = 0x01;
+    final static int CONFIDENTIAL = 0x02;
+
+    private int transportType = NA;
+    private String name;
+
+    public UncheckedItem(String name, int transportType) {
+        setName(name);
+        setTransportType(transportType);
+    }
+
+    public boolean equals(Object o) {
+        if (o instanceof UncheckedItem) {
+            UncheckedItem item = (UncheckedItem) o;
+            return item.transportType == transportType && 
item.name.equals(this.name);
+        }
+        return false;
+    }
+
+
+    public int hashCode() {
+        return name.hashCode() + transportType;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getTransportType() {
+        return transportType;
+    }
+
+    public void setTransportType(int transportType) {
+        this.transportType = transportType;
+    }
+}
\ No newline at end of file
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java
index 037467e..4afcc7c 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/TomEESecurityContext.java
@@ -19,8 +19,11 @@ package org.apache.tomee.security;
 import org.apache.catalina.authenticator.jaspic.CallbackHandlerImpl;
 import org.apache.catalina.connector.Request;
 import org.apache.catalina.realm.GenericPrincipal;
+import org.apache.openejb.core.security.JaccProvider;
+import org.apache.openejb.core.security.jacc.BasicJaccProvider;
 import org.apache.openejb.loader.SystemInstance;
 import org.apache.openejb.spi.SecurityService;
+import org.apache.openejb.util.JavaSecurityManagers;
 import org.apache.tomee.catalina.OpenEJBSecurityListener;
 import org.apache.tomee.catalina.TomcatSecurityService;
 import org.apache.tomee.security.message.TomEEMessageInfo;
@@ -47,9 +50,12 @@ import java.util.Set;
 import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
 import static javax.security.auth.message.AuthStatus.SEND_FAILURE;
 import static javax.security.auth.message.AuthStatus.SUCCESS;
+import static org.apache.tomee.catalina.Contexts.toAppContext;
 
 public class TomEESecurityContext implements SecurityContext {
+
     private TomcatSecurityService securityService;
+    private JaccProvider jaccProvider;
 
     @PostConstruct
     private void init() {
@@ -57,6 +63,7 @@ public class TomEESecurityContext implements SecurityContext {
         if (securityService instanceof TomcatSecurityService) {
             this.securityService = (TomcatSecurityService) securityService;
         }
+        jaccProvider = JaccProvider.get();
     }
 
     @Override
@@ -66,8 +73,7 @@ public class TomEESecurityContext implements SecurityContext {
 
     @Override
     public <T extends Principal> Set<T> getPrincipalsByType(final Class<T> 
pType) {
-        // todo
-        return Collections.emptySet();
+        return securityService.getPrincipalsByType(pType);
     }
 
     @Override
@@ -77,8 +83,7 @@ public class TomEESecurityContext implements SecurityContext {
 
     @Override
     public boolean hasAccessToWebResource(final String resource, final 
String... methods) {
-        // todo
-        return false;
+        return jaccProvider.hasAccessToWebResource(resource, methods);
     }
 
     @Override
@@ -115,7 +120,7 @@ public class TomEESecurityContext implements 
SecurityContext {
     }
 
     private ServerAuthContext getServerAuthContext(final HttpServletRequest 
request) throws AuthException {
-        final String appContext = 
request.getServletContext().getVirtualServerName() + " " + 
request.getContextPath();
+        final String appContext = toAppContext(request.getServletContext(), 
request.getContextPath());
 
         final AuthConfigProvider authConfigProvider =
                 
AuthConfigFactory.getFactory().getConfigProvider("HttpServlet", appContext, 
null);
@@ -126,6 +131,7 @@ public class TomEESecurityContext implements 
SecurityContext {
     }
 
     public static void registerContainerAboutLogin(final Principal principal, 
final Set<String> groups) {
+
         final SecurityService securityService = 
SystemInstance.get().getComponent(SecurityService.class);
         if (securityService instanceof TomcatSecurityService) {
             final TomcatSecurityService tomcatSecurityService = 
(TomcatSecurityService) securityService;
@@ -136,9 +142,15 @@ public class TomEESecurityContext implements 
SecurityContext {
                         null,
                         groups == null ? Collections.emptyList() : new 
ArrayList<>(groups),
                         principal);
+
+            // todo should it be done in the enterWebApp?
+            
JavaSecurityManagers.setContextID(toAppContext(request.getServletContext(), 
request.getContextPath()));
+
             tomcatSecurityService.enterWebApp(request.getWrapper().getRealm(),
                                               genericPrincipal,
                                               request.getWrapper().getRunAs());
         }
     }
+
+
 }
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
index 591523f..c4462c6 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/cdi/TomEESecurityExtension.java
@@ -70,6 +70,8 @@ public class TomEESecurityExtension implements Extension {
     private final AtomicReference<Annotated> databaseStore = new 
AtomicReference<>();
     private final AtomicReference<Annotated> ldapStore = new 
AtomicReference<>();
 
+    private boolean applicationAuthenticationMechanisms = false;
+
     void observeBeforeBeanDiscovery(
         @Observes final BeforeBeanDiscovery beforeBeanDiscovery,
         final BeanManager beanManager) {
@@ -117,6 +119,10 @@ public class TomEESecurityExtension implements Extension {
         if (customMechanism.get() == null && 
annotatedType.isAnnotationPresent(CustomFormAuthenticationMechanismDefinition.class))
 {
             customMechanism.set(annotatedType);
         }
+
+        if 
(eventIn.getBean().getTypes().contains(HttpAuthenticationMechanism.class)) {
+            applicationAuthenticationMechanisms = true;
+        }
     }
 
     void registerAuthenticationMechanism(
@@ -294,7 +300,7 @@ public class TomEESecurityExtension implements Extension {
     }
 
     public boolean hasAuthenticationMechanisms() {
-        return basicMechanism.get() != null || formMechanism.get() != null || 
customMechanism.get() != null;
+        return basicMechanism.get() != null || formMechanism.get() != null || 
customMechanism.get() != null || applicationAuthenticationMechanisms;
     }
 
     private Supplier<LoginToContinue> createFormLoginToContinueSupplier(final 
BeanManager beanManager) {
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/identitystore/TomEEIdentityStoreHandler.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/identitystore/TomEEIdentityStoreHandler.java
index 91e660d..122b277 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/identitystore/TomEEIdentityStoreHandler.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/identitystore/TomEEIdentityStoreHandler.java
@@ -24,6 +24,8 @@ import javax.security.enterprise.credential.Credential;
 import javax.security.enterprise.identitystore.CredentialValidationResult;
 import javax.security.enterprise.identitystore.IdentityStore;
 import javax.security.enterprise.identitystore.IdentityStoreHandler;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -94,10 +96,25 @@ public class TomEEIdentityStoreHandler implements 
IdentityStoreHandler {
         }
 
         final Set<String> groups = new HashSet<>();
+
+        // Take the groups from the identity store that validated the 
credentials only
+        // if it has been set to provide groups.
         if (authorizedStore.validationTypes().contains(PROVIDE_GROUPS)) {
             groups.addAll(validationResult.getCallerGroups());
         }
 
+        // Ask all stores that were configured for group providing only to get 
the groups for the
+        // authenticated caller
+        final CredentialValidationResult finalResult = validationResult; // 
compiler didn't like validationResult in the enclosed scope
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                for (IdentityStore authorizationIdentityStore : 
authenticationStores) {
+                    
groups.addAll(authorizationIdentityStore.getCallerGroups(finalResult));
+                }
+                return null;
+            }
+        });
+
         final CredentialValidationResult authorizedValidationResult = 
validationResult;
         final Set<String> additionalGroups =
                 authorizationStores.stream()
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/provider/TomEESecurityServerAuthConfig.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/provider/TomEESecurityServerAuthConfig.java
index 5686b68..5e3c75a 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/provider/TomEESecurityServerAuthConfig.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/provider/TomEESecurityServerAuthConfig.java
@@ -49,7 +49,7 @@ public class TomEESecurityServerAuthConfig implements 
ServerAuthConfig {
 
     @Override
     public String getAuthContextID(final MessageInfo messageInfo) throws 
IllegalArgumentException {
-        return null;
+        return appContext; // not sure what's the difference with 
getAppContext()
     }
 
     @Override
diff --git 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/servlet/TomEESecurityServletContainerInitializer.java
 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/servlet/TomEESecurityServletContainerInitializer.java
index 704ee51..10e7ac0 100644
--- 
a/tomee/tomee-security/src/main/java/org/apache/tomee/security/servlet/TomEESecurityServletContainerInitializer.java
+++ 
b/tomee/tomee-security/src/main/java/org/apache/tomee/security/servlet/TomEESecurityServletContainerInitializer.java
@@ -24,11 +24,18 @@ import javax.enterprise.inject.spi.CDI;
 import javax.security.auth.message.config.AuthConfigFactory;
 import javax.servlet.ServletContainerInitializer;
 import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Set;
 
-public class TomEESecurityServletContainerInitializer implements 
ServletContainerInitializer {
+public class TomEESecurityServletContainerInitializer implements 
ServletContainerInitializer, ServletContextListener {
+
+    public static final String CONTEXT_REGISTRATION_ID = 
"org.apache.tomee.security.message.registrationId";
+
     @Override
     public void onStartup(final Set<Class<?>> c, final ServletContext ctx) 
throws ServletException {
 
@@ -49,15 +56,35 @@ public class TomEESecurityServletContainerInitializer 
implements ServletContaine
         }
 
         if (securityExtension.hasAuthenticationMechanisms()) {
-            AuthConfigFactory.getFactory().registerConfigProvider(
-                new TomEESecurityAuthConfigProvider(new HashMap(), null), // 
todo we can probably do better
-                "HttpServlet",                                              // 
from AuthenticatorBase.java:1245
-                    ctx.getVirtualServerName() + " " + ctx.getContextPath(),   
 // from AuthenticatorBase.java:1178
-                "TomEE Security JSR-375");
+            final String registrationId = AccessController.doPrivileged(new 
PrivilegedAction<String>() {
+                public String run() {
+                    return 
AuthConfigFactory.getFactory().registerConfigProvider(
+                        new TomEESecurityAuthConfigProvider(new HashMap(), 
null), // todo we can probably do better
+                        "HttpServlet",                                         
     // from AuthenticatorBase.java:1245
+                        ctx.getVirtualServerName() + " " + 
ctx.getContextPath(),    // from AuthenticatorBase.java:1178
+                        "TomEE Security JSR-375");
+                }
+            });
+
+            if (registrationId != null) {
+                ctx.setAttribute(CONTEXT_REGISTRATION_ID, registrationId);
+            }
         }
     }
 
     private BeanManager getBeanManager() throws IllegalStateException {
         return CDI.current().getBeanManager();
     }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent sce) {
+        String registrationId = (String) 
sce.getServletContext().getAttribute(CONTEXT_REGISTRATION_ID);
+        if (registrationId != null && registrationId.length() > 0) {
+            AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    return 
AuthConfigFactory.getFactory().removeRegistration(registrationId);
+                }
+            });
+        }
+    }
 }
diff --git 
a/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/JaccPermissionServletTest.java
 
b/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/JaccPermissionServletTest.java
new file mode 100644
index 0000000..a051f64
--- /dev/null
+++ 
b/tomee/tomee-security/src/test/java/org/apache/tomee/security/servlet/JaccPermissionServletTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.security.servlet;
+
+import org.apache.tomee.security.AbstractTomEESecurityTest;
+import org.apache.tomee.security.cdi.TomcatUserIdentityStoreDefinition;
+import org.apache.tomee.security.client.BasicAuthFilter;
+import org.junit.Test;
+
+import javax.inject.Inject;
+import javax.security.enterprise.SecurityContext;
+import 
javax.security.enterprise.authentication.mechanism.http.BasicAuthenticationMechanismDefinition;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.HttpConstraint;
+import javax.servlet.annotation.HttpMethodConstraint;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class JaccPermissionServletTest extends AbstractTomEESecurityTest {
+
+    @Test
+    public void authenticate() throws Exception {
+        final String servlet = getAppUrl() + "/servlet2";
+        {
+            final String username = "tom";
+            final Response response = ClientBuilder.newBuilder().register(new 
BasicAuthFilter(username, "secret1")).build()
+                                                   .target(servlet)
+                                                   .request()
+                                                   .get();
+            assertEquals(200, response.getStatus());
+            final String responsePayload = response.readEntity(String.class);
+            System.out.println(responsePayload);
+
+            final StringBuilder sb = new StringBuilder(100);
+            sb.append("context username: ").append(username).append("\n");
+            sb.append("has GET access to /protectedServlet: 
true").append("\n");
+            sb.append("has POST access to /protectedServlet: true");
+
+            assertTrue(responsePayload.contains(sb.toString()));
+        }
+        {
+            final String username = "bob";
+            final Response response = ClientBuilder.newBuilder().register(new 
BasicAuthFilter(username, "secret3")).build()
+                                                   .target(servlet)
+                                                   .request()
+                                                   .get();
+            assertEquals(200, response.getStatus());
+            final String responsePayload = response.readEntity(String.class);
+            System.out.println(responsePayload);
+
+            final StringBuilder sb = new StringBuilder(100);
+            sb.append("context username: ").append(username).append("\n");
+            sb.append("has GET access to /protectedServlet: 
true").append("\n");
+            sb.append("has POST access to /protectedServlet: false");
+
+            assertTrue(responsePayload.contains(sb.toString()));
+        }
+    }
+
+    @WebServlet("/protectedServlet")
+    @ServletSecurity(value = @HttpConstraint(rolesAllowed = "Manager"),
+                     httpMethodConstraints = { @HttpMethodConstraint("GET") })
+    @TomcatUserIdentityStoreDefinition
+    @BasicAuthenticationMechanismDefinition
+    public static class ProtectedServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public void doGet(HttpServletRequest request, HttpServletResponse 
response)
+            throws ServletException, IOException {
+
+            response.getWriter().write("This is a servlet \n");
+
+        }
+
+        @Override
+        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+            throws ServletException, IOException {
+            super.doPost(req, resp);
+        }
+
+    }
+
+    @WebServlet("/servlet2")
+    @TomcatUserIdentityStoreDefinition
+    @BasicAuthenticationMechanismDefinition
+    public static class Servlet2 extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+
+        @Inject
+        private SecurityContext securityContext;
+
+        @Override
+        public void doGet(HttpServletRequest request, HttpServletResponse 
response)
+            throws ServletException, IOException {
+
+            response.getWriter().write("This is a servlet \n");
+
+            String contextName = null;
+            if (securityContext.getCallerPrincipal() != null) {
+                contextName = securityContext.getCallerPrincipal().getName();
+            }
+
+            response.getWriter().write("context username: " + contextName + 
"\n");
+
+            response.getWriter().println("has GET access to /protectedServlet: 
"
+                                         + 
securityContext.hasAccessToWebResource("/protectedServlet", "GET"));
+
+            response.getWriter().println("has POST access to 
/protectedServlet: "
+                                         + 
securityContext.hasAccessToWebResource("/protectedServlet", "POST"));
+
+        }
+
+    }
+
+}
diff --git a/tomee/tomee-security/src/test/resources/conf/tomcat-users.xml 
b/tomee/tomee-security/src/test/resources/conf/tomcat-users.xml
index d7de203..868e874 100644
--- a/tomee/tomee-security/src/test/resources/conf/tomcat-users.xml
+++ b/tomee/tomee-security/src/test/resources/conf/tomcat-users.xml
@@ -17,4 +17,8 @@
 <tomcat-users>
   <user name="tomcat" password="tomcat" roles="tomcat"/>
   <user name="user" password="user" roles="user"/>
+
+  <user name="tom" password="secret1" roles="Administrator,Manager"/>
+  <user name="emma" password="secret2" roles="Administrator,Employee"/>
+  <user name="bob" password="secret3" roles="Administrator"/>
 </tomcat-users>

Reply via email to