/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.auth; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.security.Principal; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import org.geoserver.data.test.SystemTestData; import org.geoserver.security.GeoServerSecurityFilterChain; import org.geoserver.security.GeoServerSecurityManager; import org.geoserver.security.config.BasicAuthenticationFilterConfig; import org.geoserver.security.config.DigestAuthenticationFilterConfig; import org.geoserver.security.config.J2eeAuthenticationBaseFilterConfig.J2EERoleSource; import org.geoserver.security.config.J2eeAuthenticationFilterConfig; import org.geoserver.security.config.PreAuthenticatedUserNameFilterConfig.PreAuthenticatedUserNameRoleSource; import org.geoserver.security.config.RequestHeaderAuthenticationFilterConfig; import org.geoserver.security.config.X509CertificateAuthenticationFilterConfig; import org.geoserver.security.filter.GeoServerBasicAuthenticationFilter; import org.geoserver.security.filter.GeoServerDigestAuthenticationFilter; import org.geoserver.security.filter.GeoServerJ2eeAuthenticationFilter; import org.geoserver.security.filter.GeoServerRequestHeaderAuthenticationFilter; import org.geoserver.security.filter.GeoServerX509CertificateAuthenticationFilter; import org.geoserver.security.impl.GeoServerRole; import org.geoserver.security.impl.GeoServerUser; import org.geoserver.test.RunTestSetup; import org.geoserver.test.SystemTest; import org.geotools.data.Base64; import org.junit.Test; import org.junit.experimental.categories.Category; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.mock.web.MockFilterChain; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @Category(SystemTest.class) public class AuthenticationCacheFilterTest extends AbstractAuthenticationProviderTest { public final static String testFilterName = "basicAuthTestFilter"; public final static String testFilterName2 = "digestAuthTestFilter"; public final static String testFilterName3 = "j2eeAuthTestFilter"; public final static String testFilterName4 = "requestHeaderTestFilter"; public final static String testFilterName5 = "basicAuthTestFilterWithRememberMe"; public final static String testFilterName8 = "x509TestFilter"; @Override protected void onSetUp(SystemTestData testData) throws Exception { super.onSetUp(testData); BasicAuthenticationFilterConfig config = new BasicAuthenticationFilterConfig(); config.setClassName(GeoServerBasicAuthenticationFilter.class.getName()); config.setUseRememberMe(false); config.setName(testFilterName); getSecurityManager().saveFilter(config); } Authentication getAuth(String filterName, String user, Integer idleTime, Integer liveTime) { Map<String,byte[]> map= getCache().cache.get(filterName); if (map==null) return null; Authentication result=null; String cacheKey=null; for ( Entry<String,byte[]> entry : map.entrySet()) { Authentication auth = getCache().deserializeAuthentication(entry.getValue()); Object o = auth.getPrincipal(); if (o instanceof UserDetails) { if (user.equals(((UserDetails)o).getUsername())) { result= auth; cacheKey=entry.getKey(); break; } } if (o instanceof Principal) { if (user.equals(((Principal)o).getName())) { result= auth; cacheKey=entry.getKey(); break; } } if (o instanceof String) { if (user.equals(((String)o))) { result= auth; cacheKey=entry.getKey(); break; } } } if (result != null) { Integer[] seconds = getCache().getExpireTimes(filterName, cacheKey); if (idleTime==null) assertEquals(TestingAuthenticationCache.DEFAULT_IDLE_SECS, seconds[0]); else assertEquals(idleTime, seconds[0]); if (liveTime==null) assertEquals(TestingAuthenticationCache.DEFAULT_LIVE_SECS, seconds[1]); else assertEquals(liveTime, seconds[1]); } return result; } @Test public void testBasicAuth() throws Exception{ prepareFilterChain(pattern,testFilterName); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); String tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Basic") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check success request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((testUserName+":"+testPassword).getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName, testUserName,null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // check wrong password // request= createRequest("/foo/bar"); // response= new MockHttpServletResponse(); // chain = new MockFilterChain(); // // request.addHeader("Authorization", "Basic " + // new String(Base64.encodeBytes((testUserName+":wrongpass").getBytes()))); // getProxy().doFilter(request, response, chain); // tmp = response.getHeader("WWW-Authenticate"); // assertNotNull(tmp); // assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); // assert(tmp.indexOf("Basic") !=-1 ); // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getErrorCode()); // assertNull(SecurityContextHolder.getContext().getAuthentication()); // auth = getAuth(testFilterName, testUserName,null,null); // assertNull(auth); // check unknown user request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes(("unknwon:"+testPassword).getBytes()))); getProxy().doFilter(request, response, chain); tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Basic") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); auth = getAuth("unknow", testPassword,null,null); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check root user request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((GeoServerUser.ROOT_USERNAME+":"+getMasterPassword()).getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(GeoServerUser.ROOT_USERNAME, "geoserver",null,null); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check disabled user updateUser("ug1", testUserName, false); // since the cache is working, disabling has no effect request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((testUserName+":"+testPassword).getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName, testUserName,null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // clear cache, user should be disabled getCache().removeAll(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((testUserName+":"+testPassword).getBytes()))); getProxy().doFilter(request, response, chain); tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Basic") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); updateUser("ug1", testUserName, true); } @Test public void testJ2eeProxy() throws Exception{ J2eeAuthenticationFilterConfig config = new J2eeAuthenticationFilterConfig(); config.setClassName(GeoServerJ2eeAuthenticationFilter.class.getName()); config.setName(testFilterName3); config.setRoleSource(J2EERoleSource.J2EE); config.setRoleServiceName("rs1"); getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName3); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_FORBIDDEN,response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); // test preauthenticated with dedicated role service request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.setUserPrincipal(new Principal() { @Override public String getName() { return testUserName; } }); if(true) { request.addUserRole(derivedRole); } if(false) { request.addUserRole(rootRole); } getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName3, testUserName,null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, auth.getPrincipal()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // test root request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.setUserPrincipal(new Principal() { @Override public String getName() { return GeoServerUser.ROOT_USERNAME; } }); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName3, GeoServerUser.ROOT_USERNAME,null,null); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); //checkForAuthenticatedRole(auth); config.setRoleServiceName(null); getSecurityManager().saveFilter(config); // test preauthenticated with active role service request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.setUserPrincipal(new Principal() { @Override public String getName() { return testUserName; } }); if(true) { request.addUserRole(derivedRole); } if(false) { request.addUserRole(rootRole); } getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName3, testUserName,null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, auth.getPrincipal()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // Test anonymous insertAnonymousFilter(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); // Anonymous context is not stored in http session, no further testing removeAnonymousFilter(); } @Test public void testRequestHeaderProxy() throws Exception{ RequestHeaderAuthenticationFilterConfig config = new RequestHeaderAuthenticationFilterConfig(); config.setClassName(GeoServerRequestHeaderAuthenticationFilter.class.getName()); config.setName(testFilterName4); config.setRoleServiceName("rs1"); config.setPrincipalHeaderAttribute("principal"); config.setRoleSource(PreAuthenticatedUserNameRoleSource.RoleService); config.setUserGroupServiceName("ug1"); config.setPrincipalHeaderAttribute("principal"); config.setRolesHeaderAttribute("roles");; getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName4); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_FORBIDDEN,response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); for (PreAuthenticatedUserNameRoleSource rs : PreAuthenticatedUserNameRoleSource.values()) { getCache().removeAll(); config.setRoleSource(rs); getSecurityManager().saveFilter(config); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("principal", testUserName); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { request.addHeader("roles", derivedRole+";"+rootRole); } getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName4, testUserName,null,null); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { continue; // no cache } assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, auth.getPrincipal()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); } // unknown user for (PreAuthenticatedUserNameRoleSource rs : PreAuthenticatedUserNameRoleSource.values()) { getCache().removeAll(); config.setRoleSource(rs); getSecurityManager().saveFilter(config); config.setRoleSource(rs); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("principal", "unknown"); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { continue; // no cache } Authentication auth = getAuth(testFilterName4, "unknown",null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals("unknown", auth.getPrincipal()); } // test disabled user, should not work since cache is active config.setRoleSource(PreAuthenticatedUserNameRoleSource.UserGroupService); // saving a filter empties the cache getSecurityManager().saveFilter(config); updateUser("ug1", testUserName, false); request= createRequest("/foo/bar"); request.addHeader("principal", testUserName); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_FORBIDDEN,response.getStatus()); Authentication auth = getAuth(testFilterName4, testUserName,null,null); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); updateUser("ug1", testUserName, true); // Test anonymous insertAnonymousFilter(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); // Anonymous context is not stored in http session, no further testing removeAnonymousFilter(); } @Test public void testDigestAuth() throws Exception{ DigestAuthenticationFilterConfig config = new DigestAuthenticationFilterConfig(); config.setClassName(GeoServerDigestAuthenticationFilter.class.getName()); config.setName(testFilterName2); config.setUserGroupServiceName("ug1"); getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName2); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_UNAUTHORIZED,response.getStatus()); String tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Digest") !=-1 ); assertNull(SecurityContextHolder.getContext().getAuthentication()); // test successful login request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); String headerValue=clientDigestString(tmp, testUserName, testPassword, request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName2, testUserName,300,300); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // check wrong password // request= createRequest("/foo/bar"); // response= new MockHttpServletResponse(); // chain = new MockFilterChain(); // // headerValue=clientDigestString(tmp, testUserName, "wrongpass", request.getMethod()); // request.addHeader("Authorization", headerValue); // getProxy().doFilter(request, response, chain); // tmp = response.getHeader("WWW-Authenticate"); // assertNotNull(tmp); // assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); // assert(tmp.indexOf("Digest") !=-1 ); // assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getErrorCode()); // auth = getAuth(testFilterName2, testUserName,300,300); // assertNull(auth); // assertNull(SecurityContextHolder.getContext().getAuthentication()); // check unknown user request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); headerValue=clientDigestString(tmp, "unknown", testPassword, request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Digest") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); auth = getAuth(testFilterName2, "unknown",300,300); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check root user request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); headerValue=clientDigestString(tmp, GeoServerUser.ROOT_USERNAME, getMasterPassword(), request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName2, GeoServerUser.ROOT_USERNAME,300,300); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check root user with wrong password request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); headerValue=clientDigestString(tmp, GeoServerUser.ROOT_USERNAME, "geoserver1", request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Digest") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); auth = getAuth(testFilterName2, GeoServerUser.ROOT_USERNAME,300,300); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); // check disabled user, should not work becaus of cache updateUser("ug1", testUserName, false); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); headerValue=clientDigestString(tmp, testUserName, testPassword, request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName2, testUserName,300,300); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // clear cache, now disabling should work getCache().removeAll(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); headerValue=clientDigestString(tmp, "unknown", testPassword, request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Digest") !=-1 ); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); auth = getAuth(testFilterName2, testUserName,300,300); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); updateUser("ug1", testUserName, true); // Test anonymous insertAnonymousFilter(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); // Anonymous context is not stored in http session, no further testing removeAnonymousFilter(); } @Test public void testBasicAuthWithRememberMe() throws Exception{ BasicAuthenticationFilterConfig config = new BasicAuthenticationFilterConfig(); config.setClassName(GeoServerBasicAuthenticationFilter.class.getName()); config.setUseRememberMe(true); config.setName(testFilterName5); getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName5, GeoServerSecurityFilterChain.REMEMBER_ME_FILTER); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(0, response.getCookies().length); String tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); // check success request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes(("abc@xyz.com:abc").getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName5, "abc@xyz.com", null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(1,response.getCookies().length); Cookie cookie = (Cookie) response.getCookies()[0]; request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); request.setCookies(cookie); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName5, "abc@xyz.com", null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals("abc@xyz.com", ((UserDetails) auth.getPrincipal()).getUsername()); // assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); // assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // send cookie + auth header request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); request.setCookies(cookie); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes(("abc@xyz.com:abc").getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName5, "abc@xyz.com", null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals("abc@xyz.com", ((UserDetails) auth.getPrincipal()).getUsername()); // check no remember me for root user request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((GeoServerUser.ROOT_USERNAME+":"+getMasterPassword()).getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName5, GeoServerUser.ROOT_USERNAME, null,null); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); //checkForAuthenticatedRole(auth); // no cookie for root user assertEquals(0,response.getCookies().length); // check disabled user updateUser("ug1", "abc@xyz.com", false); request= createRequest("/foo/bar"); request.addParameter("_spring_security_remember_me", "yes"); request.setCookies(cookie); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_UNAUTHORIZED, response.getStatus()); // check for cancel cookie assertEquals(1,response.getCookies().length); Cookie cancelCookie = (Cookie) response.getCookies()[0]; assertNull(cancelCookie.getValue()); updateUser("ug1", "abc@xyz.com", true); } @Test public void testX509Auth() throws Exception{ X509CertificateAuthenticationFilterConfig config = new X509CertificateAuthenticationFilterConfig(); config.setClassName(GeoServerX509CertificateAuthenticationFilter.class.getName()); config.setName(testFilterName8); config.setRoleServiceName("rs1"); config.setRoleSource(PreAuthenticatedUserNameRoleSource.RoleService); config.setUserGroupServiceName("ug1"); config.setRolesHeaderAttribute("roles"); getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName8); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_FORBIDDEN,response.getStatus()); assertNull(SecurityContextHolder.getContext().getAuthentication()); for (PreAuthenticatedUserNameRoleSource rs : PreAuthenticatedUserNameRoleSource.values()) { getCache().removeAll(); config.setRoleSource(rs); getSecurityManager().saveFilter(config); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { request.addHeader("roles", derivedRole+";"+rootRole); } setCertifacteForUser(testUserName, request); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { continue; // no cache } Authentication auth = getAuth(testFilterName8, testUserName,null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, auth.getPrincipal()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); } // unknown user for (PreAuthenticatedUserNameRoleSource rs : PreAuthenticatedUserNameRoleSource.values()) { getCache().removeAll(); config.setRoleSource(rs); getSecurityManager().saveFilter(config); config.setRoleSource(rs); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); //TODO setCertifacteForUser("unknown", request); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); if (rs.equals(PreAuthenticatedUserNameRoleSource.Header)) { continue; // no cache } Authentication auth = getAuth(testFilterName8, "unknown",null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals("unknown", auth.getPrincipal()); } // test disabled user, should not work because of active cache updateUser("ug1", testUserName, false); config.setRoleSource(PreAuthenticatedUserNameRoleSource.UserGroupService); // saving the filter clears the cache getSecurityManager().saveFilter(config); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); setCertifacteForUser(testUserName, request); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_FORBIDDEN,response.getStatus()); Authentication auth = getAuth(testFilterName8, testUserName,0,0); assertNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); updateUser("ug1", testUserName, true); // Test anonymous insertAnonymousFilter(); request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); // Anonymous context is not stored in http session, no further testing removeAnonymousFilter(); } @Test @RunTestSetup public void testCascadingFilters() throws Exception{ DigestAuthenticationFilterConfig config = new DigestAuthenticationFilterConfig(); config.setClassName(GeoServerDigestAuthenticationFilter.class.getName()); config.setName(testFilterName2); config.setUserGroupServiceName("ug1"); getSecurityManager().saveFilter(config); prepareFilterChain(pattern, testFilterName, testFilterName2); SecurityContextHolder.getContext().setAuthentication(null); // Test entry point, must be digest MockHttpServletRequest request= createRequest("/foo/bar"); MockHttpServletResponse response= new MockHttpServletResponse(); MockFilterChain chain = new MockFilterChain(); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_UNAUTHORIZED,response.getStatus()); String tmp = response.getHeader("WWW-Authenticate"); assertNotNull(tmp); assert(tmp.indexOf(GeoServerSecurityManager.REALM) !=-1 ); assert(tmp.indexOf("Digest") !=-1 ); assertNull(SecurityContextHolder.getContext().getAuthentication()); // test successful login for digest request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); String headerValue=clientDigestString(tmp, testUserName, testPassword, request.getMethod()); request.addHeader("Authorization", headerValue); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); Authentication auth = getAuth(testFilterName2, testUserName, 300,300); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); // check success for basic authentication request= createRequest("/foo/bar"); response= new MockHttpServletResponse(); chain = new MockFilterChain(); request.addHeader("Authorization", "Basic " + new String(Base64.encodeBytes((testUserName+":"+testPassword).getBytes()))); getProxy().doFilter(request, response, chain); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); auth = getAuth(testFilterName, testUserName, null,null); assertNotNull(auth); assertNull(SecurityContextHolder.getContext().getAuthentication()); checkForAuthenticatedRole(auth); assertEquals(testUserName, ((UserDetails) auth.getPrincipal()).getUsername()); assertTrue(auth.getAuthorities().contains(new GeoServerRole(rootRole))); assertTrue(auth.getAuthorities().contains(new GeoServerRole(derivedRole))); } }