/** * Jetty has a bug in which if there is an Authorization header sent by a client which is * not of the Negotiate type, Jetty does not send the challenge to negotiate. This works * around that issue, forcing the challenge to be sent. Will require investigation on * upgrade to a newer version of Jetty. */ Authentication sendChallengeIfNecessary(Authentication computedAuth, ServletRequest request, ServletResponse response) throws IOException { if (computedAuth == Authentication.UNAUTHENTICATED) { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; String header = req.getHeader(HttpHeader.AUTHORIZATION.asString()); // We have an authorization header, but it's not Negotiate if (header != null && !header.startsWith(HttpHeader.NEGOTIATE.asString())) { LOG.debug("Client sent Authorization header that was not for Negotiate," + " sending challenge anyways."); if (DeferredAuthentication.isDeferred(res)) { return Authentication.UNAUTHENTICATED; } res.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString()); res.sendError(HttpServletResponse.SC_UNAUTHORIZED); return Authentication.SEND_CONTINUE; } } return computedAuth; }
/** * Test to verify response when request is sent for {@link WebServerConstants#SPENGO_LOGIN_RESOURCE_PATH} from * unauthenticated session. Expectation is client will receive response with Negotiate header. * @throws Exception */ @Test public void testNewSessionReqForSpnegoLogin() throws Exception { final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); final HttpServletResponse response = Mockito.mock(HttpServletResponse.class); final HttpSession session = Mockito.mock(HttpSession.class); Mockito.when(request.getSession(true)).thenReturn(session); Mockito.when(request.getRequestURI()).thenReturn(WebServerConstants.SPENGO_LOGIN_RESOURCE_PATH); final Authentication authentication = spnegoAuthenticator.validateRequest(request, response, false); assertEquals(authentication, Authentication.SEND_CONTINUE); verify(response).sendError(401); verify(response).setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString()); }
/** * Test to verify response when request is sent for {@link WebServerConstants#SPENGO_LOGIN_RESOURCE_PATH} from * authenticated session. Expectation is server will find the authenticated UserIdentity. * @throws Exception */ @Test public void testAuthClientRequestForSpnegoLoginResource() throws Exception { final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); final HttpServletResponse response = Mockito.mock(HttpServletResponse.class); final HttpSession session = Mockito.mock(HttpSession.class); final Authentication authentication = Mockito.mock(UserAuthentication.class); Mockito.when(request.getSession(true)).thenReturn(session); Mockito.when(request.getRequestURI()).thenReturn(WebServerConstants.SPENGO_LOGIN_RESOURCE_PATH); Mockito.when(session.getAttribute(SessionAuthentication.__J_AUTHENTICATED)).thenReturn(authentication); final UserAuthentication returnedAuthentication = (UserAuthentication) spnegoAuthenticator.validateRequest (request, response, false); assertEquals(authentication, returnedAuthentication); verify(response, never()).sendError(401); verify(response, never()).setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString()); }
/** * Test to verify response when request is sent for any other resource other than * {@link WebServerConstants#SPENGO_LOGIN_RESOURCE_PATH} from authenticated session. Expectation is server will * find the authenticated UserIdentity and will not perform the authentication again for new resource. * @throws Exception */ @Test public void testAuthClientRequestForOtherPage() throws Exception { final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); final HttpServletResponse response = Mockito.mock(HttpServletResponse.class); final HttpSession session = Mockito.mock(HttpSession.class); final Authentication authentication = Mockito.mock(UserAuthentication.class); Mockito.when(request.getSession(true)).thenReturn(session); Mockito.when(request.getRequestURI()).thenReturn(WebServerConstants.WEBSERVER_ROOT_PATH); Mockito.when(session.getAttribute(SessionAuthentication.__J_AUTHENTICATED)).thenReturn(authentication); final UserAuthentication returnedAuthentication = (UserAuthentication) spnegoAuthenticator.validateRequest (request, response, false); assertEquals(authentication, returnedAuthentication); verify(response, never()).sendError(401); verify(response, never()).setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString()); }
/** * Test to verify that when request is sent for {@link WebServerConstants#LOGOUT_RESOURCE_PATH} then the UserIdentity * will be removed from the session and returned authentication will be null from * {@link DrillSpnegoAuthenticator#validateRequest(ServletRequest, ServletResponse, boolean)} * @throws Exception */ @Test public void testAuthClientRequestForLogOut() throws Exception { final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); final HttpServletResponse response = Mockito.mock(HttpServletResponse.class); final HttpSession session = Mockito.mock(HttpSession.class); final Authentication authentication = Mockito.mock(UserAuthentication.class); Mockito.when(request.getSession(true)).thenReturn(session); Mockito.when(request.getRequestURI()).thenReturn(WebServerConstants.LOGOUT_RESOURCE_PATH); Mockito.when(session.getAttribute(SessionAuthentication.__J_AUTHENTICATED)).thenReturn(authentication); final UserAuthentication returnedAuthentication = (UserAuthentication) spnegoAuthenticator.validateRequest (request, response, false); assertNull(returnedAuthentication); verify(session).removeAttribute(SessionAuthentication.__J_AUTHENTICATED); verify(response, never()).sendError(401); verify(response, never()).setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString()); }
@Override public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { Authentication result = super.validateRequest(request, response, mandatory); if ((result == Authentication.UNAUTHENTICATED) && mandatory && !DeferredAuthentication.isDeferred((HttpServletResponse)response)) { LOG.debug("SpengoAuthenticatorEx: unauthenticated -> forbidden"); try { ((HttpServletResponse)response).sendError(Response.SC_FORBIDDEN, "negotiation failure"); } catch (IOException ex) { throw new ServerAuthException(ex); } result = Authentication.SEND_FAILURE; } return result; }
Authentication validateRequestDelegation(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { Authenticator auth = userAuthenticator; HttpServletRequest httpReq = (HttpServletRequest) request; boolean isRestCall = httpReq.getHeader(SSOConstants.X_REST_CALL) != null; boolean isAppCall = httpReq.getHeader(SSOConstants.X_APP_AUTH_TOKEN) != null || httpReq.getHeader(SSOConstants.X_APP_COMPONENT_ID) != null; if (isAppCall && isRestCall) { auth = appAuthenticator; if (getLog().isTraceEnabled()) { getLog().trace("App request '{}'", getRequestInfoForLogging(httpReq, "?")); } } else { if (getLog().isTraceEnabled()) { getLog().trace("User request '{}'", getRequestInfoForLogging(httpReq, "?")); } } return auth.validateRequest(request, response, mandatory); }
protected Authentication returnUnauthorized( HttpServletRequest httpReq, HttpServletResponse httpRes, Map errorReason, String principalId, String logMessageTemplate ) throws ServerAuthException { if (getLog().isDebugEnabled()) { getLog().debug(logMessageTemplate, getRequestInfoForLogging(httpReq, principalId)); } try { httpRes.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), "dpm"); httpRes.setStatus(HttpServletResponse.SC_UNAUTHORIZED); httpRes.setContentType("application/json"); OBJECT_MAPPER.writeValue(httpRes.getWriter(), errorReason); return Authentication.SEND_FAILURE; } catch (IOException ex) { throw new ServerAuthException(Utils.format("Could send a Unauthorized (401) response: {}", ex.toString(), ex)); } }
@Test public void testReturnForbidden() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); AbstractSSOAuthenticator authenticator = new ForTestSSOAuthenticator(ssoService); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); Mockito.when(req.getRequestURL()).thenReturn(new StringBuffer("url")); Mockito.when(req.getRemoteAddr()).thenReturn("remoteAddress"); Mockito.when(req.getMethod()).thenReturn("method"); Mockito.when(req.getQueryString()).thenReturn("QS"); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); Mockito.when(res.getWriter()).thenReturn(printWriter); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.returnUnauthorized(req, res, "principal", "template")); ArgumentCaptor<Integer> error = ArgumentCaptor.forClass(Integer.class); Mockito.verify(res).setStatus(error.capture()); Assert.assertEquals( SSOUserAuthenticator.UNAUTHORIZED_JSON, new ObjectMapper().readValue(writer.toString().trim(), Map.class) ); Mockito.verify(res).setContentType(Mockito.eq("application/json")); }
@Test public void testRedirectToSelf() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = new SSOUserAuthenticator(ssoService, null); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); Mockito.when(req.getRequestURL()).thenReturn(new StringBuffer("http://foo/bar")); Mockito.when(req.getQueryString()).thenReturn("a=A&b=B&" + SSOConstants.USER_AUTH_TOKEN_PARAM + "=token"); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Assert.assertEquals(Authentication.SEND_CONTINUE, authenticator.redirectToSelf(req, res)); ArgumentCaptor<String> redirect = ArgumentCaptor.forClass(String.class); Mockito.verify(res).sendRedirect(redirect.capture()); Assert.assertEquals("http://foo/bar?a=A&b=B", redirect.getValue()); }
@Test public void testreturnUnauthorized() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); ssoService.setConfiguration(new Configuration()); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); Mockito .doReturn("http://foo") .when(authenticator) .getLoginUrl(Mockito.any(HttpServletRequest.class), Mockito.anyBoolean()); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); Mockito.when(req.getServerPort()).thenReturn(1000); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(res.getWriter()).thenReturn(new PrintWriter(new StringWriter())); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.returnUnauthorized(req, res, "principal", "template")); Mockito.verify(authenticator).redirectToLogin(Mockito.eq(req), Mockito.eq(res)); ArgumentCaptor<Cookie> cookieCaptor = ArgumentCaptor.forClass(Cookie.class); Mockito.verify(authenticator, Mockito.times(1)).createAuthCookie(Mockito.eq(req), Mockito.eq(""), Mockito.eq(0L)); Mockito.verify(res, Mockito.times(1)).addCookie(cookieCaptor.capture()); Assert.assertEquals(authenticator.getAuthCookieName(req), cookieCaptor.getValue().getName()); Assert.assertEquals("", cookieCaptor.getValue().getValue()); Assert.assertEquals("/", cookieCaptor.getValue().getPath()); Assert.assertEquals(0, cookieCaptor.getValue().getMaxAge()); }
@Test public void testreturnUnauthorizedREST() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); Mockito .doReturn("http://foo") .when(authenticator) .getLoginUrl(Mockito.any(HttpServletRequest.class), Mockito.anyBoolean()); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn("foo"); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(res.getWriter()).thenReturn(new PrintWriter(new StringWriter())); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.returnUnauthorized(req, res, "principal", "template")); Mockito.verify(res).setContentType(Mockito.eq("application/json")); }
@Test public void testValidateRequestMandatoryInvalidAuthToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.doReturn("token").when(authenticator).getAuthTokenFromRequest(Mockito.eq(req)); Mockito.doReturn(Authentication.SEND_FAILURE).when(authenticator).returnUnauthorized(Mockito.eq(req), Mockito.eq (res), Mockito.anyString(), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); Mockito.verify(ssoService).validateUserToken(Mockito.eq("token")); Mockito.verifyNoMoreInteractions(ssoService); }
@Test public void testValidateRequestMandatoryNoRESTCall() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = Mockito.spy(new SSOAppAuthenticator(ssoService)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_COMPONENT_ID))).thenReturn("componentId"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn(null); Mockito .doReturn(Authentication.SEND_FAILURE) .when(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.eq("componentId"), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.eq("componentId"), Mockito.anyString()); }
@Test public void testValidateRequestMandatoryNoAuthToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = Mockito.spy(new SSOAppAuthenticator(ssoService)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_COMPONENT_ID))).thenReturn("componentId"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn("foo"); Mockito .doReturn(Authentication.SEND_FAILURE) .when(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.eq("componentId"), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.eq("componentId"), Mockito.anyString()); }
@Test public void testValidateRequestMandatoryNoComponentIdToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = Mockito.spy(new SSOAppAuthenticator(ssoService)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_AUTH_TOKEN))).thenReturn("token"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn("foo"); Mockito .doReturn(Authentication.SEND_FAILURE) .when(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); }
@Test public void testValidateRequestMandatoryInvalidToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = Mockito.spy(new SSOAppAuthenticator(ssoService)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_AUTH_TOKEN))).thenReturn("token"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_COMPONENT_ID))).thenReturn("componentId"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn("foo"); Mockito.when(ssoService.validateAppToken(Mockito.eq("token"), Mockito.eq("componentId"))).thenReturn(null); Mockito .doReturn(Authentication.SEND_FAILURE) .when(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); Mockito.verify(ssoService, Mockito.times(1)).validateAppToken(Mockito.eq("token"), Mockito.eq("componentId")); }
@Test public void testValidateRequestMandatoryValidToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = Mockito.spy(new SSOAppAuthenticator(ssoService)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_AUTH_TOKEN))).thenReturn("token"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_APP_COMPONENT_ID))).thenReturn("componentId"); Mockito.when(req.getHeader(Mockito.eq(SSOConstants.X_REST_CALL))).thenReturn("foo"); Mockito.when(ssoService.validateAppToken(Mockito.eq("token"), Mockito.eq("componentId"))).thenReturn(null); SSOPrincipal principal = Mockito.mock(SSOPrincipal.class); Mockito.when(principal.getTokenStr()).thenReturn("token"); Mockito.when(principal.getExpires()).thenReturn(1L); Mockito.doReturn(principal).when(ssoService).validateAppToken(Mockito.eq("token"), Mockito.eq("componentId")); Authentication auth = authenticator.validateRequest(req, res, true); Assert.assertNotNull(auth); Assert.assertSame(principal, ((SSOAuthenticationUser)auth).getSSOUserPrincipal()); }
@Test public void testCleanDelegationMethods() throws Exception { Authenticator auth = Mockito.mock(Authenticator.class); Activation activation = Mockito.mock(Activation.class); ActivationAuthenticator activationAuth = new ActivationAuthenticator(auth, activation); Authenticator.AuthConfiguration conf = Mockito.mock(Authenticator.AuthConfiguration.class); activationAuth.setConfiguration(conf); Mockito.verify(auth, Mockito.times(1)).setConfiguration(Mockito.eq(conf)); Mockito.when(auth.getAuthMethod()).thenReturn("foo"); Assert.assertEquals("foo", activationAuth.getAuthMethod()); ServletRequest req = Mockito.mock(ServletRequest.class); activationAuth.prepareRequest(req); Mockito.verify(auth, Mockito.times(1)).prepareRequest(Mockito.eq(req)); ServletResponse res = Mockito.mock(ServletResponse.class); Authentication.User user = Mockito.mock(Authentication.User.class); Mockito.when(auth.secureResponse(Mockito.eq(req), Mockito.eq(res), Mockito.eq(true), Mockito.eq(user))) .thenReturn(true); Assert.assertTrue(auth.secureResponse(req, res, true, user)); }
@Override public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { final Authentication computedAuth = super.validateRequest(request, response, mandatory); try { return sendChallengeIfNecessary(computedAuth, request, response); } catch (IOException e) { throw new ServerAuthException(e); } }
@Test public void testAuthenticatedDoesNothingExtra() throws IOException { List<Authentication> authsNotRequiringUpdate = Arrays.asList(Authentication.NOT_CHECKED, Authentication.SEND_CONTINUE, Authentication.SEND_FAILURE, Authentication.SEND_SUCCESS); for (Authentication auth : authsNotRequiringUpdate) { assertEquals(auth, authenticator.sendChallengeIfNecessary(auth, request, response)); verifyZeroInteractions(request); verifyZeroInteractions(response); } }
@Test public void testChallengeSendOnBasicAuthorization() throws IOException { when(request.getHeader("Authorization")).thenReturn("Basic asdf"); assertEquals(Authentication.SEND_CONTINUE, authenticator.sendChallengeIfNecessary(Authentication.UNAUTHENTICATED, request, response)); verify(response).setHeader(HttpHeader.WWW_AUTHENTICATE.toString(), HttpHeader.NEGOTIATE.asString()); verify(response).sendError(HttpServletResponse.SC_UNAUTHORIZED); }
@Override public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Authentication auth = baseRequest.getAuthentication(); if (Authentication.UNAUTHENTICATED == auth) { throw new AssertionError("Unauthenticated users should not reach here!"); } baseRequest.setHandled(true); UserAuthentication userAuth = (UserAuthentication) auth; UserIdentity userIdentity = userAuth.getUserIdentity(); Principal userPrincipal = userIdentity.getUserPrincipal(); response.getWriter().print("OK " + userPrincipal.getName()); response.setStatus(200); }
/** * Updated logic as compared to default implementation in * {@link SpnegoAuthenticator#validateRequest(ServletRequest, ServletResponse, boolean)} to handle below cases: * 1) Perform SPNEGO authentication only when spnegoLogin resource is requested. This helps to avoid authentication * for each and every resource which the JETTY provided authenticator does. * 2) Helps to redirect to the target URL after authentication is done successfully. * 3) Clear-Up in memory session information once LogOut is triggered such that any future request also triggers SPNEGO * authentication. * @param request * @param response * @param mandatoryAuth * @return * @throws ServerAuthException */ @Override public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatoryAuth) throws ServerAuthException { final HttpServletRequest req = (HttpServletRequest) request; final HttpSession session = req.getSession(true); final Authentication authentication = (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED); final String uri = req.getRequestURI(); // If the Request URI is for /spnegoLogin then perform login final boolean mandatory = mandatoryAuth || uri.equals(WebServerConstants.SPENGO_LOGIN_RESOURCE_PATH); // For logout remove the attribute from the session that holds UserIdentity if (authentication != null) { if (uri.equals(WebServerConstants.LOGOUT_RESOURCE_PATH)) { logger.debug("Logging out user {}", req.getRemoteAddr()); session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED); return null; } // Already logged in so just return the session attribute. return authentication; } // Try to authenticate an unauthenticated session. return authenticateSession(request, response, mandatory); }
public UserIdentity login(String username, Object password, ServletRequest request) { final UserIdentity user = super.login(username, password, request); if (user != null) { final HttpSession session = ((HttpServletRequest) request).getSession(true); final Authentication cached = new SessionAuthentication(this.getAuthMethod(), user, password); session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached); } return user; }
@Override public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException { HttpServletRequest request = ((HttpServletRequest) req); request.setAttribute(HttpServletRequest.class.getName(), request); if (getAdapterConfig().isBearerOnly() == false && request.getQueryString() != null && request.getQueryString().contains("code=")) { // we receive a code as part of the query string that is returned by OAuth // but only assume control is this is not bearer only! mandatory = true; } else if (request.getHeaders("Authorization").hasMoreElements()) { // we receive Authorization, might be Bearer or Basic Auth (both supported by Keycloak) mandatory = true; } HttpSession session = ((HttpServletRequest) req).getSession(false); if (session != null && session.getAttribute(JettyAdapterSessionStore.CACHED_FORM_PARAMETERS) != null) { // this is a redirect after the code has been received for a FORM mandatory = true; } else if (session != null && session.getAttribute(KeycloakSecurityContext.class.getName()) != null) { // there is an existing authentication in the session, use it mandatory = true; } Authentication authentication = super.validateRequest(req, res, mandatory); if (authentication instanceof DeferredAuthentication) { // resolving of a deferred authentication later will otherwise lead to a NullPointerException authentication = null; } return authentication; }
Authentication redirectToSelf(HttpServletRequest httpReq, HttpServletResponse httpRes) throws ServerAuthException { String authToken = httpReq.getParameter(SSOConstants.USER_AUTH_TOKEN_PARAM); String urlWithoutToken = getRequestUrlWithoutToken(httpReq); httpRes.setHeader(SSOConstants.X_USER_AUTH_TOKEN, authToken); try { LOG.debug("Redirecting to self without token '{}'", urlWithoutToken); httpRes.sendRedirect(urlWithoutToken); return Authentication.SEND_CONTINUE; } catch (IOException ex) { throw new ServerAuthException(Utils.format("Could not redirect to '{}': {}", urlWithoutToken, ex.toString(), ex)); } }
Authentication redirectToLogin(HttpServletRequest httpReq, HttpServletResponse httpRes) throws ServerAuthException { boolean repeatedRedirect = httpReq.getParameter(SSOConstants.REPEATED_REDIRECT_PARAM) != null; String urlToLogin = getLoginUrl(httpReq, repeatedRedirect); try { LOG.debug("Redirecting to login '{}'", urlToLogin); httpRes.sendRedirect(urlToLogin); return Authentication.SEND_CONTINUE; } catch (IOException ex) { throw new ServerAuthException(Utils.format("Could not redirect to '{}': {}", urlToLogin, ex.toString(), ex)); } }
Authentication redirectToLogout(HttpServletResponse httpRes) throws ServerAuthException { String urlToLogout = getSsoService().getLogoutUrl(); try { LOG.debug("Redirecting to logout '{}'", urlToLogout); httpRes.sendRedirect(urlToLogout); return Authentication.SEND_SUCCESS; } catch (IOException ex) { throw new ServerAuthException(Utils.format("Could not redirect to '{}': {}", urlToLogout, ex.toString(), ex)); } }
@Override protected Authentication returnUnauthorized( HttpServletRequest httpReq, HttpServletResponse httpRes, String principalId, String logMessageTemplate ) throws ServerAuthException { Authentication ret; httpRes.addCookie(createAuthCookie(httpReq, "", 0)); if (httpReq.getHeader(SSOConstants.X_REST_CALL) != null) { ret = super.returnUnauthorized(httpReq, httpRes, null, logMessageTemplate); } else { redirectToLogin(httpReq, httpRes); ret = Authentication.SEND_FAILURE; } return ret; }
@Override public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { SSOPrincipalJson.resetRequestIpAddress(); Authentication authentication = validateRequestDelegation(request, response, mandatory); if (authentication instanceof SSOAuthenticationUser) { // if the Authentication is an authenticated user, we set the IP address of the request in it. SSOPrincipalUtils.setRequestInfo(((SSOAuthenticationUser)authentication).getSSOUserPrincipal(), request); } return authentication; }
@Override public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException { HttpServletRequest httpReq = (HttpServletRequest) request; HttpServletResponse httpRes = (HttpServletResponse) response; Authentication ret; String componentId = getAppComponentId(httpReq); if (!mandatory) { if (LOG.isDebugEnabled()) { LOG.trace("URL '{}' does not require authentication", getRequestInfoForLogging(httpReq, componentId)); } ret = Authentication.NOT_CHECKED; } else { if (((HttpServletRequest) request).getHeader(SSOConstants.X_REST_CALL) == null) { ret = returnUnauthorized(httpReq, httpRes, componentId, "Not a REST call: {}"); } else { String authToken = getAppAuthToken(httpReq); if (authToken == null) { ret = returnUnauthorized(httpReq, httpRes, componentId, "Missing app authentication token: {}"); } else if (componentId == null) { ret = returnUnauthorized(httpReq, httpRes, null, "Missing component ID: {}"); } else { try { SSOPrincipal principal = getSsoService().validateAppToken(authToken, componentId); if (principal != null) { ret = new SSOAuthenticationUser(principal); } else { ret = returnUnauthorized(httpReq, httpRes, componentId, "Invalid app authentication token: {}"); } } catch (ForbiddenException fex) { ret = returnUnauthorized(httpReq, httpRes, fex.getErrorInfo(), componentId, "Request: {}"); } } } } return ret; }
@Test public void testRedirectToLogin() throws Exception { RemoteSSOService ssoService = new RemoteSSOService(); Configuration conf = new Configuration(); conf.set(RemoteSSOService.SECURITY_SERVICE_APP_AUTH_TOKEN_CONFIG, "authToken"); conf.set(RemoteSSOService.SECURITY_SERVICE_COMPONENT_ID_CONFIG, "componentId"); ssoService.setConfiguration(conf); SSOUserAuthenticator authenticator = new SSOUserAuthenticator(ssoService, null); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); Mockito.when(req.getRequestURL()).thenReturn(new StringBuffer("http://foo/bar")); Mockito.when(req.getQueryString()).thenReturn("a=A&b=B"); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Assert.assertEquals(Authentication.SEND_CONTINUE, authenticator.redirectToLogin(req, res)); ArgumentCaptor<String> redirect = ArgumentCaptor.forClass(String.class); Mockito.verify(res).sendRedirect(redirect.capture()); Assert.assertEquals("http://localhost:18631/security/login?" + SSOConstants.REQUESTED_URL_PARAM + "=" + URLEncoder.encode("http://foo/bar?a=A&b=B", "UTF-8"), redirect.getValue()); Mockito.when(req.getRequestURL()).thenReturn(new StringBuffer("http://foo/bar")); Mockito.when(req.getQueryString()).thenReturn("a=A&b=B"); Mockito.reset(res); Mockito.when(req.getQueryString()).thenReturn("a=A&b=B&" + SSOConstants.REPEATED_REDIRECT_PARAM + "=x"); Mockito.when(req.getParameter(Mockito.eq(SSOConstants.REPEATED_REDIRECT_PARAM))).thenReturn("x"); Assert.assertEquals(Authentication.SEND_CONTINUE, authenticator.redirectToLogin(req, res)); redirect = ArgumentCaptor.forClass(String.class); Mockito.verify(res).sendRedirect(redirect.capture()); Assert.assertEquals( "http://localhost:18631/security/login?" + SSOConstants.REQUESTED_URL_PARAM + "=" + URLEncoder.encode("http://foo/bar?a=A&b=B", "UTF-8") + "&" + SSOConstants.REPEATED_REDIRECT_PARAM + "=", redirect.getValue() ); }
@Test public void testRedirectToLogout() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); Mockito.when(ssoService.getLogoutUrl()).thenReturn("http://foo/logout"); SSOUserAuthenticator authenticator = new SSOUserAuthenticator(ssoService, null); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Authentication auth = authenticator.redirectToLogout(res); Assert.assertEquals(Authentication.SEND_SUCCESS, auth); Mockito.verify(res).sendRedirect(Mockito.eq(ssoService.getLogoutUrl())); }
@Test public void testValidateRequestNotMandatory() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Assert.assertEquals(Authentication.NOT_CHECKED, authenticator.validateRequest(req, res, false)); }
@Test public void testValidateRequestMandatoryNoAuthToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.doReturn(Authentication.SEND_FAILURE).when(authenticator).returnUnauthorized(Mockito.eq(req), Mockito.eq (res), Mockito.anyString(), Mockito.anyString()); Assert.assertEquals(Authentication.SEND_FAILURE, authenticator.validateRequest(req, res, true)); Mockito .verify(authenticator) .returnUnauthorized(Mockito.eq(req), Mockito.eq(res), Mockito.anyString(), Mockito.anyString()); Mockito.verifyNoMoreInteractions(ssoService); }
@Test public void testValidateRequestMandatoryValidAuthToken() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.doReturn("token").when(authenticator).getAuthTokenFromRequest(Mockito.eq(req)); SSOPrincipal principal = Mockito.mock(SSOPrincipal.class); Mockito.when(principal.getTokenStr()).thenReturn("token"); Mockito.when(principal.getExpires()).thenReturn(1L); Mockito.doReturn(principal).when(ssoService).validateUserToken(Mockito.eq("token")); Mockito.doReturn(false).when(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito.doNothing().when(authenticator).setAuthCookieIfNecessary(Mockito.eq(req), Mockito.eq(res), Mockito.eq ("token"), Mockito.eq(1)); Mockito.doReturn(false).when(authenticator).isAuthTokenInQueryString(Mockito.eq(req)); Authentication auth = authenticator.validateRequest(req, res, true); Assert.assertNotNull(auth); Assert.assertSame(principal, ((SSOAuthenticationUser)auth).getSSOUserPrincipal()); Mockito.verify(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito .verify(authenticator) .setAuthCookieIfNecessary(Mockito.eq(req), Mockito.eq(res), Mockito.eq("token"), Mockito.eq(1L)); Mockito.verify(authenticator).isAuthTokenInQueryString(Mockito.eq(req)); Mockito.verify(ssoService).validateUserToken(Mockito.eq("token")); Mockito.verifyNoMoreInteractions(ssoService); }
@Test public void testValidateRequestMandatoryValidAuthTokenWithTokenInQueryString() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.doReturn("token").when(authenticator).getAuthTokenFromRequest(Mockito.eq(req)); SSOPrincipal principal = Mockito.mock(SSOPrincipal.class); Mockito.when(principal.getTokenStr()).thenReturn("token"); Mockito.when(principal.getExpires()).thenReturn(1L); Mockito.doReturn(principal).when(ssoService).validateUserToken(Mockito.eq("token")); Mockito.doReturn(false).when(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito.doNothing().when(authenticator).setAuthCookieIfNecessary(Mockito.eq(req), Mockito.eq(res), Mockito.eq ("token"), Mockito.eq(1)); Mockito.doReturn(Authentication.SEND_CONTINUE).when(authenticator).redirectToSelf(Mockito.eq(req), Mockito.eq(res)); Mockito.doReturn(true).when(authenticator).isAuthTokenInQueryString(Mockito.eq(req)); Authentication auth = authenticator.validateRequest(req, res, true); Assert.assertNotNull(auth); Assert.assertSame(Authentication.SEND_CONTINUE, auth); Mockito.verify(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito .verify(authenticator) .setAuthCookieIfNecessary(Mockito.eq(req), Mockito.eq(res), Mockito.eq("token"), Mockito.eq(1L)); Mockito.verify(authenticator).isAuthTokenInQueryString(Mockito.eq(req)); Mockito.verify(ssoService).validateUserToken(Mockito.eq("token")); Mockito.verifyNoMoreInteractions(ssoService); Mockito.verify(authenticator).redirectToSelf(Mockito.eq(req), Mockito.eq(res)); }
@Test public void testValidateRequestMandatoryValidAuthTokenLogoutRequest() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOUserAuthenticator authenticator = Mockito.spy(new SSOUserAuthenticator(ssoService, null)); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Mockito.doReturn("token").when(authenticator).getAuthTokenFromRequest(Mockito.eq(req)); SSOPrincipal principal = Mockito.mock(SSOPrincipal.class); Mockito.when(principal.getTokenStr()).thenReturn("token"); Mockito.when(principal.getExpires()).thenReturn(1L); Mockito.doReturn(principal).when(ssoService).validateUserToken(Mockito.eq("token")); Mockito.doReturn(true).when(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito.doReturn(Authentication.SEND_SUCCESS).when(authenticator).redirectToLogout(Mockito.eq(res)); Authentication auth = authenticator.validateRequest(req, res, true); Assert.assertNotNull(auth); Assert.assertSame(Authentication.SEND_SUCCESS, auth); Mockito.verify(authenticator).isLogoutRequest(Mockito.eq(req)); Mockito .verify(authenticator, Mockito.times(0)) .setAuthCookieIfNecessary(Mockito.eq(req), Mockito.eq(res), Mockito.eq("token"), Mockito.eq(1L)); Mockito.verify(ssoService).validateUserToken(Mockito.eq("token")); Mockito.verify(ssoService, Mockito.times(1)).invalidateUserToken(Mockito.eq("token")); }
@Test public void testValidateRequestNotMandatory() throws Exception { SSOService ssoService = Mockito.mock(SSOService.class); SSOAppAuthenticator authenticator = new SSOAppAuthenticator(ssoService); HttpServletRequest req = Mockito.mock(HttpServletRequest.class); HttpServletResponse res = Mockito.mock(HttpServletResponse.class); Assert.assertEquals(Authentication.NOT_CHECKED, authenticator.validateRequest(req, res, false)); }