From e7ed05e4f5b0421e93f2f2cadc5beda3d28b9911 Mon Sep 17 00:00:00 2001 From: Benoy Antony Date: Mon, 21 Mar 2016 13:19:43 -0700 Subject: [PATCH] HADOOP-12929. JWTRedirectAuthenticationHandler must accommodate null expiration time. Contributed by Larry McCay. --- .../JWTRedirectAuthenticationHandler.java | 16 ++------ .../TestJWTRedirectAuthentictionHandler.java | 37 +++++++++++++++---- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/JWTRedirectAuthenticationHandler.java b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/JWTRedirectAuthenticationHandler.java index cbe923be8e..61f5b9e894 100644 --- a/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/JWTRedirectAuthenticationHandler.java +++ b/hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/JWTRedirectAuthenticationHandler.java @@ -26,20 +26,10 @@ import java.util.Properties; import java.text.ParseException; -import java.io.ByteArrayInputStream; -import java.io.UnsupportedEncodingException; -import java.security.PublicKey; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateException; import java.security.interfaces.RSAPublicKey; -import org.apache.commons.codec.binary.Base64; import org.apache.hadoop.security.authentication.client.AuthenticationException; -import org.apache.hadoop.security.authentication.server.AltKerberosAuthenticationHandler; -import org.apache.hadoop.security.authentication.server.AuthenticationToken; import org.apache.hadoop.security.authentication.util.CertificateUtil; -import org.apache.hadoop.security.authentication.util.KerberosName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,7 +73,8 @@ public class JWTRedirectAuthenticationHandler extends private static Logger LOG = LoggerFactory .getLogger(JWTRedirectAuthenticationHandler.class); - public static final String AUTHENTICATION_PROVIDER_URL = "authentication.provider.url"; + public static final String AUTHENTICATION_PROVIDER_URL = + "authentication.provider.url"; public static final String PUBLIC_KEY_PEM = "public.key.pem"; public static final String EXPECTED_JWT_AUDIENCES = "expected.jwt.audiences"; public static final String JWT_COOKIE_NAME = "jwt.cookie.name"; @@ -205,7 +196,6 @@ public AuthenticationToken alternateAuthenticate(HttpServletRequest request, protected String getJWTFromCookie(HttpServletRequest req) { String serializedJWT = null; Cookie[] cookies = req.getCookies(); - String userName = null; if (cookies != null) { for (Cookie cookie : cookies) { if (cookieName.equals(cookie.getName())) { @@ -350,7 +340,7 @@ protected boolean validateExpiration(SignedJWT jwtToken) { boolean valid = false; try { Date expires = jwtToken.getJWTClaimsSet().getExpirationTime(); - if (expires != null && new Date().before(expires)) { + if (expires == null || new Date().before(expires)) { LOG.debug("JWT token expiration date has been " + "successfully validated"); valid = true; diff --git a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestJWTRedirectAuthentictionHandler.java b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestJWTRedirectAuthentictionHandler.java index 019ecb416c..97a8a9d2c5 100644 --- a/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestJWTRedirectAuthentictionHandler.java +++ b/hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestJWTRedirectAuthentictionHandler.java @@ -13,19 +13,15 @@ */ package org.apache.hadoop.security.authentication.server; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; -import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.Properties; @@ -50,8 +46,6 @@ import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jose.crypto.RSASSAVerifier; -import com.nimbusds.jose.util.Base64URL; public class TestJWTRedirectAuthentictionHandler extends KerberosSecurityTestcase { @@ -261,6 +255,36 @@ public void testExpiredJWT() throws Exception { } } + @Test + public void testNoExpirationJWT() throws Exception { + try { + handler.setPublicKey(publicKey); + + Properties props = getProperties(); + handler.init(props); + + SignedJWT jwt = getJWT("bob", null, privateKey); + + Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize()); + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie }); + Mockito.when(request.getRequestURL()).thenReturn( + new StringBuffer(SERVICE_URL)); + HttpServletResponse response = Mockito.mock(HttpServletResponse.class); + Mockito.when(response.encodeRedirectURL(SERVICE_URL)).thenReturn( + SERVICE_URL); + + AuthenticationToken token = handler.alternateAuthenticate(request, + response); + Assert.assertNotNull("Token should not be null.", token); + Assert.assertEquals("bob", token.getUserName()); + } catch (ServletException se) { + fail("alternateAuthentication should NOT have thrown a ServletException"); + } catch (AuthenticationException ae) { + fail("alternateAuthentication should NOT have thrown a AuthenticationException"); + } + } + @Test public void testInvalidAudienceJWT() throws Exception { try { @@ -442,7 +466,6 @@ protected SignedJWT getJWT(String sub, Date expires, RSAPrivateKey privateKey) JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build(); SignedJWT signedJWT = new SignedJWT(header, claimsSet); - Base64URL sigInput = Base64URL.encode(signedJWT.getSigningInput()); JWSSigner signer = new RSASSASigner(privateKey); signedJWT.sign(signer);