/** * Create an authenticated connection to the Oozie server. * * <p>It uses Hadoop-auth client authentication which by default supports Kerberos HTTP SPNEGO, * Pseudo/Simple and anonymous. * * <p>if the Java system property {@link #USE_AUTH_TOKEN_CACHE_SYS_PROP} is set to true * Hadoop-auth authentication token will be cached/used in/from the '.oozie-auth-token' file in * the user home directory. * * @param url the URL to open a HTTP connection to. * @param method the HTTP method for the HTTP connection. * @return an authenticated connection to the Oozie server. * @throws IOException if an IO error occurred. * @throws OozieClientException if an oozie client error occurred. */ @Override protected HttpURLConnection createConnection(URL url, String method) throws IOException, OozieClientException { boolean useAuthFile = System.getProperty(USE_AUTH_TOKEN_CACHE_SYS_PROP, "false").equalsIgnoreCase("true"); AuthenticatedURL.Token readToken = new AuthenticatedURL.Token(); AuthenticatedURL.Token currentToken = new AuthenticatedURL.Token(); if (useAuthFile) { readToken = readAuthToken(); if (readToken != null) { currentToken = new AuthenticatedURL.Token(readToken.toString()); } } if (currentToken.isSet()) { HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("OPTIONS"); AuthenticatedURL.injectToken(conn, currentToken); if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED) { AUTH_TOKEN_CACHE_FILE.delete(); currentToken = new AuthenticatedURL.Token(); } } if (!currentToken.isSet()) { Authenticator authenticator = getAuthenticator(); try { new AuthenticatedURL(authenticator).openConnection(url, currentToken); } catch (AuthenticationException ex) { AUTH_TOKEN_CACHE_FILE.delete(); throw new OozieClientException( OozieClientException.AUTHENTICATION, "Could not authenticate, " + ex.getMessage(), ex); } } if (useAuthFile && !currentToken.equals(readToken)) { writeAuthToken(currentToken); } HttpURLConnection conn = super.createConnection(url, method); AuthenticatedURL.injectToken(conn, currentToken); return conn; }
/** * If the request has a valid authentication token it allows the request to continue to the target * resource, otherwise it triggers an authentication sequence using the configured {@link * AuthenticationHandler}. * * @param request the request object. * @param response the response object. * @param filterChain the filter chain object. * @throws IOException thrown if an IO error occurred. * @throws ServletException thrown if a processing error occurred. */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { boolean unauthorizedResponse = true; int errCode = HttpServletResponse.SC_UNAUTHORIZED; AuthenticationException authenticationEx = null; HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; boolean isHttps = "https".equals(httpRequest.getScheme()); try { boolean newToken = false; AuthenticationToken token; try { token = getToken(httpRequest); } catch (AuthenticationException ex) { LOG.warn("AuthenticationToken ignored: " + ex.getMessage()); // will be sent back in a 401 unless filter authenticates authenticationEx = ex; token = null; } if (authHandler.managementOperation(token, httpRequest, httpResponse)) { if (token == null) { if (LOG.isDebugEnabled()) { LOG.debug("Request [{}] triggering authentication", getRequestURL(httpRequest)); } token = authHandler.authenticate(httpRequest, httpResponse); if (token != null && token.getExpires() != 0 && token != AuthenticationToken.ANONYMOUS) { token.setExpires(System.currentTimeMillis() + getValidity() * 1000); } newToken = true; } if (token != null) { unauthorizedResponse = false; if (LOG.isDebugEnabled()) { LOG.debug( "Request [{}] user [{}] authenticated", getRequestURL(httpRequest), token.getUserName()); } final AuthenticationToken authToken = token; httpRequest = new HttpServletRequestWrapper(httpRequest) { @Override public String getAuthType() { return authToken.getType(); } @Override public String getRemoteUser() { return authToken.getUserName(); } @Override public Principal getUserPrincipal() { return (authToken != AuthenticationToken.ANONYMOUS) ? authToken : null; } }; if (newToken && !token.isExpired() && token != AuthenticationToken.ANONYMOUS) { String signedToken = signer.sign(token.toString()); createAuthCookie( httpResponse, signedToken, getCookieDomain(), getCookiePath(), token.getExpires(), isHttps); } filterChain.doFilter(httpRequest, httpResponse); } } else { unauthorizedResponse = false; } } catch (AuthenticationException ex) { // exception from the filter itself is fatal errCode = HttpServletResponse.SC_FORBIDDEN; authenticationEx = ex; LOG.warn("Authentication exception: " + ex.getMessage(), ex); } if (unauthorizedResponse) { if (!httpResponse.isCommitted()) { createAuthCookie(httpResponse, "", getCookieDomain(), getCookiePath(), 0, isHttps); if (authenticationEx == null) { httpResponse.sendError(errCode, "Authentication required"); } else { httpResponse.sendError(errCode, authenticationEx.getMessage()); } } } }