Repository: knox Updated Branches: refs/heads/master fb2e31348 -> efc361ddc
KNOX-938 - JWTProvider to accept Query Param as well as Bearer Token Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/efc361dd Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/efc361dd Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/efc361dd Branch: refs/heads/master Commit: efc361ddc97209a2d87f69018701dbcc5a3450fc Parents: fb2e313 Author: Larry McCay <[email protected]> Authored: Sat May 13 12:47:03 2017 -0400 Committer: Larry McCay <[email protected]> Committed: Sat May 13 12:47:03 2017 -0400 ---------------------------------------------------------------------- .../jwt/filter/JWTFederationFilter.java | 91 +++++++++++++------- 1 file changed, 61 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/efc361dd/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java ---------------------------------------------------------------------- diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java index 33af374..9facd30 100644 --- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java +++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java @@ -46,9 +46,11 @@ import java.util.Set; public class JWTFederationFilter extends AbstractJWTFilter { public static final String KNOX_TOKEN_AUDIENCES = "knox.token.audiences"; + private static final String KNOX_TOKEN_QUERY_PARAM_NAME = "knox.token.query.param.name"; private static final String BEARER = "Bearer "; private static JWTMessages log = MessagesFactory.get( JWTMessages.class ); private JWTokenAuthority authority = null; + private String paramName = "knoxtoken"; @Override public void init( FilterConfig filterConfig ) throws ServletException { @@ -60,6 +62,13 @@ public class JWTFederationFilter extends AbstractJWTFilter { if (expectedAudiences != null) { audiences = parseExpectedAudiences(expectedAudiences); } + + // query param name for finding the provided knoxtoken + String queryParamName = filterConfig.getInitParameter(KNOX_TOKEN_QUERY_PARAM_NAME); + if (queryParamName != null) { + paramName = queryParamName; + } + } public void destroy() { @@ -71,51 +80,73 @@ public class JWTFederationFilter extends AbstractJWTFilter { if (header != null && header.startsWith(BEARER)) { // what follows the bearer designator should be the JWT token being used to request or as an access token String wireToken = header.substring(BEARER.length()); - JWTToken token; - token = new JWTToken(wireToken); - boolean verified = false; - try { - verified = authority.verifyToken(token); - } catch (TokenServiceException e) { - log.unableToVerifyToken(e); + JWTToken token = new JWTToken(wireToken); + if (validateToken(request, response, chain, token)) { + Subject subject = createSubjectFromToken(token); + continueWithEstablishedSecurityContext(subject, (HttpServletRequest)request, (HttpServletResponse)response, chain); } - if (verified) { - // confirm that issue matches intended target - which for this filter must be KNOXSSO - if (token.getIssuer().equals("KNOXSSO")) { - // if there is no expiration data then the lifecycle is tied entirely to - // the cookie validity - otherwise ensure that the current time is before - // the designated expiration time - if (tokenIsStillValid(token)) { - boolean audValid = validateAudiences(token); - if (audValid) { - Subject subject = createSubjectFromToken(token); - continueWithEstablishedSecurityContext(subject, (HttpServletRequest)request, (HttpServletResponse)response, chain); - } - else { - log.failedToValidateAudience(); - ((HttpServletResponse) response).sendError(400, "Bad request: missing required token audience"); - } + else { + return; // break the filter chain + } + } + else { + // check for query param + String wireToken = ((HttpServletRequest) request).getParameter(paramName); + if (wireToken != null) { + JWTToken token = new JWTToken(wireToken); + if (validateToken(request, response, chain, token)) { + Subject subject = createSubjectFromToken(token); + continueWithEstablishedSecurityContext(subject, (HttpServletRequest)request, (HttpServletResponse)response, chain); + } + } + else { + // no token provided in header + ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; //break filter chain + } + } + } + + private boolean validateToken(ServletRequest request, ServletResponse response, + FilterChain chain, JWTToken token) + throws IOException, ServletException { + boolean rc = false; + boolean verified = false; + try { + verified = authority.verifyToken(token); + } catch (TokenServiceException e) { + log.unableToVerifyToken(e); + } + if (verified) { + // confirm that issue matches intended target - which for this filter must be KNOXSSO + if (token.getIssuer().equals("KNOXSSO")) { + // if there is no expiration data then the lifecycle is tied entirely to + // the cookie validity - otherwise ensure that the current time is before + // the designated expiration time + if (tokenIsStillValid(token)) { + boolean audValid = validateAudiences(token); + if (audValid) { + rc = true; } else { - log.tokenHasExpired(); - ((HttpServletResponse) response).sendError(400, "Bad request: token has expired"); + log.failedToValidateAudience(); + ((HttpServletResponse) response).sendError(400, "Bad request: missing required token audience"); } } else { - ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED); - return; //break filter chain + log.tokenHasExpired(); + ((HttpServletResponse) response).sendError(400, "Bad request: token has expired"); } } else { ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED); - return; //break filter chain } } else { - // no token provided in header ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED); - return; //break filter chain } + + return rc; } private void continueWithEstablishedSecurityContext(Subject subject, final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException {
