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

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 5e1bf35fa4f97204d8007686191688d5ba6f9c08
Author: Alex Heneveld <[email protected]>
AuthorDate: Mon Jan 7 17:14:55 2019 +0000

    working filter, sharing sessions
    
    lots of tidies needed but minimal confirmation here that we can share auth 
across servlets by discovering each other's sessions
---
 .../brooklyn/launcher/BrooklynWebServer.java       |  43 +---
 .../filter/BrooklynSecurityProviderFilter.java     | 254 ---------------------
 .../BrooklynSecurityProviderFilterHelper.java      | 218 ++++++++++++++++++
 .../BrooklynSecurityProviderFilterJavax.java       |  88 +++++++
 .../BrooklynSecurityProviderFilterJersey.java      |  71 ++++++
 .../provider/DelegatingSecurityProvider.java       |   2 +-
 .../security/provider/OauthSecurityProvider.java   | 204 +++++++----------
 .../rest/security/provider/SecurityProvider.java   |  24 +-
 .../rest/util/ManagementContextProvider.java       |  27 ++-
 .../main/resources/OSGI-INF/blueprint/service.xml  |   6 +-
 .../rest/filter/EntitlementContextFilterTest.java  |   6 +-
 .../rest/testing/BrooklynRestResourceTest.java     |   1 -
 .../org/apache/brooklyn/rest/RestApiSetup.java     |  17 --
 .../filter/BrooklynPropertiesSecurityFilter.java   | 179 ---------------
 .../apache/brooklyn/rest/filter/MyOauthFilter.java | 244 --------------------
 .../brooklyn/rest/BrooklynRestApiLauncher.java     |  19 +-
 16 files changed, 521 insertions(+), 882 deletions(-)

diff --git 
a/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java 
b/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
index ad50454..7e6a0bb 100644
--- a/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
+++ b/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynWebServer.java
@@ -37,7 +37,6 @@ import java.util.List;
 import java.util.Map;
 
 import javax.annotation.Nullable;
-import javax.security.auth.spi.LoginModule;
 
 import org.apache.brooklyn.api.location.PortRange;
 import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -53,10 +52,15 @@ import 
org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocati
 import org.apache.brooklyn.rest.BrooklynWebConfig;
 import org.apache.brooklyn.rest.NopSecurityHandler;
 import org.apache.brooklyn.rest.RestApiSetup;
-import org.apache.brooklyn.rest.filter.*;
-import org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule;
-import 
org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule.RolePrincipal;
-import org.apache.brooklyn.rest.security.jaas.JaasUtils;
+import org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilterJavax;
+import org.apache.brooklyn.rest.filter.CorsImplSupplierFilter;
+import org.apache.brooklyn.rest.filter.CsrfTokenFilter;
+import org.apache.brooklyn.rest.filter.EntitlementContextFilter;
+import org.apache.brooklyn.rest.filter.HaHotCheckResourceFilter;
+import org.apache.brooklyn.rest.filter.LoggingFilter;
+import org.apache.brooklyn.rest.filter.NoCacheFilter;
+import org.apache.brooklyn.rest.filter.RequestTaggingFilter;
+import org.apache.brooklyn.rest.filter.RequestTaggingRsFilter;
 import org.apache.brooklyn.rest.util.ManagementContextProvider;
 import org.apache.brooklyn.rest.util.ShutdownHandlerProvider;
 import org.apache.brooklyn.util.collections.MutableMap;
@@ -81,7 +85,6 @@ import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.time.Time;
 import org.apache.brooklyn.util.web.ContextHandlerCollectionHotSwappable;
 import org.eclipse.jetty.http.HttpVersion;
-import org.eclipse.jetty.jaas.JAASLoginService;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.HttpConfiguration;
 import org.eclipse.jetty.server.HttpConnectionFactory;
@@ -193,14 +196,6 @@ public class BrooklynWebServer {
 
     private File webappTempDir;
     
-    /**
-     * @deprecated since 0.9.0, use {@link #consoleSecurity} to disable 
security or
-     * register an alternative JAAS {@link LoginModule}.
-     * {@link BrooklynLoginModule} used by default.
-     */
-    @Deprecated
-    private 
Class<org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilter> 
securityFilterClazz;
-    
     @SetFromFlag
     private boolean skipSecurity = false;
 
@@ -223,7 +218,6 @@ public class BrooklynWebServer {
             log.warn("Ignoring unknown flags " + leftovers);
         
         webappTempDir = 
BrooklynServerPaths.getBrooklynWebTmpDir(managementContext);
-        JaasUtils.init(managementContext);
     }
 
     public BrooklynWebServer(ManagementContext managementContext, int port) {
@@ -234,12 +228,6 @@ public class BrooklynWebServer {
         this(MutableMap.of("port", port, "war", warUrl), managementContext);
     }
 
-    /** @deprecated since 0.9.0, use {@link #skipSecurity} or {@link 
BrooklynLoginModule} */
-    @Deprecated
-    public void 
setSecurityFilter(Class<org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilter>
 filterClazz) {
-        this.securityFilterClazz = filterClazz;
-    }
-
     public BrooklynWebServer skipSecurity() {
         return skipSecurity(true);
     }
@@ -390,13 +378,6 @@ public class BrooklynWebServer {
 
         server = new Server(threadPool);
 
-        // Can be moved to jetty-web.xml inside wars or a global jetty.xml.
-        JAASLoginService loginService = new JAASLoginService();
-        loginService.setName("webconsole");
-        loginService.setLoginModuleName("webconsole");
-        loginService.setRoleClassNames(new String[] 
{RolePrincipal.class.getName()});
-        server.addBean(loginService);
-
         final ServerConnector connector;
 
         if (getHttpsEnabled()) {
@@ -493,12 +474,8 @@ public class BrooklynWebServer {
                 providersListBuilder.build().toArray());
         RestApiSetup.installServletFilters(context,
                 RequestTaggingFilter.class,
+                BrooklynSecurityProviderFilterJavax.class,
                 LoggingFilter.class);
-        RestApiSetup.installOauthServletFilters(context,
-                MyOauthFilter.class);
-        if (securityFilterClazz != null) {
-            RestApiSetup.installServletFilters(context, securityFilterClazz);
-        }
         return context;
     }
 
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilter.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilter.java
deleted file mode 100644
index 4f960f6..0000000
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilter.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.rest.filter;
-
-import java.io.IOException;
-import java.security.Principal;
-import java.util.function.Function;
-
-import javax.annotation.Priority;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.ext.ContextResolver;
-import javax.ws.rs.ext.Provider;
-
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.rest.BrooklynWebConfig;
-import org.apache.brooklyn.rest.security.provider.DelegatingSecurityProvider;
-import org.apache.brooklyn.rest.security.provider.SecurityProvider;
-import 
org.apache.brooklyn.rest.security.provider.SecurityProvider.PostAuthenticator;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.http.auth.BasicUserPrincipal;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Provides a filter that performs authentication with the {@link 
SecurityProvider}
- * as configured according to {@link 
BrooklynWebConfig#SECURITY_PROVIDER_CLASSNAME}.
- * 
- * This replaces the JAAS {@link BrooklynLoginModule} because that login 
module requires
- * Basic auth, which is not flexible enough to support redirect-based 
solutions like Oauth. 
- */
-@Provider
-@Priority(100)
-public class BrooklynSecurityProviderFilter implements ContainerRequestFilter {
-
-    /**
-     * The session attribute set for authenticated users; for reference
-     * (but should not be relied up to confirm authentication, as
-     * the providers may impose additional criteria such as timeouts,
-     * or a null user (no login) may be permitted)
-     */
-    public static final String AUTHENTICATED_USER_SESSION_ATTRIBUTE = 
"brooklyn.user";
-
-    private static final Logger log = 
LoggerFactory.getLogger(BrooklynSecurityProviderFilter.class);
-
-    
-    @Context
-    HttpServletRequest webRequest;
-    
-    @Context
-    private ContextResolver<ManagementContext> mgmtC;
-    
-    private ManagementContext mgmt() {
-        return mgmtC.getContext(ManagementContext.class);
-    }
-    
-    public static class SimpleSecurityContext implements SecurityContext {
-        final Principal principal;
-        final Function<String,Boolean> roleChecker;
-        final boolean secure;
-        final String authScheme;
-        
-        public SimpleSecurityContext(String username, Function<String, 
Boolean> roleChecker, boolean secure, String authScheme) {
-            this.principal = new BasicUserPrincipal(username);
-            this.roleChecker = roleChecker;
-            this.secure = secure;
-            this.authScheme = authScheme;
-        }
-
-        @Override
-        public Principal getUserPrincipal() {
-            return principal;
-        }
-
-        @Override
-        public boolean isUserInRole(String role) {
-            return roleChecker.apply(role);
-        }
-
-        @Override
-        public boolean isSecure() {
-            return secure;
-        }
-
-        @Override
-        public String getAuthenticationScheme() {
-            return authScheme;
-        }
-    }
-    
-    @Override
-    public void filter(ContainerRequestContext requestContext) throws 
IOException {
-        SecurityProvider provider = getProvider();
-        HttpSession session = webRequest.getSession(false);
-        
-        if (provider.isAuthenticated(session)) {
-            return;
-        }
-        
-        String user = null, pass = null;
-        if (provider.requiresUserPass()) {
-            String authorization = webRequest.getHeader("Authorization");
-            if (authorization != null) {
-                String userpass = new 
String(Base64.decodeBase64(authorization.substring(6)));
-                int idxColon = userpass.indexOf(":");
-                if (idxColon >= 0) {
-                    user = userpass.substring(0, idxColon);
-                    pass = userpass.substring(idxColon + 1);
-                } else {
-                    abort(requestContext, "Invalid authorization string");
-                    return;
-                }
-            } else {
-                abort(requestContext, "Authorization required");
-                return;
-            }
-        }
-        
-        if (session==null) {
-            // only create the session if an auth string is supplied
-            session = webRequest.getSession(true);
-        }
-        
session.setAttribute(BrooklynWebConfig.REMOTE_ADDRESS_SESSION_ATTRIBUTE, 
webRequest.getRemoteAddr());
-        
-        if (provider.authenticate(session, user, pass)) {
-            if (provider instanceof PostAuthenticator) {
-                ((PostAuthenticator)provider).postAuthenticate(requestContext);
-            }
-            if (user != null) {
-                session.setAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE, 
user);
-                if 
(requestContext.getSecurityContext().getUserPrincipal()==null) {
-                    requestContext.setSecurityContext(new 
SimpleSecurityContext(user, (role) -> false, 
-                        webRequest.isSecure(), SecurityContext.BASIC_AUTH));
-                }
-            }
-            return;
-        }
-    
-        abort(requestContext, "Authentication failed");
-        return;
-    }
-    
-    private void abort(ContainerRequestContext requestContext, String message) 
{
-        requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
-            .type(MediaType.TEXT_PLAIN)
-            .entity(message)
-            .header("WWW-Authenticate", "Basic realm=\"brooklyn\"")
-            .build());
-    }
-
-    protected SecurityProvider getProvider() {
-        // we don't cache here (could, it might be faster) but the delegate 
does use a cache
-        return new DelegatingSecurityProvider(mgmt());
-    }
-
-//    private static ThreadLocal<String> originalRequest = new 
ThreadLocal<String>();
-//
-//    @Override
-//    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
-//        HttpServletRequest httpRequest = (HttpServletRequest) request;
-//        HttpServletResponse httpResponse = (HttpServletResponse) response;
-//        String uri = httpRequest.getRequestURI();
-//
-//        if (provider == null) {
-//            log.warn("No security provider available: disallowing web access 
to brooklyn");
-//            
httpResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
-//            return;
-//        }
-//
-//        if (originalRequest.get() != null) {
-//            // clear the entitlement context before setting to avoid warnings
-//            Entitlements.clearEntitlementContext();
-//        } else {
-//            originalRequest.set(uri);
-//        }
-//
-//        boolean authenticated = 
provider.isAuthenticated(httpRequest.getSession());
-//        if ("/logout".equals(uri) || "/v1/logout".equals(uri)) {
-//            httpResponse.setHeader("WWW-Authenticate", "Basic 
realm=\"brooklyn\"");
-//            if (authenticated && 
httpRequest.getSession().getAttributeNames().hasMoreElements()) {
-//                logout(httpRequest);
-//                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-//            } else {
-//                RequestDispatcher dispatcher = 
httpRequest.getRequestDispatcher("/");
-//                log.debug("Not authenticated, forwarding request for {} to 
{}", uri, dispatcher);
-//                dispatcher.forward(httpRequest, httpResponse);
-//            }
-//            return;
-//        }
-//
-//        if (!(httpRequest.getSession().getAttributeNames().hasMoreElements() 
&& provider.isAuthenticated(httpRequest.getSession())) ||
-//                "/logout".equals(originalRequest.get())) {
-//            authenticated = authenticate(httpRequest);
-//        }
-//
-//        if (!authenticated) {
-//            httpResponse.setHeader("WWW-Authenticate", "Basic 
realm=\"brooklyn\"");
-//            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-//            return;
-//        }
-//
-//        // Note that the attribute AUTHENTICATED_USER_SESSION_ATTRIBUTE is 
only set in the call to authenticate(httpRequest),
-//        // so must not try to get the user until that is done.
-//        String uid = RequestTaggingFilter.getTag();
-//        String user = 
Strings.toString(httpRequest.getSession().getAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE));
-//        try {
-//            WebEntitlementContext entitlementContext = new 
WebEntitlementContext(user, httpRequest.getRemoteAddr(), uri, uid);
-//            Entitlements.setEntitlementContext(entitlementContext);
-//
-//            chain.doFilter(request, response);
-//        } catch (Throwable e) {
-//            if (!response.isCommitted()) {
-//                
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-//            }
-//        } finally {
-//            originalRequest.remove();
-//            Entitlements.clearEntitlementContext();
-//        }
-//    }
-//
-//    protected boolean authenticate(HttpServletRequest request) {
-//
-//    protected void logout(HttpServletRequest request) {
-//        log.info("REST logging {} out of session {}",
-//                
request.getSession().getAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE), 
request.getSession().getId());
-//        provider.logout(request.getSession());
-//        
request.getSession().removeAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE);
-//        
request.getSession().removeAttribute(BrooklynWebConfig.REMOTE_ADDRESS_SESSION_ATTRIBUTE);
-//        request.getSession().invalidate();
-//    }
-
-}
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterHelper.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterHelper.java
new file mode 100644
index 0000000..47180c9
--- /dev/null
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterHelper.java
@@ -0,0 +1,218 @@
+/*
+ * 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.brooklyn.rest.filter;
+
+import java.util.Set;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.rest.BrooklynWebConfig;
+import org.apache.brooklyn.rest.security.provider.DelegatingSecurityProvider;
+import org.apache.brooklyn.rest.security.provider.SecurityProvider;
+import 
org.apache.brooklyn.rest.security.provider.SecurityProvider.SecurityProviderDeniedAuthentication;
+import org.apache.brooklyn.util.collections.MutableSet;
+import org.apache.commons.codec.binary.Base64;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides a filter that performs authentication with the {@link 
SecurityProvider}
+ * as configured according to {@link 
BrooklynWebConfig#SECURITY_PROVIDER_CLASSNAME}.
+ * 
+ * This replaces the JAAS "BrooklynLoginModule" because that login module 
requires
+ * Basic auth, which is not flexible enough to support redirect-based 
solutions like Oauth.
+ * 
+ * Unfortunately we seem to need two filters, the Jersey filter for the REST 
bundle,
+ * and the Javax filter for the static content bundles (in 
brooklyn-ui/ui-modules).
+ * (We could set up our own Jersey servlet or blueprint for the static content 
bundles
+ * to re-use the Jersey filter, but that seems like overkill; and surely 
there's an easy
+ * way to set the Javax filter to run for the REST bundle inside 
blueprint.xml, but a
+ * few early attempts didn't succeed and the approach of having two filters 
seems easiest
+ * (especially as they share code for the significant parts, in this class).
+ * 
+ * This does give us the opportunity to differentiate the redirect, so that
+ * jersey (REST) requests don't redirect to the auth site, as the redirect 
requires human intervention.
+ */
+public class BrooklynSecurityProviderFilterHelper {
+
+    public interface Responder {
+        void error(String message, boolean requiresBasicAuth) throws 
SecurityProviderDeniedAuthentication;
+    }
+    
+    /**
+     * The session attribute set for authenticated users; for reference
+     * (but should not be relied up to confirm authentication, as
+     * the providers may impose additional criteria such as timeouts,
+     * or a null user (no login) may be permitted)
+     */
+    public static final String AUTHENTICATED_USER_SESSION_ATTRIBUTE = 
"brooklyn.user";
+
+    // TODO ugly, using a static, but it shares across bundles and all have 
different instances, so this is reasonable
+    public static Set<SessionHandler> SESSION_MANAGER_CACHE = MutableSet.of();
+    
+    private static final Logger log = 
LoggerFactory.getLogger(BrooklynSecurityProviderFilterHelper.class);
+    
+    /* check all contexts for sessions; surprisingly hard to configure session 
management for karaf/pax web container.
+     * they _really_ want each servlet to have their own sessions. how you're 
meant to do oauth for multiple servlets i don't know! */
+    public HttpSession getSession(HttpServletRequest webRequest, 
ManagementContext mgmt, boolean create) {
+        String requestedSessionId = webRequest.getRequestedSessionId();
+        
+        log.info("SESSION for "+ webRequest.getRequestURI()+", wants session 
"+requestedSessionId);
+        
+        if (webRequest instanceof Request) {
+            SessionHandler sm = ((Request)webRequest).getSessionHandler();
+            boolean added = SESSION_MANAGER_CACHE.add( sm );
+            log.info("SESSION MANAGER found for 
"+webRequest.getRequestURI()+": "+sm+" ("+added+")");
+        } else {
+            log.info("SESSION MANAGER NOT found for 
"+webRequest.getRequestURI()+" - "+webRequest);
+        }
+        
+        if (requestedSessionId!=null) {
+            for (SessionHandler m: SESSION_MANAGER_CACHE) {
+                HttpSession s = m.getHttpSession(requestedSessionId);
+                if (s!=null) {
+                    log.info("SESSION found for 
"+webRequest.getRequestURI()+": "+s+"; "+m.isValid(s));
+                    return s;
+                }
+            }
+        }
+        
+        if (create) {
+            HttpSession session = webRequest.getSession(true);
+            log.info("SESSION creating for "+webRequest.getRequestURI()+": 
"+session);
+            return session;
+        }
+        
+        return null;
+        
+//        HttpSession session = webRequest.getSession(false);
+//        if (session!=null) return session;
+//        
+//        // go through all the known session managers
+//        
+//        
+//        
webRequest.getServletContext().getServlets().nextElement().getServletConfig().getServletContext().getser
+//        BundleContext ctx = (BundleContext) 
webRequest.getServletContext().getAttribute(
+//            //WebContainerConstants.BUNDLE_CONTEXT_ATTRIBUTE
+//            "osgi-bundlecontext");
+//        log.info("TEST context "+ctx);
+//        if (ctx!=null) {
+//            log.info("TEST server "+ctx.getServiceReference( 
"org.ops4j.pax.web.service.WebContainer" ));
+//        }
+//        ctx.getServiceReference( "org.ops4j.pax.web.service.WebContainer" );
+//        
+//        ctx = 
FrameworkUtil.getBundle(BrooklynSecurityProviderFilterHelper.class).getBundleContext();
+//        
+//        
+//        log.info("TEST context2 "+ctx);
+//        if (ctx!=null) {
+//            log.info("TEST server2 "+ctx.getServiceReference( 
"org.ops4j.pax.web.service.WebContainer" ));
+//        }
+//        
+////        String id = webRequest.getRequestedSessionId();
+////        webRequest.getServletContext().gethan
+//////        for (Cookie c: webRequest.getCookies()) {
+//////            if ("JSESSIONID".equals(c.getName())) {
+//////                c.getValue()
+//////            }
+//////        }
+////        HttpSession session = getLocalSession(id); 
+////        if (session == null) { 
+////            for (SessionHandler manager: 
getSessionIdManager().getSessionHandlers()) { 
+////                if (manager.equals(this) || !(manager instanceof 
CustomSessionHandler)) { 
+////                    continue; 
+////                } 
+////                session = 
((CustomSessionHandler)manager).getLocalSession(id); 
+////                if (session != null) { 
+////                    break; 
+////                } 
+////            } // should we duplicate sessions in each context? // will we 
end up with inconsistent sessions? /* if (externalSession != null) { try { 
getSessionCache().put(id, externalSession); } catch (Exception e) { 
LOG.warn("Unable to save session to local cache."); } } */ }
+////        }
+////        return session;
+//        return null;
+    }
+    
+    public void run(HttpServletRequest webRequest, ManagementContext mgmt) 
throws SecurityProviderDeniedAuthentication {
+        log.info("SEC PROV for "+webRequest.getRequestURI());
+        
+        SecurityProvider provider = getProvider(mgmt);
+        HttpSession session = getSession(webRequest, mgmt, false);
+        
+        if (provider.isAuthenticated(session)) {
+            return;
+        }
+        
+        String user = null, pass = null;
+        if (provider.requiresUserPass()) {
+            String authorization = webRequest.getHeader("Authorization");
+            if (authorization != null) {
+                String userpass = new 
String(Base64.decodeBase64(authorization.substring(6)));
+                int idxColon = userpass.indexOf(":");
+                if (idxColon >= 0) {
+                    user = userpass.substring(0, idxColon);
+                    pass = userpass.substring(idxColon + 1);
+                } else {
+                    throw abort("Invalid authorization string", 
provider.requiresUserPass());
+                }
+            } else {
+                throw abort("Authorization required", 
provider.requiresUserPass());
+            }
+        }
+        
+        if (session==null) {
+            // only create the session if an auth string is supplied
+            session = getSession(webRequest, mgmt, true);
+        }
+        
session.setAttribute(BrooklynWebConfig.REMOTE_ADDRESS_SESSION_ATTRIBUTE, 
webRequest.getRemoteAddr());
+        
+        if (provider.authenticate(session, user, pass)) {
+            if (user != null) {
+                session.setAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE, 
user);
+            }
+            return;
+        }
+    
+        throw abort("Authentication failed", provider.requiresUserPass());
+    }
+    
+    private SecurityProviderDeniedAuthentication abort(String msg, boolean 
requiresUserPass) throws SecurityProviderDeniedAuthentication {
+        ResponseBuilder response = Response.status(Status.UNAUTHORIZED);
+        if (requiresUserPass) {
+            response.header(HttpHeader.WWW_AUTHENTICATE.asString(), "BASIC 
realm=\"brooklyn\"");
+        }
+        response.header(HttpHeader.CONTENT_TYPE.asString(), 
MediaType.TEXT_PLAIN);
+        response.entity(msg);
+        throw new SecurityProviderDeniedAuthentication(response.build());
+    }
+
+    protected SecurityProvider getProvider(ManagementContext mgmt) {
+        // we don't cache here (could, it might be faster) but the delegate 
does use a cache
+        return new DelegatingSecurityProvider(mgmt);
+    }
+
+}
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJavax.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJavax.java
new file mode 100644
index 0000000..5751872
--- /dev/null
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJavax.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     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.brooklyn.rest.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import 
org.apache.brooklyn.rest.security.provider.SecurityProvider.SecurityProviderDeniedAuthentication;
+import org.apache.brooklyn.rest.util.ManagementContextProvider;
+import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/** See {@link BrooklynSecurityProviderFilterHelper} */
+public class BrooklynSecurityProviderFilterJavax implements Filter {
+    
+    @SuppressWarnings("unused")
+    private static final Logger log = 
LoggerFactory.getLogger(BrooklynSecurityProviderFilterJavax.class);
+    
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        // no init needed
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain)
+            throws IOException, ServletException {
+
+        try {
+            ManagementContext mgmt = new 
ManagementContextProvider(request.getServletContext()).getManagementContext();
+            Preconditions.checkNotNull(mgmt, "Brooklyn management context not 
available; cannot authenticate");
+            new 
BrooklynSecurityProviderFilterHelper().run((HttpServletRequest)request, mgmt);
+
+            chain.doFilter(request, response);
+
+        } catch (SecurityProviderDeniedAuthentication e) {
+            HttpServletResponse rout = ((HttpServletResponse)response);
+            Response rin = e.getResponse();
+            if (rin==null) rin = Response.status(Status.UNAUTHORIZED).build();
+     
+            rout.setStatus(rin.getStatus());
+            
+            // TODO does content type need to be set explicitly?
+            rin.getHeaders().forEach((k,v) -> v.forEach(v2 -> 
rout.addHeader(k, Strings.toString(v2))));
+            
+            Object body = rin.getEntity();
+            if (body!=null) {
+                response.getWriter().write(Strings.toString(body));
+                response.getWriter().flush();
+            }
+        }
+    }
+
+    @Override
+    public void destroy() {
+        // no clean-up needed
+    }
+    
+}
\ No newline at end of file
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java
new file mode 100644
index 0000000..ff1a1d3
--- /dev/null
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/filter/BrooklynSecurityProviderFilterJersey.java
@@ -0,0 +1,71 @@
+/*
+ * 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.brooklyn.rest.filter;
+
+import java.io.IOException;
+
+import javax.annotation.Priority;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import 
org.apache.brooklyn.rest.security.provider.SecurityProvider.SecurityProviderDeniedAuthentication;
+import org.eclipse.jetty.http.HttpHeader;
+
+/** See {@link BrooklynSecurityProviderFilterHelper} */
+@Provider
+@Priority(100)
+public class BrooklynSecurityProviderFilterJersey implements 
ContainerRequestFilter {
+    
+    @Context
+    HttpServletRequest webRequest;
+
+    @Context
+    private ContextResolver<ManagementContext> mgmtC;
+
+    @Override
+    public void filter(ContainerRequestContext requestContext) throws 
IOException {
+        try {
+            new BrooklynSecurityProviderFilterHelper().run(webRequest, 
mgmtC.getContext(ManagementContext.class));
+            
+        } catch (SecurityProviderDeniedAuthentication e) {
+            Response rin = e.getResponse();
+            if (rin==null) rin = Response.status(Status.UNAUTHORIZED).build();
+            
+            if (rin.getStatus()==Status.FOUND.getStatusCode()) {
+                String location = 
rin.getHeaderString(HttpHeader.LOCATION.asString());
+                if (location!=null) {
+                    rin = 
Response.status(Status.UNAUTHORIZED).entity("Authentication is required at 
"+location).
+                        header(HttpHeader.LOCATION.asString(), 
location).build();
+                } else {
+                    rin = 
Response.status(Status.UNAUTHORIZED).entity("Authentication is 
required").build();
+                }
+            }
+            requestContext.abortWith(rin);
+        }
+    }
+
+}
+
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java
index 664c5c1..65567c4 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/DelegatingSecurityProvider.java
@@ -195,7 +195,7 @@ public class DelegatingSecurityProvider implements 
SecurityProvider {
     }
 
     @Override
-    public boolean authenticate(HttpSession session, String user, String 
password) {
+    public boolean authenticate(HttpSession session, String user, String 
password) throws SecurityProviderDeniedAuthentication {
         boolean authenticated = getDelegate().authenticate(session, user, 
password);
         if (authenticated) {
             session.setAttribute(getModificationCountKey(), modCount.get());
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/OauthSecurityProvider.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/OauthSecurityProvider.java
index b3975f1..a3bbcf1 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/OauthSecurityProvider.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/OauthSecurityProvider.java
@@ -27,12 +27,14 @@ import java.util.Optional;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpSession;
-import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
-import 
org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilter.SimpleSecurityContext;
+import org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilterHelper;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.text.Identifiers;
 import org.apache.brooklyn.util.text.Strings;
+import org.apache.brooklyn.util.time.Duration;
 import org.apache.brooklyn.util.yaml.Yamls;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
@@ -46,83 +48,59 @@ import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.http.util.EntityUtils;
+import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.server.HttpChannel;
 import org.eclipse.jetty.server.HttpConnection;
 import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.Response;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /** Configurable OAuth redirect security provider
  * 
  *  Redirects all inbound requests to an oath web server unless a session 
token is specified. */
-public class OauthSecurityProvider implements SecurityProvider, 
SecurityProvider.PostAuthenticator {
+public class OauthSecurityProvider implements SecurityProvider {
 
     public static final Logger LOG = 
LoggerFactory.getLogger(OauthSecurityProvider.class);
 
-    // TODO replace with LOG
-    private static final Logger logger = 
LoggerFactory.getLogger(OauthSecurityProvider.class);
-    private static final String SESSION_KEY_ACCESS_TOKEN = "access_token";
-    private static final String SESSION_KEY_CODE = "code";
-    private static final String FAKE_TOKEN_FOR_DEBUG = "fake_token";
-//    public static final String PARAM_URI_TOKEN_INFO = "uriTokenInfo";
-//    public static final String PARAM_URI_GETTOKEN = "uriGetToken";
-//    public static final String PARAM_URI_LOGIN_REDIRECT = "uriLoginRedirect";
-//    public static final String PARAM_CLIENT_ID = "clientId";
-//    public static final String PARAM_CLIENT_SECRET = "clientSecret";
-//    public static final String PARAM_CALLBACK_URI = "callbackUri";
-//    public static final String PARAM_AUDIENCE = "audience";
-
+    private static final String OAUTH_ACCESS_TOKEN_SESSION_KEY = 
"org.apache.brooklyn.security.oauth.access_token";
+    private static final String OAUTH_ACCESS_TOKEN_EXPIRY_UTC_KEY = 
"org.apache.brooklyn.security.oauth.access_token_expiry_utc";
+    
+    private static final String OAUTH_AUTH_CODE_PARAMETER_FROM_USER = "code";
+    private static final String OAUTH_AUTH_CODE_PARAMETER_FOR_SERVER = 
OAUTH_AUTH_CODE_PARAMETER_FROM_USER;
+    
+    // TODO parameterise
+    
     // tempting to use getJettyRequest().getRequestURL().toString();
     // but some oauth providers require this to be declared
     private String callbackUri = "http://localhost.io:8081/";;
+    private String accessTokenResponseKey = "access_token";
+    private String audience = "audience";
+    private Duration validity = Duration.hours(1);
     
+    // google test data
     private String uriGetToken = "https://accounts.google.com/o/oauth2/token";;
     private String uriAuthorize = "https://accounts.google.com/o/oauth2/auth";;
     private String uriTokenInfo = 
"https://www.googleapis.com/oauth2/v1/tokeninfo";;
+    private String clientId = 
"789182012565-burd24h3bc0im74g2qemi7lnihvfqd02.apps.googleusercontent.com";
+    private String clientSecret = "X00v-LfU34U4SfsHqPKMWfQl";
     
-    // or github:
+    // github test data
 //    private String uriGetToken = "https://github.com/login/oauth/authorize";;
 //    private String uriAuthorize = "https://github.com/login/oauth/authorize";;
 //    private String uriTokenInfo = 
"https://github.com/login/oauth/access_token";;
-    
-//    private String apiURLBase = "https://api.github.com/";;
-
-//    private String uriTokenRedirect = "/";
-    // google
-    // TODO parameterise
-    private String clientId = 
"789182012565-burd24h3bc0im74g2qemi7lnihvfqd02.apps.googleusercontent.com";
-    private String clientSecret = "X00v-LfU34U4SfsHqPKMWfQl";
-    // github
 //    private String clientId = "7f76b9970d8ac15b30b0";
 //    private String clientSecret = "9e15f8dd651f0b1896a3a582f17fa82f049fc910";
     
-    // TODO
-    private String audience = "audience";
-
-//    private static final String OAUTH2_TOKEN = 
"org.apache.activemq.jaas.oauth2.token";
-//    private static final String OAUTH2_ROLE = 
"org.apache.activemq.jaas.oauth2.role";
-//    private static final String OAUTH2_URL = 
"org.apache.activemq.jaas.oauth2.oauth2url";
-//    private Set<Principal> principals = new HashSet<>();
-//    private Subject subject;
-//    private CallbackHandler callbackHandler;
-//    private boolean debug;
-//    private String roleName = "webconsole";
-//    private String oauth2URL = uriTokenInfo;
-//    private boolean loginSucceeded;
-//    private String userName;
-//    private boolean commitSuccess;
-    
     @Override
     public boolean isAuthenticated(HttpSession session) {
-        LOG.info("isAuthenticated 1 "+session+" ... "+this);
-        Object token = session.getAttribute(SESSION_KEY_ACCESS_TOKEN);
+        LOG.info("isAuthenticated 1 "+getJettyRequest().getRequestURI()+" 
"+session+" ... "+this);
+        Object token = session.getAttribute(OAUTH_ACCESS_TOKEN_SESSION_KEY);
         // TODO is it valid?
         return token!=null;
     }
 
     @Override
-    public boolean authenticate(HttpSession session, String user, String 
password) {
+    public boolean authenticate(HttpSession session, String user, String 
password) throws SecurityProviderDeniedAuthentication {
         LOG.info("authenticate "+session+" "+user);
         
         if (isAuthenticated(session)) {
@@ -131,18 +109,23 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         
         Request request = getJettyRequest();
         // Redirection from the authenticator server
-        String code = request.getParameter(SESSION_KEY_CODE);
+        String code = 
request.getParameter(OAUTH_AUTH_CODE_PARAMETER_FROM_USER);
         // Getting token, if exists, from the current session
-        String token = (String) 
request.getSession().getAttribute(SESSION_KEY_ACCESS_TOKEN);
+        String token = (String) 
request.getSession().getAttribute(OAUTH_ACCESS_TOKEN_SESSION_KEY);
         
         try {
             if (Strings.isNonBlank(code)) {
-                return getToken();
-            } else if (Strings.isEmpty(token)) {
-                return redirectLogin();
+                return retrieveTokenForAuthCodeFromOauthServer(session, code);
+            } else if (Strings.isNonBlank(token)) {
+                // they have a token but no auth code and not or no longer 
authenticated; 
+                // we need to check that the token is still valid
+                return validateTokenAgainstOauthServer(token);
             } else {
-                return validateToken(token);
+                // no token or code; the user needs to log in
+                return redirectUserToOauthLoginUi();
             }
+        } catch (SecurityProviderDeniedAuthentication e) {
+            throw e;
         } catch (Exception e) {
             LOG.warn("Error performing OAuth: "+e, e);
             throw Exceptions.propagate(e);
@@ -152,7 +135,8 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
     @Override
     public boolean logout(HttpSession session) {
         LOG.info("logout");
-        session.removeAttribute(SESSION_KEY_ACCESS_TOKEN);
+        session.removeAttribute(OAUTH_ACCESS_TOKEN_SESSION_KEY);
+        session.removeAttribute(OAUTH_ACCESS_TOKEN_EXPIRY_UTC_KEY);
         return true;
     }
     
@@ -161,13 +145,10 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         return false;
     }
 
-    private boolean getToken() throws ClientProtocolException, IOException, 
ServletException {
-        Request request = getJettyRequest();
-        String code = request.getParameter(SESSION_KEY_CODE);
-
+    private boolean retrieveTokenForAuthCodeFromOauthServer(HttpSession 
session, String code) throws ClientProtocolException, IOException, 
ServletException, SecurityProviderDeniedAuthentication {
         // get the access token by post to Google
         HashMap<String, String> params = new HashMap<String, String>();
-        params.put(SESSION_KEY_CODE, code);
+        params.put(OAUTH_AUTH_CODE_PARAMETER_FOR_SERVER, code);
         params.put("client_id", clientId);
         params.put("client_secret", clientSecret);
         params.put("redirect_uri", callbackUri);
@@ -180,18 +161,22 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         // get the access token from json and request info from Google
         try {
             jsonObject = (Map<?,?>) Yamls.parseAll(body).iterator().next();
-            logger.info("Parsed '"+body+"' as "+jsonObject);
+            LOG.info("Parsed '"+body+"' as "+jsonObject);
         } catch (Exception e) {
             Exceptions.propagateIfFatal(e);
-            logger.info("Unable to parse: '"+body+"'");
+            LOG.info("Unable to parse: '"+body+"'");
             // throw new RuntimeException("Unable to parse json " + body);
-            return redirectLogin();
+            return redirectUserToOauthLoginUi();
         }
 
-        // Left token and code in session
-        String accessToken = (String) jsonObject.get(SESSION_KEY_ACCESS_TOKEN);
-        request.getSession().setAttribute(SESSION_KEY_ACCESS_TOKEN, 
accessToken);
-        request.getSession().setAttribute(SESSION_KEY_CODE, code);
+        // TODO validate
+        
+        // Put token in session
+        String accessToken = (String) jsonObject.get(accessTokenResponseKey);
+        session.setAttribute(OAUTH_ACCESS_TOKEN_SESSION_KEY, accessToken);
+        
+        // TODO record code?
+//        request.getSession().setAttribute(SESSION_KEY_CODE, code);
 
         // TODO is it valid?
         LOG.debug("Got token/code "+accessToken+"/"+code+" from "+jsonObject);
@@ -205,46 +190,40 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         //   scope=https://www.googleapis.com/auth/userinfo.email 
https://www.googleapis.com/auth/plus.me, 
         //   token_type=Bearer, 
         //   
id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc5NzhhOTEzNDcyNjFhMjkxYmQ3MWRjYWI0YTQ2NGJlN2QyNzk2NjYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNzg5MTgyMDEyNTY1LWJ1cmQyNGgzYmMwaW03NGcycWVtaTdsbmlodmZxZDAyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNzg5MTgyMDEyNTY1LWJ1cmQyNGgzYmMwaW03NGcycWVtaTdsbmlodmZxZDAyLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTA2MDQyNTE3MjU2MTcxNzYyMTU0IiwiaGQiOiJjbG91ZHNvZnRjb3JwLmNvbSIsImVtYWlsIjoiYWxleC5oZW5ldmVsZEBjbG91ZHN
 [...]
-        // TODO how do we get the user ID back?
+        // TODO get the user's ID : 
https://stackoverflow.com/questions/24442668/google-oauth-api-to-get-users-email-address
+        String user = accessToken;  // wrong, see above
+        
session.setAttribute(BrooklynSecurityProviderFilterHelper.AUTHENTICATED_USER_SESSION_ATTRIBUTE,
 user);
+        
         return true;
     }
-    
-    @Override
-    public void postAuthenticate(ContainerRequestContext requestContext) {
-        Request request = getJettyRequest();
-        String token = (String) 
request.getSession().getAttribute(SESSION_KEY_ACCESS_TOKEN);
-        LOG.info("TOKEN post authed = "+token);
-        String user = token; // TODO not right - see above
-        requestContext.setSecurityContext(new SimpleSecurityContext(user, 
(role) -> false, request.isSecure(), "brooklyn-oauth"));
-    }
-
-    private boolean validateToken(String token) throws 
ClientProtocolException, IOException {
-        // TODO for debug
-        if(token.equals(FAKE_TOKEN_FOR_DEBUG)){
-            return true;
-        }
-        HashMap<String, String> params = new HashMap<String, String>();
-        params.put(SESSION_KEY_ACCESS_TOKEN, token);
-
-        String body = post(uriTokenInfo, params);
-        // System.out.println(body);
-        Map<?,?> jsonObject = null;
-
-        // get the access token from json and request info from Google
-        try {
-            jsonObject = (Map<?,?>) Yamls.parseAll(body).iterator().next();
-            logger.info("Parsed '"+body+"' as "+jsonObject);
-        } catch (Exception e) {
-            Exceptions.propagateIfFatal(e);
-            logger.info("Unable to parse: '"+body+"'");
-            throw new RuntimeException("Unable to parse json " + body, e);
-        }
 
-        // TODO what's this for?
-        if (!clientId.equals(jsonObject.get(audience))) {
-            return redirectLogin();
-        }
-        // if (isTokenExpiredOrNearlySo(...) { ... }
+    private boolean validateTokenAgainstOauthServer(String token) throws 
ClientProtocolException, IOException {
+        // TODO support validation, and run periodically
+        
+//        HashMap<String, String> params = new HashMap<String, String>();
+//        params.put(OAUTH_ACCESS_TOKEN_KEY, token);
+//
+//        String body = post(uriTokenInfo, params);
+//        
+//        Map<?,?> jsonObject = null;
+//        // get the access token from json and request info from Google
+//        try {
+//            jsonObject = (Map<?,?>) Yamls.parseAll(body).iterator().next();
+//            LOG.info("Parsed '"+body+"' as "+jsonObject);
+//        } catch (Exception e) {
+//            Exceptions.propagateIfFatal(e);
+//            LOG.info("Unable to parse: '"+body+"'");
+//            throw new RuntimeException("Unable to parse json " + body, e);
+//        }
+//
+//        if (!clientId.equals(jsonObject.get(audience))) {
+//            LOG.warn("Oauth not meant for this client ("+clientId+"), 
redirecting user to login again: "+jsonObject);
+//            return redirectUserToOauthLoginUi();
+//        }
+//        
+//        // TODO
+//        // if (isTokenExpiredOrNearlySo(...) { ... }
+        
         return true;
     }
 
@@ -286,7 +265,7 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         return body;
     }
 
-    private boolean redirectLogin() throws IOException {
+    private boolean redirectUserToOauthLoginUi() throws IOException, 
SecurityProviderDeniedAuthentication {
         String state=Identifiers.makeRandomId(12); //should be stored in 
session
         StringBuilder oauthUrl = new StringBuilder().append(uriAuthorize)
                 .append("?response_type=").append("code")
@@ -304,17 +283,12 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
         // just for look inside
 //        Collection<String> originalHeaders = response.getHeaderNames();
 
-        Response response = getJettyResponse();
-        response.reset();
+        throw new SecurityProviderDeniedAuthentication(
+            
Response.status(Status.FOUND).header(HttpHeader.LOCATION.asString(), 
oauthUrl.toString()).build());
 //        response.addHeader("Origin", "http://localhost.io:8081";);
 //        response.addHeader("Access-Control-Allow-Origin", "*");
-////        response.addHeader("Access-Control-Request-Method", "GET, POST");
-////        response.addHeader("Access-Control-Request-Headers", "origin, 
x-requested-with");
-        LOG.info("OAUTH url redirect is: "+oauthUrl.toString());
-        
-        response.sendRedirect(oauthUrl.toString());
-
-        return false;
+//        response.addHeader("Access-Control-Request-Method", "GET, POST");
+//        response.addHeader("Access-Control-Request-Headers", "origin, 
x-requested-with");
     }
 
     private Request getJettyRequest() {
@@ -324,10 +298,4 @@ public class OauthSecurityProvider implements 
SecurityProvider, SecurityProvider
                 .orElse(null);
     }
 
-    private Response getJettyResponse() {
-        return Optional.ofNullable(HttpConnection.getCurrentConnection())
-                .map(HttpConnection::getHttpChannel)
-                .map(HttpChannel::getResponse)
-                .orElse(null);
-    }
 }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
index 1a16219..7ceecf0 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/security/provider/SecurityProvider.java
@@ -19,7 +19,7 @@
 package org.apache.brooklyn.rest.security.provider;
 
 import javax.servlet.http.HttpSession;
-import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.core.Response;
 
 /**
  * The SecurityProvider is responsible for doing authentication.
@@ -35,12 +35,24 @@ public interface SecurityProvider {
      * (ie for things like oauth, the framework should not require basic auth 
if this method returns false)
      */
     public boolean requiresUserPass();
-    public boolean authenticate(HttpSession session, String user, String pass);
+    /** Perform the authentication. If {@link #requiresUserPass()} returns 
false, user/pass may be null;
+     * otherwise the framework will guarantee the basic auth is in effect and 
these values are set.
+     * The provider should not send a response but should throw {@link 
SecurityProviderDeniedAuthentication}
+     * if a custom response is required. It can include a response in that 
exception,
+     * e.g. to provide more information or supply a redirect. */
+    public boolean authenticate(HttpSession session, String user, String pass) 
throws SecurityProviderDeniedAuthentication;
     public boolean logout(HttpSession session);
     
-    public interface PostAuthenticator {
-        /** Invoked by framework after successful authentication for 
principals to be updated. 
-         * (That needs to happen against the container which is not otherwise 
accessible.) */
-        public void postAuthenticate(ContainerRequestContext requestContext);
+    public static class SecurityProviderDeniedAuthentication extends Exception 
{
+        private static final long serialVersionUID = -3048228939219746783L;
+        private final Response response;
+        public SecurityProviderDeniedAuthentication() { this(null); }
+        public SecurityProviderDeniedAuthentication(Response r) {
+            this.response = r;
+        }
+        public Response getResponse() {
+            return response;
+        }
     }
+
 }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ManagementContextProvider.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ManagementContextProvider.java
index 46a2238..fc80fe8 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ManagementContextProvider.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/util/ManagementContextProvider.java
@@ -24,13 +24,19 @@ import javax.ws.rs.ext.ContextResolver;
 import javax.ws.rs.ext.Provider;
 
 import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.core.server.BrooklynServiceAttributes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
 
 @Provider
 // Needed by tests in rest-resources module and by main code in rest-server
 public class ManagementContextProvider implements 
ContextResolver<ManagementContext> {
+    
+    @SuppressWarnings("unused")
+    private static final Logger log = 
LoggerFactory.getLogger(ManagementContextProvider.class);
+    
     @Context
     private ServletContext context;
 
@@ -38,6 +44,11 @@ public class ManagementContextProvider implements 
ContextResolver<ManagementCont
 
     public ManagementContextProvider() {
     }
+    
+    // for usages that cannot do injection 
+    public ManagementContextProvider(ServletContext context) {
+        this.context = context;
+    }
 
     @VisibleForTesting
     public ManagementContextProvider(ManagementContext mgmt) {
@@ -47,14 +58,18 @@ public class ManagementContextProvider implements 
ContextResolver<ManagementCont
     @Override
     public ManagementContext getContext(Class<?> type) {
         if (type == ManagementContext.class) {
-            if (mgmt != null) {
-                return mgmt;
-            } else {
-                return (ManagementContext) 
context.getAttribute(BrooklynServiceAttributes.BROOKLYN_MANAGEMENT_CONTEXT);
-            }
+            return getManagementContext();
         } else {
             return null;
         }
     }
+    
+    @Beta
+    public ManagementContext getManagementContext() {
+        if (mgmt != null) {
+            return mgmt;
+        }
+        return OsgiCompat.getManagementContext(context);
+    }
 
 }
diff --git 
a/rest/rest-resources/src/main/resources/OSGI-INF/blueprint/service.xml 
b/rest/rest-resources/src/main/resources/OSGI-INF/blueprint/service.xml
index f357222..1f10b4b 100644
--- a/rest/rest-resources/src/main/resources/OSGI-INF/blueprint/service.xml
+++ b/rest/rest-resources/src/main/resources/OSGI-INF/blueprint/service.xml
@@ -108,14 +108,10 @@ limitations under the License.
             <bean 
class="org.apache.brooklyn.rest.util.DefaultExceptionMapper"/>
             <bean 
class="org.apache.brooklyn.rest.util.json.BrooklynJacksonJsonProvider"/>
             <bean class="org.apache.brooklyn.rest.util.FormMapProvider"/>
-            <bean 
class="org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilter"/>
             <bean 
class="org.apache.brooklyn.rest.util.ManagementContextProvider">
                 <argument ref="localManagementContext"/>
             </bean>
-            <!--
-                TODO ShutdownHandlerProvider, sync with init work.
-                Needs to be custom OSGi implementation?
-            -->
+            <bean 
class="org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilterJersey"/>
             <bean class="org.apache.brooklyn.rest.filter.CsrfTokenFilter"/>
             <bean 
class="org.apache.brooklyn.rest.filter.RequestTaggingRsFilter"/>
             <bean class="org.apache.brooklyn.rest.filter.NoCacheFilter"/>
diff --git 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/filter/EntitlementContextFilterTest.java
 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/filter/EntitlementContextFilterTest.java
index 3c7748b..7b75428 100644
--- 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/filter/EntitlementContextFilterTest.java
+++ 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/filter/EntitlementContextFilterTest.java
@@ -34,7 +34,7 @@ import 
org.apache.brooklyn.rest.testing.BrooklynRestResourceTest;
 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.http.HttpStatus;
-import org.eclipse.jetty.server.session.HashSessionManager;
+import org.eclipse.jetty.server.session.SessionHandler;
 import org.testng.annotations.Test;
 
 public class EntitlementContextFilterTest extends BrooklynRestResourceTest {
@@ -57,13 +57,13 @@ public class EntitlementContextFilterTest extends 
BrooklynRestResourceTest {
         props.put(BrooklynWebConfig.PASSWORD_FOR_USER(USER_PASS), USER_PASS);
         
getManagementContext().getScratchpad().put(BrooklynWebConfig.SECURITY_PROVIDER_INSTANCE,
 new ExplicitUsersSecurityProvider(getManagementContext()));
 
-        sf.setProvider(new HashSessionManager());
+        sf.setProvider(new SessionHandler());
         super.configureCXF(sf);
     }
 
     @Override
     protected void addBrooklynResources() {
-        addResource(new BrooklynSecurityProviderFilter());
+        addResource(new BrooklynSecurityProviderFilterHelper());
         addResource(new RequestTaggingRsFilter());
         addResource(new EntitlementContextFilter());
         addResource(new EntitlementResource());
diff --git 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestResourceTest.java
 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestResourceTest.java
index 0e2ba61..4a52a53 100644
--- 
a/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestResourceTest.java
+++ 
b/rest/rest-resources/src/test/java/org/apache/brooklyn/rest/testing/BrooklynRestResourceTest.java
@@ -49,7 +49,6 @@ import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.cxf.jaxrs.utils.ResourceUtils;
 import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngine;
 import org.apache.cxf.transport.http_jetty.JettyHTTPServerEngineFactory;
-import org.eclipse.jetty.server.session.HashSessionManager;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
diff --git 
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java 
b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
index d961f7d..33bbfd3 100644
--- a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
+++ b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/RestApiSetup.java
@@ -26,17 +26,14 @@ import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 
 import org.apache.brooklyn.rest.apidoc.RestApiResourceScanner;
-import org.apache.brooklyn.rest.filter.MyOauthFilter;
 import org.apache.cxf.BusFactory;
 import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet;
 import org.apache.cxf.transport.common.gzip.GZIPInInterceptor;
 import org.apache.cxf.transport.common.gzip.GZIPOutInterceptor;
-import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
 
 import io.swagger.config.ScannerFactory;
-import org.eclipse.jetty.webapp.WebAppContext;
 
 public class RestApiSetup {
 
@@ -73,18 +70,4 @@ public class RestApiSetup {
         ScannerFactory.setScanner(new RestApiResourceScanner());
     }
 
-    public static void installOauthServletFilters(WebAppContext context, 
Class<MyOauthFilter> myOauthFilterClass) {
-        FilterHolder fh= context.addFilter(myOauthFilterClass, "/*", 
EnumSet.allOf(DispatcherType.class));
-        setFilterParams(fh);
-    }
-    private static void setFilterParams(FilterHolder fh) {
-        fh.setInitParameter(MyOauthFilter.PARAM_URI_GETTOKEN, 
"https://accounts.google.com/o/oauth2/token";);
-        fh.setInitParameter(MyOauthFilter.PARAM_URI_TOKEN_INFO, 
"https://www.googleapis.com/oauth2/v1/tokeninfo";);
-        fh.setInitParameter(MyOauthFilter.PARAM_URI_LOGIN_REDIRECT, "/login");
-        fh.setInitParameter(MyOauthFilter.PARAM_CLIENT_ID,
-                
"789182012565-burd24h3bc0im74g2qemi7lnihvfqd02.apps.googleusercontent.com");
-        fh.setInitParameter(MyOauthFilter.PARAM_CLIENT_SECRET, 
"X00v-LfU34U4SfsHqPKMWfQl");
-        fh.setInitParameter(MyOauthFilter.PARAM_CALLBACK_URI, 
"http://localhost.io:8080/service/ping";);
-        fh.setInitParameter(MyOauthFilter.PARAM_AUDIENCE, "audience");
-    }
 }
diff --git 
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
 
b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
deleted file mode 100644
index fcdea9d..0000000
--- 
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/BrooklynPropertiesSecurityFilter.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.rest.filter;
-
-import java.io.IOException;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.apache.brooklyn.api.mgmt.ManagementContext;
-import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
-import org.apache.brooklyn.core.mgmt.entitlement.WebEntitlementContext;
-import org.apache.brooklyn.rest.BrooklynWebConfig;
-import org.apache.brooklyn.rest.resources.LogoutResource;
-import org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule;
-import org.apache.brooklyn.rest.security.provider.DelegatingSecurityProvider;
-import org.apache.brooklyn.rest.util.OsgiCompat;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.commons.codec.binary.Base64;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Provides basic HTTP authentication.
- * 
- * @deprecated since 0.9.0, use JAAS authentication instead, see {@link 
BrooklynLoginModule}, {@link LogoutResource}, {@link EntitlementContextFilter}.
- */
-@Deprecated
-public class BrooklynPropertiesSecurityFilter implements Filter {
-
-    /**
-     * The session attribute set for authenticated users; for reference
-     * (but should not be relied up to confirm authentication, as
-     * the providers may impose additional criteria such as timeouts,
-     * or a null user (no login) may be permitted)
-     */
-    public static final String AUTHENTICATED_USER_SESSION_ATTRIBUTE = 
BrooklynLoginModule.AUTHENTICATED_USER_SESSION_ATTRIBUTE;
-
-    private static final Logger log = 
LoggerFactory.getLogger(BrooklynSecurityProviderFilter.class);
-
-    protected DelegatingSecurityProvider provider;
-
-    private static ThreadLocal<String> originalRequest = new 
ThreadLocal<String>();
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
-        HttpServletRequest httpRequest = (HttpServletRequest) request;
-        HttpServletResponse httpResponse = (HttpServletResponse) response;
-        String uri = httpRequest.getRequestURI();
-
-        if (provider == null) {
-            log.warn("No security provider available: disallowing web access 
to brooklyn");
-            httpResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
-            return;
-        }
-
-        if (originalRequest.get() != null) {
-            // clear the entitlement context before setting to avoid warnings
-            Entitlements.clearEntitlementContext();
-        } else {
-            originalRequest.set(uri);
-        }
-
-        boolean authenticated = 
provider.isAuthenticated(httpRequest.getSession());
-        if ("/logout".equals(uri) || "/v1/logout".equals(uri)) {
-            httpResponse.setHeader("WWW-Authenticate", "Basic 
realm=\"brooklyn\"");
-            if (authenticated && 
httpRequest.getSession().getAttributeNames().hasMoreElements()) {
-                logout(httpRequest);
-                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-            } else {
-                RequestDispatcher dispatcher = 
httpRequest.getRequestDispatcher("/");
-                log.debug("Not authenticated, forwarding request for {} to 
{}", uri, dispatcher);
-                dispatcher.forward(httpRequest, httpResponse);
-            }
-            return;
-        }
-
-        if (!(httpRequest.getSession().getAttributeNames().hasMoreElements() 
&& provider.isAuthenticated(httpRequest.getSession())) ||
-                "/logout".equals(originalRequest.get())) {
-            authenticated = authenticate(httpRequest);
-        }
-
-        if (!authenticated) {
-            httpResponse.setHeader("WWW-Authenticate", "Basic 
realm=\"brooklyn\"");
-            httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-            return;
-        }
-
-        // Note that the attribute AUTHENTICATED_USER_SESSION_ATTRIBUTE is 
only set in the call to authenticate(httpRequest),
-        // so must not try to get the user until that is done.
-        String uid = RequestTaggingFilter.getTag();
-        String user = 
Strings.toString(httpRequest.getSession().getAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE));
-        try {
-            WebEntitlementContext entitlementContext = new 
WebEntitlementContext(user, httpRequest.getRemoteAddr(), uri, uid);
-            Entitlements.setEntitlementContext(entitlementContext);
-
-            chain.doFilter(request, response);
-        } catch (Throwable e) {
-            if (!response.isCommitted()) {
-                
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
-            }
-        } finally {
-            originalRequest.remove();
-            Entitlements.clearEntitlementContext();
-        }
-    }
-
-    protected boolean authenticate(HttpServletRequest request) {
-        HttpSession session = request.getSession();
-        if (provider.isAuthenticated(session)) {
-            return true;
-        }
-        
session.setAttribute(BrooklynWebConfig.REMOTE_ADDRESS_SESSION_ATTRIBUTE, 
request.getRemoteAddr());
-        String user = null, pass = null;
-        String authorization = request.getHeader("Authorization");
-        if (authorization != null) {
-            String userpass = new 
String(Base64.decodeBase64(authorization.substring(6)));
-            int idxColon = userpass.indexOf(":");
-            if (idxColon >= 0) {
-                user = userpass.substring(0, idxColon);
-                pass = userpass.substring(idxColon + 1);
-            } else {
-                return false;
-            }
-        }
-        if (provider.authenticate(session, user, pass)) {
-            if (user != null) {
-                session.setAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE, 
user);
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    @Override
-    public void init(FilterConfig config) throws ServletException {
-        ManagementContext mgmt = 
OsgiCompat.getManagementContext(config.getServletContext());
-        provider = new DelegatingSecurityProvider(mgmt);
-    }
-
-    @Override
-    public void destroy() {
-    }
-
-    protected void logout(HttpServletRequest request) {
-        log.info("REST logging {} out of session {}",
-                
request.getSession().getAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE), 
request.getSession().getId());
-        provider.logout(request.getSession());
-        
request.getSession().removeAttribute(AUTHENTICATED_USER_SESSION_ATTRIBUTE);
-        
request.getSession().removeAttribute(BrooklynWebConfig.REMOTE_ADDRESS_SESSION_ATTRIBUTE);
-        request.getSession().invalidate();
-    }
-
-}
diff --git 
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java
 
b/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java
deleted file mode 100644
index 4ae2b4a..0000000
--- 
a/rest/rest-server/src/main/java/org/apache/brooklyn/rest/filter/MyOauthFilter.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.rest.filter;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.minidev.json.JSONObject;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.entity.ContentType;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.message.BasicNameValuePair;
-import org.apache.http.util.EntityUtils;
-import org.json.simple.parser.JSONParser;
-import org.json.simple.parser.ParseException;
-
-public class MyOauthFilter  implements Filter {
-
-    private static final String SESSION_KEY_CODE = "code";
-
-    private static final String SESSION_KEY_ACCESS_TOKEN = "access_token";
-
-    public static final String PARAM_URI_TOKEN_INFO = "uriTokenInfo";
-    private String uriTokenInfo = "";
-    public static final String PARAM_URI_GETTOKEN = "uriGetToken";
-    private String uriGetToken = "";
-    public static final String PARAM_URI_LOGIN_REDIRECT = "uriLoginRedirect";
-    private String uriTokenRedirect = "";
-    public static final String PARAM_CLIENT_ID = "clientId";
-    private String clientId = "";
-    public static final String PARAM_CLIENT_SECRET = "clientSecret";
-    private String clientSecret = "";
-    public static final String PARAM_CALLBACK_URI = "callbackUri";
-    private String callbackUri = "";
-    public static final String PARAM_AUDIENCE = "audience";
-    private String audience = "";
-
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-        initializateParams(filterConfig);
-    }
-
-    private void initializateParams(FilterConfig filterConfig) {
-        Enumeration<String> enums = filterConfig.getInitParameterNames();
-
-        while (enums.hasMoreElements()) {
-            String paramKey = enums.nextElement();
-            String paramValue = filterConfig.getInitParameter(paramKey);
-            System.out.println(paramKey + ":" + paramValue);
-            switch (paramKey) {
-            case PARAM_URI_TOKEN_INFO:
-                uriTokenInfo = paramValue;
-                break;
-            case PARAM_URI_GETTOKEN:
-                uriGetToken = paramValue;
-                break;
-            case PARAM_URI_LOGIN_REDIRECT:
-                uriTokenRedirect = paramValue;
-                break;
-            case PARAM_CLIENT_ID:
-                clientId = paramValue;
-                break;
-            case PARAM_CLIENT_SECRET:
-                clientSecret = paramValue;
-                break;
-            case PARAM_CALLBACK_URI:
-                callbackUri = paramValue;
-                break;
-            case PARAM_AUDIENCE:
-                audience = paramValue;
-                break;
-            default:
-                System.out.println("Ignored param: " + paramKey + ":" + 
paramValue);
-            }
-        }
-    }
-
-    @Override
-    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain 
chain)
-            throws IOException, ServletException {
-        HttpServletRequest request = (HttpServletRequest) req;
-        // Redirection from the authenticator server
-        String code = req.getParameter(SESSION_KEY_CODE);
-
-        // Getting token, if exists, from the current session
-        String token = (String) 
request.getSession().getAttribute(SESSION_KEY_ACCESS_TOKEN);
-
-        boolean continueFilterProcessing;
-        if (code != null && !"".equals(code)) { // in brooklyn, have
-                                                // Strings.isNonBlank(code)
-            continueFilterProcessing = getToken(req, resp, chain);
-        } else if (token == null || "".equals(token)) { // isBlank
-            continueFilterProcessing = redirectLogin(resp);
-        } else {
-            continueFilterProcessing = validateToken(token, resp);
-        }
-        if (continueFilterProcessing) {
-            chain.doFilter(req, resp);
-        }
-    }
-
-    private boolean validateToken(String token, ServletResponse resp) throws 
ClientProtocolException, IOException {
-        // System.out.println("########################### Validating token
-        // ###########################");
-        HashMap<String, String> params = new HashMap<String, String>();
-        params.put(SESSION_KEY_ACCESS_TOKEN, token);
-
-        String body = post(uriTokenInfo, params);
-        // System.out.println(body);
-        JSONObject jsonObject = null;
-
-        // get the access token from json and request info from Google
-        try {
-            jsonObject = (JSONObject) new JSONParser().parse(body);
-        } catch (ParseException e) {
-            throw new RuntimeException("Unable to parse json " + body);
-        }
-
-        if (!clientId.equals(jsonObject.get(audience))) {
-            return redirectLogin(resp);
-        }
-        // if (isTokenExpiredOrNearlySo(...) { ... }
-        return true;
-    }
-
-    private boolean getToken(ServletRequest req, ServletResponse resp, 
FilterChain chain)
-            throws ClientProtocolException, IOException, ServletException {
-        String code = req.getParameter(SESSION_KEY_CODE);
-
-        // get the access token by post to Google
-        HashMap<String, String> params = new HashMap<String, String>();
-        params.put(SESSION_KEY_CODE, code);
-        params.put("client_id", clientId);
-        params.put("client_secret", clientSecret);
-        params.put("redirect_uri", callbackUri);
-        params.put("grant_type", "authorization_code");
-
-        String body = post(uriGetToken, params);
-
-        JSONObject jsonObject = null;
-
-        // get the access token from json and request info from Google
-        try {
-            jsonObject = (JSONObject) new JSONParser().parse(body);
-        } catch (ParseException e) {
-            // throw new RuntimeException("Unable to parse json " + body);
-            return redirectLogin(resp);
-        }
-
-        // Left token and code in session
-        String accessToken = (String) jsonObject.get(SESSION_KEY_ACCESS_TOKEN);
-        HttpServletRequest request = (HttpServletRequest) req;
-        request.getSession().setAttribute(SESSION_KEY_ACCESS_TOKEN, 
accessToken);
-        request.getSession().setAttribute(SESSION_KEY_CODE, code);
-
-        // resp.getWriter().println(json);
-        return true;
-    }
-
-    // makes a POST request to url with form parameters and returns body as a
-    // string
-    public String post(String url, Map<String, String> formParameters) throws 
ClientProtocolException, IOException {
-        HttpPost request = new HttpPost(url);
-
-        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
-        for (String key : formParameters.keySet()) {
-            nvps.add(new BasicNameValuePair(key, formParameters.get(key)));
-        }
-        request.setEntity(new UrlEncodedFormEntity(nvps));
-
-        return execute(request);
-    }
-
-    // makes a GET request to url and returns body as a string
-    public String get(String url) throws ClientProtocolException, IOException {
-        return execute(new HttpGet(url));
-    }
-
-    // makes request and checks response code for 200
-    private String execute(HttpRequestBase request) throws 
ClientProtocolException, IOException {
-        HttpClient httpClient = new DefaultHttpClient();
-        HttpResponse response = httpClient.execute(request);
-
-        HttpEntity entity = response.getEntity();
-        String body = EntityUtils.toString(entity);
-
-        if (response.getStatusLine().getStatusCode() != 200) {
-            throw new RuntimeException(
-                    "Expected 200 but got " + 
response.getStatusLine().getStatusCode() + ", with body " + body);
-        }
-
-        return body;
-    }
-
-    private boolean redirectLogin(ServletResponse response) throws IOException 
{
-        HttpServletResponse res = (HttpServletResponse) response;
-        res.setContentType(ContentType.APPLICATION_XML.toString());
-        res.sendRedirect(uriTokenRedirect);
-        return false;
-    }
-
-    @Override
-    public void destroy() {
-        // TODO Auto-generated method stub
-    }
-
-}
diff --git 
a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
 
b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
index eaa20f4..ec117e0 100644
--- 
a/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
+++ 
b/rest/rest-server/src/test/java/org/apache/brooklyn/rest/BrooklynRestApiLauncher.java
@@ -38,6 +38,7 @@ import 
org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.core.server.BrooklynServerConfig;
 import org.apache.brooklyn.core.server.BrooklynServiceAttributes;
 import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.rest.filter.BrooklynSecurityProviderFilterHelper;
 import org.apache.brooklyn.rest.filter.CorsImplSupplierFilter;
 import org.apache.brooklyn.rest.filter.CsrfTokenFilter;
 import org.apache.brooklyn.rest.filter.EntitlementContextFilter;
@@ -46,8 +47,6 @@ import org.apache.brooklyn.rest.filter.LoggingFilter;
 import org.apache.brooklyn.rest.filter.NoCacheFilter;
 import org.apache.brooklyn.rest.filter.RequestTaggingFilter;
 import org.apache.brooklyn.rest.filter.RequestTaggingRsFilter;
-import 
org.apache.brooklyn.rest.security.jaas.BrooklynLoginModule.RolePrincipal;
-import org.apache.brooklyn.rest.security.jaas.JaasUtils;
 import org.apache.brooklyn.rest.security.provider.AnyoneSecurityProvider;
 import org.apache.brooklyn.rest.security.provider.SecurityProvider;
 import org.apache.brooklyn.rest.util.ManagementContextProvider;
@@ -58,7 +57,6 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.net.Networking;
 import org.apache.brooklyn.util.text.WildcardGlobs;
-import org.eclipse.jetty.jaas.JAASLoginService;
 import org.eclipse.jetty.server.NetworkConnector;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.handler.ContextHandler;
@@ -281,7 +279,7 @@ public class BrooklynRestApiLauncher {
     private static Server startServer(ManagementContext mgmt, ContextHandler 
context, String summary, InetSocketAddress bindLocation) {
         Server server = new Server(bindLocation);
 
-        initJaas(mgmt, server);
+        initAuth(mgmt, server);
 
         server.setHandler(context);
         try {
@@ -296,17 +294,8 @@ public class BrooklynRestApiLauncher {
     }
 
     // TODO Why parallel code for server init here and in BrooklynWebServer?
-    private static void initJaas(ManagementContext mgmt, Server server) {
-        JaasUtils.init(mgmt);
-        initJaasLoginService(server);
-    }
-
-    public static void initJaasLoginService(Server server) {
-        JAASLoginService loginService = new JAASLoginService();
-        loginService.setName("webconsole");
-        loginService.setLoginModuleName("webconsole");
-        loginService.setRoleClassNames(new String[] 
{RolePrincipal.class.getName()});
-        server.addBean(loginService);
+    private static void initAuth(ManagementContext mgmt, Server server) {
+        server.addBean(new BrooklynSecurityProviderFilterHelper());
     }
 
     public static BrooklynRestApiLauncher launcher() {

Reply via email to