HADOOP-12929. JWTRedirectAuthenticationHandler must accommodate null expiration time. Contributed by Larry McCay.

This commit is contained in:
Benoy Antony 2016-03-21 13:19:43 -07:00
parent 680716f31e
commit e7ed05e4f5
2 changed files with 33 additions and 20 deletions

View File

@ -26,20 +26,10 @@
import java.util.Properties; import java.util.Properties;
import java.text.ParseException; 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 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.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.CertificateUtil;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -83,7 +73,8 @@ public class JWTRedirectAuthenticationHandler extends
private static Logger LOG = LoggerFactory private static Logger LOG = LoggerFactory
.getLogger(JWTRedirectAuthenticationHandler.class); .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 PUBLIC_KEY_PEM = "public.key.pem";
public static final String EXPECTED_JWT_AUDIENCES = "expected.jwt.audiences"; public static final String EXPECTED_JWT_AUDIENCES = "expected.jwt.audiences";
public static final String JWT_COOKIE_NAME = "jwt.cookie.name"; public static final String JWT_COOKIE_NAME = "jwt.cookie.name";
@ -205,7 +196,6 @@ public AuthenticationToken alternateAuthenticate(HttpServletRequest request,
protected String getJWTFromCookie(HttpServletRequest req) { protected String getJWTFromCookie(HttpServletRequest req) {
String serializedJWT = null; String serializedJWT = null;
Cookie[] cookies = req.getCookies(); Cookie[] cookies = req.getCookies();
String userName = null;
if (cookies != null) { if (cookies != null) {
for (Cookie cookie : cookies) { for (Cookie cookie : cookies) {
if (cookieName.equals(cookie.getName())) { if (cookieName.equals(cookie.getName())) {
@ -350,7 +340,7 @@ protected boolean validateExpiration(SignedJWT jwtToken) {
boolean valid = false; boolean valid = false;
try { try {
Date expires = jwtToken.getJWTClaimsSet().getExpirationTime(); 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 " LOG.debug("JWT token expiration date has been "
+ "successfully validated"); + "successfully validated");
valid = true; valid = true;

View File

@ -13,19 +13,15 @@
*/ */
package org.apache.hadoop.security.authentication.server; package org.apache.hadoop.security.authentication.server;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.io.File; import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Properties; import java.util.Properties;
@ -50,8 +46,6 @@
import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.SignedJWT;
import com.nimbusds.jose.crypto.RSASSASigner; import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.util.Base64URL;
public class TestJWTRedirectAuthentictionHandler extends public class TestJWTRedirectAuthentictionHandler extends
KerberosSecurityTestcase { 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 @Test
public void testInvalidAudienceJWT() throws Exception { public void testInvalidAudienceJWT() throws Exception {
try { try {
@ -442,7 +466,6 @@ protected SignedJWT getJWT(String sub, Date expires, RSAPrivateKey privateKey)
JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build(); JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build();
SignedJWT signedJWT = new SignedJWT(header, claimsSet); SignedJWT signedJWT = new SignedJWT(header, claimsSet);
Base64URL sigInput = Base64URL.encode(signedJWT.getSigningInput());
JWSSigner signer = new RSASSASigner(privateKey); JWSSigner signer = new RSASSASigner(privateKey);
signedJWT.sign(signer); signedJWT.sign(signer);