/** * */ package org.minnal.security.filter; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.Cookie; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.NewCookie; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.minnal.security.auth.JaxrsWebContext; import org.minnal.security.auth.User; import org.minnal.security.config.SecurityConfiguration; import org.minnal.security.session.Session; import org.minnal.security.session.SessionStore; import org.pac4j.core.client.Clients; import org.pac4j.core.exception.RequiresHttpAction; import org.pac4j.core.exception.TechnicalException; import org.pac4j.http.client.BasicAuthClient; import org.pac4j.http.profile.HttpProfile; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** * @author ganeshs * */ public class AuthenticationFilterTest { private AuthenticationFilter filter; private Clients clients; private SecurityConfiguration configuration; private ContainerRequestContext context; private UriInfo uriInfo; private SessionStore sessionStore; private BasicAuthClient basicClient; @BeforeMethod public void setup() { basicClient = mock(BasicAuthClient.class); when(basicClient.getName()).thenReturn("client1"); clients = new Clients("/callback", basicClient); sessionStore = mock(SessionStore.class); configuration = mock(SecurityConfiguration.class); when(configuration.getSessionStore()).thenReturn(sessionStore); filter = spy(new AuthenticationFilter(clients, configuration)); context = mock(ContainerRequestContext.class); uriInfo = mock(UriInfo.class); when(uriInfo.getPath()).thenReturn("/dummy"); when(context.getUriInfo()).thenReturn(uriInfo); } @Test public void shouldReturnTrueIfWhiteListedUrl() { when(configuration.getWhiteListedUrls()).thenReturn(Lists.newArrayList("/dummy", "/dummy1")); assertTrue(filter.isWhiteListed(context)); } @Test public void shouldReturnFalseIfWhiteNotListedUrl() { when(configuration.getWhiteListedUrls()).thenReturn(Lists.newArrayList("/dummy2", "/dummy1")); assertFalse(filter.isWhiteListed(context)); } @Test public void shouldReturnTrueForWhiteListedUrlWithParams() { when(configuration.getWhiteListedUrls()).thenReturn(Lists.newArrayList("/dummy", "/dummy1")); when(uriInfo.getPath()).thenReturn("/dummy?key=value"); assertTrue(filter.isWhiteListed(context)); } @Test public void shouldCreateSessionIfAuthCookieIsNotFound() { when(context.getCookies()).thenReturn(Maps.<String, Cookie>newHashMap()); Session session = mock(Session.class); when(sessionStore.createSession(any(String.class))).thenReturn(session); assertEquals(filter.getSession(context, true), session); } @Test public void shouldNotCreateSessionIfAuthCookieIsNotFoundAndCreateIsFalse() { when(context.getCookies()).thenReturn(Maps.<String, Cookie>newHashMap()); Session session = mock(Session.class); when(sessionStore.createSession(any(String.class))).thenReturn(session); assertNull(filter.getSession(context, false)); } @Test public void shouldCreateSessionIfAuthCookieIsFoundButSessionNotFound() { Map<String, Cookie> cookies = new HashMap<String, Cookie>(); String sessionId = UUID.randomUUID().toString(); cookies.put(AuthenticationFilter.AUTH_COOKIE, new Cookie(AuthenticationFilter.AUTH_COOKIE, sessionId)); when(context.getCookies()).thenReturn(cookies); Session session = mock(Session.class); when(sessionStore.getSession(sessionId)).thenReturn(null); when(sessionStore.createSession(any(String.class))).thenReturn(session); assertEquals(filter.getSession(context, true), session); verify(sessionStore).getSession(sessionId); } @Test public void shouldCreateSessionIfAuthCookieIsFoundButSessionHasExpired() { when(configuration.getSessionExpiryTimeInSecs()).thenReturn(100L); Map<String, Cookie> cookies = new HashMap<String, Cookie>(); String sessionId = UUID.randomUUID().toString(); cookies.put(AuthenticationFilter.AUTH_COOKIE, new Cookie(AuthenticationFilter.AUTH_COOKIE, sessionId)); when(context.getCookies()).thenReturn(cookies); Session expiredSession = mock(Session.class); Session session = mock(Session.class); when(expiredSession.hasExpired(100)).thenReturn(true); when(sessionStore.getSession(sessionId)).thenReturn(expiredSession); when(sessionStore.createSession(any(String.class))).thenReturn(session); assertEquals(filter.getSession(context, true), session); verify(sessionStore).getSession(sessionId); } @Test public void shouldReturnSessionIfAlreadySetToRequestProperty() { Session session = mock(Session.class); when(context.getProperty(AuthenticationFilter.SESSION)).thenReturn(session); assertEquals(filter.getSession(context, true), session); verify(sessionStore, never()).createSession(any(String.class)); } @Test public void shouldReturnSessionIfAuthCookieIsFoundAndSessionHasNotExpired() { when(configuration.getSessionExpiryTimeInSecs()).thenReturn(100L); Map<String, Cookie> cookies = new HashMap<String, Cookie>(); String sessionId = UUID.randomUUID().toString(); cookies.put(AuthenticationFilter.AUTH_COOKIE, new Cookie(AuthenticationFilter.AUTH_COOKIE, sessionId)); when(context.getCookies()).thenReturn(cookies); Session session = mock(Session.class); when(session.hasExpired(100)).thenReturn(false); when(sessionStore.getSession(sessionId)).thenReturn(session); assertEquals(filter.getSession(context, true), session); verify(sessionStore, never()).createSession(any(String.class)); } @Test public void shouldReturnNullFromRequestContextIfClientNameAttributeIsNotSet() { JaxrsWebContext context = mock(JaxrsWebContext.class); when(context.getRequestParameter(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn(null); assertNull(filter.getClient(context)); } @Test public void shouldThrowExceptionIfClientNameIsNotFoundInRequestContext() { JaxrsWebContext context = mock(JaxrsWebContext.class); when(context.getRequestParameter(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn("unknownClient"); assertNull(filter.getClient(context)); } @Test public void shouldGetClientFromRequestContextIfClientNameAttributeIsSet() { JaxrsWebContext context = mock(JaxrsWebContext.class); when(context.getRequestParameter(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn("client1"); assertEquals(filter.getClient(context), basicClient); } @Test public void shouldGetClientFromSessionIfClientNameAttributeIsSet() { Session session = mock(Session.class); when(session.getAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn("client1"); assertEquals(filter.getClient(session), basicClient); } @Test public void shouldReturnNullClientFromSessionIfClientNameAttributeIsNotSet() { Session session = mock(Session.class); when(session.getAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn(null); assertNull(filter.getClient(session)); } @Test(expectedExceptions=TechnicalException.class) public void shouldThrowExceptionIfClientNameIsNotFoundInSession() { Session session = mock(Session.class); when(session.getAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER)).thenReturn("unknownClient"); filter.getClient(session); } @Test public void shouldReturnNullProfileIfNotFoundInSession() { Session session = mock(Session.class); when(session.getAttribute(AuthenticationFilter.PRINCIPAL)).thenReturn(null); assertNull(filter.retrieveProfile(session)); } @Test public void shouldReturnProfileIfFoundInSession() { Session session = mock(Session.class); HttpProfile profile = mock(HttpProfile.class); when(session.getAttribute(AuthenticationFilter.PRINCIPAL)).thenReturn(profile); doReturn(basicClient).when(filter).getClient(session); User user = filter.retrieveProfile(session); assertEquals(user.getProfile(), profile); } @Test public void shouldDeserializeProfileIfFoundInSessionAsMap() { Session session = mock(Session.class); Map<String, Object> profile = new HashMap<String, Object>(); profile.put("id", "dummy"); when(session.getAttribute(AuthenticationFilter.PRINCIPAL)).thenReturn(profile); doReturn(basicClient).when(filter).getClient(session); User user = filter.retrieveProfile(session); assertEquals(user.getProfile().getId(), "dummy"); } @Test public void shouldReturnTrueIfAlreadyAuthenticated() { Session session = mock(Session.class); doReturn(mock(User.class)).when(filter).retrieveProfile(session); assertTrue(filter.isAuthenticated(session)); } @Test public void shouldReturnFalseIfNotAlreadyAuthenticated() { Session session = mock(Session.class); doReturn(null).when(filter).retrieveProfile(session); assertFalse(filter.isAuthenticated(session)); } @Test public void shouldNotFilterWhiteListedUrls() { doReturn(true).when(filter).isWhiteListed(context); filter.filter(context); verify(filter).getSession(context, true); verify(filter, never()).getContext(eq(context), any(Session.class)); } @Test public void shouldFilterIfAlreadyAuthenticated() { Session session = mock(Session.class); doReturn(true).when(filter).isAuthenticated(session); doReturn(session).when(filter).getSession(context, true); filter.filter(context); verify(context, never()).abortWith(any(Response.class)); } @Test public void shouldReturnUnauthorizedIfClientNameIsNotSet() { Session session = mock(Session.class); Response response = mock(Response.class); JaxrsWebContext webContext = mock(JaxrsWebContext.class); when(webContext.getResponse()).thenReturn(response); doReturn(false).when(filter).isAuthenticated(session); doReturn(session).when(filter).getSession(context, true); doReturn(webContext).when(filter).getContext(context, session); filter.filter(context); verify(webContext).setResponseStatus(Response.Status.UNAUTHORIZED.getStatusCode()); verify(context).abortWith(response); } @Test public void shouldSetClientNameParamInSessionIfNotAuthenticated() throws RequiresHttpAction { Session session = mock(Session.class); Response response = mock(Response.class); JaxrsWebContext webContext = mock(JaxrsWebContext.class); when(webContext.getResponse()).thenReturn(response); doReturn(basicClient).when(filter).getClient(webContext); doReturn(false).when(filter).isAuthenticated(session); doReturn(session).when(filter).getSession(context, true); doReturn(webContext).when(filter).getContext(context, session); filter.filter(context); verify(session).addAttribute(Clients.DEFAULT_CLIENT_NAME_PARAMETER, "client1"); verify(sessionStore).save(session); } @Test public void shouldRedirectIfClientNameIsSet() throws RequiresHttpAction { Session session = mock(Session.class); when(session.getId()).thenReturn(UUID.randomUUID().toString()); Response response = mock(Response.class); JaxrsWebContext webContext = mock(JaxrsWebContext.class); when(webContext.getResponse()).thenReturn(response); doNothing().when(basicClient).redirect(webContext, false, false); doReturn(basicClient).when(filter).getClient(webContext); doReturn(false).when(filter).isAuthenticated(session); doReturn(session).when(filter).getSession(context, true); doReturn(webContext).when(filter).getContext(context, session); filter.filter(context); verify(basicClient).redirect(webContext, false, false); verify(webContext, atLeast(1)).setResponseHeader(eq(HttpHeaders.LOCATION), any(String.class)); verify(webContext).setResponseHeader(HttpHeaders.SET_COOKIE, new NewCookie(AuthenticationFilter.AUTH_COOKIE, session.getId(), "/", null, null, NewCookie.DEFAULT_MAX_AGE, false).toString()); verify(context).abortWith(response); } }