knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From m...@apache.org
Subject [10/64] [partial] knox git commit: KNOX-998 - Refactoring save 1
Date Fri, 01 Sep 2017 13:17:08 GMT
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
deleted file mode 100644
index 396aec9..0000000
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.provider.federation;
-
-import static org.junit.Assert.fail;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.util.Properties;
-import java.util.Date;
-import java.util.Set;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.nimbusds.jwt.SignedJWT;
-
-public class SSOCookieProviderTest extends AbstractJWTFilterTest {
-  private static final String SERVICE_URL = "https://localhost:8888/resource";
-  private static final String REDIRECT_LOCATION =
-      "https://localhost:8443/authserver?originalUrl=" + SERVICE_URL;
-  
-  @Before
-  public void setup() throws Exception, NoSuchAlgorithmException {
-    super.setup();
-    handler = new TestSSOCookieFederationProvider();
-    ((TestSSOCookieFederationProvider) handler).setTokenService(new TestJWTokenAuthority());
-  }
-  
-  protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
-    Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
-    EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
-  }
-  
-  protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
-    Cookie cookie = new Cookie("hadoop-jwt", "ljm" + jwt.serialize());
-    EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
-  }
-
-  protected String getAudienceProperty() {
-    return TestSSOCookieFederationProvider.SSO_EXPECTED_AUDIENCES;
-  }
-  
-  @Test
-  public void testCustomCookieNameJWT() throws Exception {
-    try {
-      Properties props = getProperties();
-      props.put("sso.cookie.name", "jowt");
-      handler.init(new TestFilterConfig(props));
-
-      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000),
-          privateKey, props);
-
-      Cookie cookie = new Cookie("jowt", jwt.serialize());
-      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
-      EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
-      EasyMock.expect(request.getRequestURL()).andReturn(
-          new StringBuffer(SERVICE_URL)).anyTimes();
-      EasyMock.expect(request.getQueryString()).andReturn(null);
-      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
-      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
-          SERVICE_URL);
-      EasyMock.replay(request);
-
-      TestFilterChain chain = new TestFilterChain();
-      handler.doFilter(request, response, chain);
-      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
-      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
-      Assert.assertTrue("No PrimaryPrincipal returned.", principals.size() > 0);
-      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
-    } catch (ServletException se) {
-      fail("Should NOT have thrown a ServletException.");
-    }
-  }
-
-  @Test
-  public void testNoProviderURLJWT() throws Exception {
-    try {
-      Properties props = getProperties();
-      props.remove("sso.authentication.provider.url");
-      handler.init(new TestFilterConfig(props));
-
-      fail("Servlet exception should have been thrown.");
-
-    } catch (ServletException se) {
-      // expected - let's ensure it mentions the missing authentication provider URL
-      se.getMessage().contains("authentication provider URL is missing");
-    }
-  }
-  
-/*
-  @Test
-  public void testFailedSignatureValidationJWT() throws Exception {
-    try {
-
-      // Create a public key that doesn't match the one needed to
-      // verify the signature - in order to make it fail verification...
-      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
-      kpg.initialize(2048);
-
-      KeyPair kp = kpg.genKeyPair();
-      RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
-
-      handler.setPublicKey(publicKey);
-
-      Properties props = getProperties();
-      handler.init(props);
-
-      SignedJWT jwt = getJWT("bob", new Date(new Date().getTime() + 5000),
-          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)).anyTimes();
-      HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
-      Mockito.when(response.encodeRedirectURL(SERVICE_URL)).thenReturn(
-          SERVICE_URL);
-
-      AuthenticationToken token = handler.alternateAuthenticate(request,
-          response);
-      Mockito.verify(response).sendRedirect(REDIRECT_LOCATION);
-    } 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 testOrigURLWithQueryString() throws Exception {
-    Properties props = getProperties();
-    handler.init(new TestFilterConfig(props));
-
-    HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
-    EasyMock.expect(request.getRequestURL()).andReturn(
-        new StringBuffer(SERVICE_URL)).anyTimes();
-    EasyMock.expect(request.getQueryString()).andReturn("name=value");
-    EasyMock.replay(request);
-
-    String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
-    Assert.assertNotNull("loginURL should not be null.", loginURL);
-    Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL + "?name=value", loginURL);
-  }
-
-  @Test
-  public void testOrigURLNoQueryString() throws Exception {
-    Properties props = getProperties();
-    handler.init(new TestFilterConfig(props));
-
-    HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
-    EasyMock.expect(request.getRequestURL()).andReturn(
-        new StringBuffer(SERVICE_URL)).anyTimes();
-    EasyMock.expect(request.getQueryString()).andReturn(null);
-    EasyMock.replay(request);
-
-    String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
-    Assert.assertNotNull("LoginURL should not be null.", loginURL);
-    Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL, loginURL);
-  }
-  
-
-  @Override
-  protected String getVerificationPemProperty() {
-    return SSOCookieFederationFilter.SSO_VERIFICATION_PEM;
-  };
-
-  private static class TestSSOCookieFederationProvider extends SSOCookieFederationFilter {
-    public String testConstructLoginURL(HttpServletRequest req) {
-      return constructLoginURL(req);
-    }
-    
-    public void setTokenService(JWTokenAuthority ts) {
-      authority = ts;
-    }
-  };
-
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
new file mode 100644
index 0000000..503f323
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
@@ -0,0 +1,490 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.provider.federation;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.security.AccessController;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Date;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter;
+import org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.security.impl.X509CertificateUtil;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.apache.knox.gateway.services.security.token.TokenServiceException;
+import org.apache.knox.gateway.services.security.token.impl.JWT;
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.nimbusds.jose.*;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.util.Base64URL;
+
+public abstract class AbstractJWTFilterTest  {
+  private static final String SERVICE_URL = "https://localhost:8888/resource";
+  private static final String dnTemplate = "CN={0},OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
+
+  protected AbstractJWTFilter handler = null;
+  protected RSAPublicKey publicKey = null;
+  protected RSAPrivateKey privateKey = null;
+  protected String pem = null;
+
+  protected abstract void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
+  protected abstract void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
+  protected abstract String getAudienceProperty();
+  protected abstract String getVerificationPemProperty();
+
+  private String buildDistinguishedName(String hostname) {
+    MessageFormat headerFormatter = new MessageFormat(dnTemplate);
+    String[] paramArray = new String[1];
+    paramArray[0] = hostname;
+    String dn = headerFormatter.format(paramArray);
+    return dn;
+  }
+
+  @Before
+  public void setup() throws Exception, NoSuchAlgorithmException {
+    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+    kpg.initialize(2048);
+    KeyPair KPair = kpg.generateKeyPair();
+    String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
+    Certificate cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+    byte[] data = cert.getEncoded();
+    Base64 encoder = new Base64( 76, "\n".getBytes( "ASCII" ) );
+    pem = new String(encoder.encodeToString( data ).getBytes( "ASCII" )).trim();
+
+    publicKey = (RSAPublicKey) KPair.getPublic();
+    privateKey = (RSAPrivateKey) KPair.getPrivate();
+  }
+
+  @After
+  public void teardown() throws Exception {
+    handler.destroy();
+  }
+  
+  @Test
+  public void testValidJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+      
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+      Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+  
+  @Test
+  public void testValidAudienceJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      props.put(getAudienceProperty(), "bar");
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+      
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+      Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+
+  @Test
+  public void testInvalidAudienceJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      props.put(getAudienceProperty(), "foo");
+      props.put("sso.authentication.provider.url", "https://localhost:8443/gateway/knoxsso/api/v1/websso");
+
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+      
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be true.", chain.doFilterCalled == false);
+      Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+
+  @Test
+  public void testValidVerificationPEM() throws Exception {
+    try {
+      Properties props = getProperties();
+      
+//      System.out.println("+" + pem + "+");
+
+      props.put(getAudienceProperty(), "bar");
+      props.put("sso.authentication.provider.url", "https://localhost:8443/gateway/knoxsso/api/v1/websso");
+      props.put(getVerificationPemProperty(), pem);
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 50000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+      Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+
+  @Test
+  public void testExpiredJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() - 1000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+      
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == false);
+      Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+  
+  @Test
+  public void testValidJWTNoExpiration() throws Exception {
+    try {
+      Properties props = getProperties();
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", null, privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setTokenOnRequest(request, jwt);
+      
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL).anyTimes();
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+      Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+  
+  @Test
+  public void testUnableToParseJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("bob",new Date(new Date().getTime() + 5000), privateKey, props);
+
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      setGarbledTokenOnRequest(request, jwt);
+
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL).anyTimes();
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == false);
+      Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+
+  protected Properties getProperties() {
+    Properties props = new Properties();
+    props.setProperty(
+        SSOCookieFederationFilter.SSO_AUTHENTICATION_PROVIDER_URL,
+        "https://localhost:8443/authserver");
+    return props;
+  }
+
+  protected SignedJWT getJWT(String sub, Date expires, RSAPrivateKey privateKey,
+      Properties props) throws Exception {
+    List<String> aud = new ArrayList<String>();
+    aud.add("bar");
+
+    JWTClaimsSet claims = new JWTClaimsSet.Builder()
+    .issuer("KNOXSSO")
+    .subject(sub)
+    .audience(aud)
+    .expirationTime(expires)
+    .claim("scope", "openid")
+    .build();
+
+    JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build();
+
+    SignedJWT signedJWT = new SignedJWT(header, claims);
+    Base64URL sigInput = Base64URL.encode(signedJWT.getSigningInput());
+    JWSSigner signer = new RSASSASigner(privateKey);
+
+    signedJWT.sign(signer);
+
+    return signedJWT;
+  }
+
+  protected static class TestFilterConfig implements FilterConfig {
+    Properties props = null;
+
+    public TestFilterConfig(Properties props) {
+      this.props = props;
+    }
+
+    @Override
+    public String getFilterName() {
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.servlet.FilterConfig#getServletContext()
+     */
+    @Override
+    public ServletContext getServletContext() {
+//      JWTokenAuthority authority = EasyMock.createNiceMock(JWTokenAuthority.class);
+//      GatewayServices services = EasyMock.createNiceMock(GatewayServices.class);
+//      EasyMock.expect(services.getService("TokenService").andReturn(authority));
+//      ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+//      EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE).andReturn(new DefaultGatewayServices()));
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see javax.servlet.FilterConfig#getInitParameter(java.lang.String)
+     */
+    @Override
+    public String getInitParameter(String name) {
+      return props.getProperty(name, null);
+    }
+
+    /* (non-Javadoc)
+     * @see javax.servlet.FilterConfig#getInitParameterNames()
+     */
+    @Override
+    public Enumeration<String> getInitParameterNames() {
+      return null;
+    }
+    
+  }
+  
+  protected static class TestJWTokenAuthority implements JWTokenAuthority {
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#issueToken(javax.security.auth.Subject, java.lang.String)
+     */
+    @Override
+    public JWTToken issueToken(Subject subject, String algorithm)
+        throws TokenServiceException {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String)
+     */
+    @Override
+    public JWTToken issueToken(Principal p, String algorithm)
+        throws TokenServiceException {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, java.lang.String)
+     */
+    @Override
+    public JWTToken issueToken(Principal p, String audience, String algorithm)
+        throws TokenServiceException {
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#verifyToken(JWTToken)
+     */
+    @Override
+    public boolean verifyToken(JWTToken token) throws TokenServiceException {
+      return true;
+    }
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, java.lang.String, long)
+     */
+    @Override
+    public JWTToken issueToken(Principal p, String audience, String algorithm,
+        long expires) throws TokenServiceException {
+      return null;
+    }
+
+    @Override
+    public JWTToken issueToken(Principal p, List<String> audiences, String algorithm,
+        long expires) throws TokenServiceException {
+      return null;
+    }
+
+    /* (non-Javadoc)
+     * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, long)
+     */
+    @Override
+    public JWT issueToken(Principal p, String audience, long l)
+        throws TokenServiceException {
+      // TODO Auto-generated method stub
+      return null;
+    }
+
+    @Override
+    public boolean verifyToken(JWTToken token, RSAPublicKey publicKey) throws TokenServiceException {
+      // TODO Auto-generated method stub
+      return true;
+    }
+    
+  }
+  
+  protected static class TestFilterChain implements FilterChain {
+    boolean doFilterCalled = false;
+    Subject subject = null;
+
+    /* (non-Javadoc)
+     * @see javax.servlet.FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+     */
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response)
+        throws IOException, ServletException {
+      doFilterCalled = true;
+      
+      subject = Subject.getSubject( AccessController.getContext() );
+    }
+    
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
new file mode 100644
index 0000000..14b704a
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
@@ -0,0 +1,67 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.provider.federation;
+
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.easymock.EasyMock;
+import org.junit.Before;
+
+import com.nimbusds.jwt.SignedJWT;
+
+public class JWTFederationFilterTest extends AbstractJWTFilterTest {
+    
+    @Before
+    public void setup() throws Exception, NoSuchAlgorithmException {
+      super.setup();
+      handler = new TestJWTFederationFilter();
+      ((TestJWTFederationFilter) handler).setTokenService(new TestJWTokenAuthority());
+    }
+    
+    protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+      String token = "Bearer " + jwt.serialize();
+      EasyMock.expect(request.getHeader("Authorization")).andReturn(token);
+    }
+    
+    protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+      String token = "Bearer " + "ljm" + jwt.serialize();
+      EasyMock.expect(request.getHeader("Authorization")).andReturn(token);
+    }
+
+    protected String getAudienceProperty() {
+      return TestJWTFederationFilter.KNOX_TOKEN_AUDIENCES;
+    }
+    
+    private static class TestJWTFederationFilter extends JWTFederationFilter {
+
+      public void setTokenService(JWTokenAuthority ts) {
+        authority = ts;
+      }
+        
+    }
+
+    @Override
+    protected String getVerificationPemProperty() {
+      return TestJWTFederationFilter.TOKEN_VERIFICATION_PEM;
+    };
+    
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
new file mode 100644
index 0000000..1f1973e
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.provider.federation;
+
+import java.util.ArrayList;
+import junit.framework.TestCase;
+
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
+import org.junit.Test;
+
+public class JWTTokenTest extends TestCase {
+  private static final String JWT_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E";
+  private static final String HEADER = "{\"alg\":\"RS256\", \"type\":\"JWT\"}";
+  private static final String CLAIMS = "{\"iss\": \"gateway\", \"prn\": \"john.doe@example.com\", \"aud\": \"https://login.example.com\", \"exp\": \"1363360913\"}";
+  
+//  public void testTokenParsing() throws Exception {
+//    try {
+//      JWTToken token = JWTToken.parseToken(JWT_TOKEN);
+//      assertEquals(token.getHeader(), HEADER);
+//      assertEquals(token.getClaims(), CLAIMS);
+//      
+//      assertEquals(token.getIssuer(), "gateway");
+//      assertEquals(token.getPrincipal(), "john.doe@example.com");
+//      assertEquals(token.getAudience(), "https://login.example.com");
+//      assertEquals(token.getExpires(), "1363360913");
+//    }
+//    catch (ParseException pe) {
+//      fail("ParseException encountered.");
+//    }
+//  }
+  
+  @Test
+  public void testTokenCreation() throws Exception {
+    String[] claims = new String[4];
+    claims[0] = "KNOXSSO";
+    claims[1] = "john.doe@example.com";
+    claims[2] = "https://login.example.com";
+    claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+    JWTToken token = new JWTToken("RS256", claims);
+
+    assertEquals("KNOXSSO", token.getIssuer());
+    assertEquals("john.doe@example.com", token.getSubject());
+    assertEquals("https://login.example.com", token.getAudience());
+  }
+
+  @Test
+  public void testTokenCreationWithAudienceListSingle() throws Exception {
+    String[] claims = new String[4];
+    claims[0] = "KNOXSSO";
+    claims[1] = "john.doe@example.com";
+    claims[2] = null;
+    claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+    ArrayList<String> audiences = new ArrayList<String>();
+    audiences.add("https://login.example.com");
+
+    JWTToken token = new JWTToken("RS256", claims, audiences);
+
+    assertEquals("KNOXSSO", token.getIssuer());
+    assertEquals("john.doe@example.com", token.getSubject());
+    assertEquals("https://login.example.com", token.getAudience());
+    assertEquals(1, token.getAudienceClaims().length);
+  }
+
+  @Test
+  public void testTokenCreationWithAudienceListMultiple() throws Exception {
+    String[] claims = new String[4];
+    claims[0] = "KNOXSSO";
+    claims[1] = "john.doe@example.com";
+    claims[2] = null;
+    claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+    ArrayList<String> audiences = new ArrayList<String>();
+    audiences.add("https://login.example.com");
+    audiences.add("KNOXSSO");
+
+    JWTToken token = new JWTToken("RS256", claims, audiences);
+
+    assertEquals("KNOXSSO", token.getIssuer());
+    assertEquals("john.doe@example.com", token.getSubject());
+    assertEquals("https://login.example.com", token.getAudience());
+    assertEquals(2, token.getAudienceClaims().length);
+  }
+
+  @Test
+  public void testTokenCreationWithAudienceListCombined() throws Exception {
+    String[] claims = new String[4];
+    claims[0] = "KNOXSSO";
+    claims[1] = "john.doe@example.com";
+    claims[2] = "LJM";
+    claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+    ArrayList<String> audiences = new ArrayList<String>();
+    audiences.add("https://login.example.com");
+    audiences.add("KNOXSSO");
+
+    JWTToken token = new JWTToken("RS256", claims, audiences);
+
+    assertEquals("KNOXSSO", token.getIssuer());
+    assertEquals("john.doe@example.com", token.getSubject());
+    assertEquals("https://login.example.com", token.getAudience());
+    assertEquals(3, token.getAudienceClaims().length);
+  }
+
+  @Test
+  public void testTokenCreationWithNullAudienceList() throws Exception {
+    String[] claims = new String[4];
+    claims[0] = "KNOXSSO";
+    claims[1] = "john.doe@example.com";
+    claims[2] = null;
+    claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+    ArrayList<String> audiences = null;
+
+    JWTToken token = new JWTToken("RS256", claims, audiences);
+
+    assertEquals("KNOXSSO", token.getIssuer());
+    assertEquals("john.doe@example.com", token.getSubject());
+    assertEquals(null, token.getAudience());
+    assertEquals(null, token.getAudienceClaims());
+  }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
new file mode 100644
index 0000000..fa0e785
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
@@ -0,0 +1,205 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.provider.federation;
+
+import static org.junit.Assert.fail;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Properties;
+import java.util.Date;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.nimbusds.jwt.SignedJWT;
+
+public class SSOCookieProviderTest extends AbstractJWTFilterTest {
+  private static final String SERVICE_URL = "https://localhost:8888/resource";
+  private static final String REDIRECT_LOCATION =
+      "https://localhost:8443/authserver?originalUrl=" + SERVICE_URL;
+  
+  @Before
+  public void setup() throws Exception, NoSuchAlgorithmException {
+    super.setup();
+    handler = new TestSSOCookieFederationProvider();
+    ((TestSSOCookieFederationProvider) handler).setTokenService(new TestJWTokenAuthority());
+  }
+  
+  protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+    Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
+    EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+  }
+  
+  protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+    Cookie cookie = new Cookie("hadoop-jwt", "ljm" + jwt.serialize());
+    EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+  }
+
+  protected String getAudienceProperty() {
+    return TestSSOCookieFederationProvider.SSO_EXPECTED_AUDIENCES;
+  }
+  
+  @Test
+  public void testCustomCookieNameJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      props.put("sso.cookie.name", "jowt");
+      handler.init(new TestFilterConfig(props));
+
+      SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000),
+          privateKey, props);
+
+      Cookie cookie = new Cookie("jowt", jwt.serialize());
+      HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+      EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+      EasyMock.expect(request.getRequestURL()).andReturn(
+          new StringBuffer(SERVICE_URL)).anyTimes();
+      EasyMock.expect(request.getQueryString()).andReturn(null);
+      HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+      EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+          SERVICE_URL);
+      EasyMock.replay(request);
+
+      TestFilterChain chain = new TestFilterChain();
+      handler.doFilter(request, response, chain);
+      Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+      Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+      Assert.assertTrue("No PrimaryPrincipal returned.", principals.size() > 0);
+      Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+    } catch (ServletException se) {
+      fail("Should NOT have thrown a ServletException.");
+    }
+  }
+
+  @Test
+  public void testNoProviderURLJWT() throws Exception {
+    try {
+      Properties props = getProperties();
+      props.remove("sso.authentication.provider.url");
+      handler.init(new TestFilterConfig(props));
+
+      fail("Servlet exception should have been thrown.");
+
+    } catch (ServletException se) {
+      // expected - let's ensure it mentions the missing authentication provider URL
+      se.getMessage().contains("authentication provider URL is missing");
+    }
+  }
+  
+/*
+  @Test
+  public void testFailedSignatureValidationJWT() throws Exception {
+    try {
+
+      // Create a public key that doesn't match the one needed to
+      // verify the signature - in order to make it fail verification...
+      KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+      kpg.initialize(2048);
+
+      KeyPair kp = kpg.genKeyPair();
+      RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
+
+      handler.setPublicKey(publicKey);
+
+      Properties props = getProperties();
+      handler.init(props);
+
+      SignedJWT jwt = getJWT("bob", new Date(new Date().getTime() + 5000),
+          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)).anyTimes();
+      HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+      Mockito.when(response.encodeRedirectURL(SERVICE_URL)).thenReturn(
+          SERVICE_URL);
+
+      AuthenticationToken token = handler.alternateAuthenticate(request,
+          response);
+      Mockito.verify(response).sendRedirect(REDIRECT_LOCATION);
+    } 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 testOrigURLWithQueryString() throws Exception {
+    Properties props = getProperties();
+    handler.init(new TestFilterConfig(props));
+
+    HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+    EasyMock.expect(request.getRequestURL()).andReturn(
+        new StringBuffer(SERVICE_URL)).anyTimes();
+    EasyMock.expect(request.getQueryString()).andReturn("name=value");
+    EasyMock.replay(request);
+
+    String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
+    Assert.assertNotNull("loginURL should not be null.", loginURL);
+    Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL + "?name=value", loginURL);
+  }
+
+  @Test
+  public void testOrigURLNoQueryString() throws Exception {
+    Properties props = getProperties();
+    handler.init(new TestFilterConfig(props));
+
+    HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+    EasyMock.expect(request.getRequestURL()).andReturn(
+        new StringBuffer(SERVICE_URL)).anyTimes();
+    EasyMock.expect(request.getQueryString()).andReturn(null);
+    EasyMock.replay(request);
+
+    String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
+    Assert.assertNotNull("LoginURL should not be null.", loginURL);
+    Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL, loginURL);
+  }
+  
+
+  @Override
+  protected String getVerificationPemProperty() {
+    return SSOCookieFederationFilter.SSO_VERIFICATION_PEM;
+  };
+
+  private static class TestSSOCookieFederationProvider extends SSOCookieFederationFilter {
+    public String testConstructLoginURL(HttpServletRequest req) {
+      return constructLoginURL(req);
+    }
+    
+    public void setTokenService(JWTokenAuthority ts) {
+      authority = ts;
+    }
+  };
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
deleted file mode 100644
index 931e494..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j;
-
-import org.apache.hadoop.gateway.i18n.messages.Message;
-import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
-import org.apache.hadoop.gateway.i18n.messages.Messages;
-
-/**
- * Logging messages for the pac4j provider.
- *
- * @since 0.8.0
- */
-@Messages(logger="org.apache.hadoop.gateway.pac4j")
-public interface Pac4jMessages {
-
-  @Message( level = MessageLevel.ERROR, text = "pac4j callback URL required")
-  public void ssoAuthenticationProviderUrlRequired();
-
-  @Message( level = MessageLevel.ERROR, text = "pac4j clientName parameter required")
-  public void clientNameParameterRequired();
-
-  @Message( level = MessageLevel.ERROR, text = "At least one pac4j client must be defined")
-  public void atLeastOnePac4jClientMustBeDefined();
-
-  @Message( level = MessageLevel.ERROR, text = "Crypto service, alias service and cluster name required")
-  public void cryptoServiceAndAliasServiceAndClusterNameRequired();
-
-  @Message( level = MessageLevel.ERROR, text = "Unable to generate a password for encryption")
-  public void unableToGenerateAPasswordForEncryption(Exception e);
-
-  @Message( level = MessageLevel.INFO, text = 
-      "No private key passphrase alias found. Defaulting to master. Exception encountered: {0}")
-  public void noPrivateKeyPasshraseProvisioned(Exception e);
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
deleted file mode 100644
index c673ed5..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j.deploy;
-
-import org.apache.hadoop.gateway.deploy.DeploymentContext;
-import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase;
-import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
-import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
-import org.apache.hadoop.gateway.topology.Provider;
-import org.apache.hadoop.gateway.topology.Service;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Descriptor of the pac4j provider. This module must be deployed for the KnoxSSO service.
- *
- * @since 0.8.0
- */
-public class Pac4jFederationProviderContributor extends ProviderDeploymentContributorBase {
-
-  private static final String ROLE = "federation";
-  private static final String NAME = "pac4j";
-  private static final String DISPATCHER_FILTER_CLASSNAME = "org.apache.hadoop.gateway.pac4j.filter.Pac4jDispatcherFilter";
-  private static final String IDENTITY_ADAPTER_CLASSNAME = "org.apache.hadoop.gateway.pac4j.filter.Pac4jIdentityAdapter";
-
-  @Override
-  public String getRole() {
-    return ROLE;
-  }
-
-  @Override
-  public String getName() {
-    return NAME;
-  }
-  
-  @Override
-  public void initializeContribution(DeploymentContext context) {
-    super.initializeContribution(context);
-  }
-
-  @Override
-  public void contributeProvider(DeploymentContext context, Provider provider) {
-  }
-
-  @Override
-  public void contributeFilter(DeploymentContext context, Provider provider, Service service, 
-      ResourceDescriptor resource, List<FilterParamDescriptor> params) {
-    // blindly add all the provider params as filter init params
-    if (params == null) {
-      params = new ArrayList<FilterParamDescriptor>();
-    }
-    Map<String, String> providerParams = provider.getParams();
-    for(Entry<String, String> entry : providerParams.entrySet()) {
-      params.add( resource.createFilterParam().name( entry.getKey() ).value( entry.getValue() ) );
-    }
-    resource.addFilter().name( getName() ).role( getRole() ).impl( DISPATCHER_FILTER_CLASSNAME ).params( params );
-    resource.addFilter().name( getName() ).role( getRole() ).impl( IDENTITY_ADAPTER_CLASSNAME ).params( params );
-  }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
deleted file mode 100644
index 574dea5..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j.filter;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.pac4j.Pac4jMessages;
-import org.apache.hadoop.gateway.pac4j.session.KnoxSessionStore;
-import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.KeystoreService;
-import org.apache.hadoop.gateway.services.security.MasterService;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.gateway.services.security.AliasServiceException;
-import org.apache.hadoop.gateway.services.security.CryptoService;
-import org.pac4j.config.client.PropertiesConfigFactory;
-import org.pac4j.core.client.Client;
-import org.pac4j.core.config.Config;
-import org.pac4j.core.config.ConfigSingleton;
-import org.pac4j.core.context.J2EContext;
-import org.pac4j.core.context.Pac4jConstants;
-import org.pac4j.core.util.CommonHelper;
-import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
-import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
-import org.pac4j.j2e.filter.CallbackFilter;
-import org.pac4j.j2e.filter.RequiresAuthenticationFilter;
-
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * <p>This is the main filter for the pac4j provider. The pac4j provider module heavily relies on the j2e-pac4j library (https://github.com/pac4j/j2e-pac4j).</p>
- * <p>This filter dispatches the HTTP calls between the j2e-pac4j filters:</p>
- * <ul>
- *     <li>to the {@link CallbackFilter} if the <code>client_name</code> parameter exists: it finishes the authentication process</li>
- *     <li>to the {@link RequiresAuthenticationFilter} otherwise: it starts the authentication process (redirection to the identity provider) if the user is not authenticated</li>
- * </ul>
- * <p>It uses the {@link KnoxSessionStore} to manage session data. The generated cookies are defined on a domain name
- * which can be configured via the domain suffix parameter: <code>pac4j.cookie.domain.suffix</code>.</p>
- * <p>The callback url must be defined to the current protected url (KnoxSSO service for example) via the parameter: <code>pac4j.callbackUrl</code>.</p>
- *
- * @since 0.8.0
- */
-public class Pac4jDispatcherFilter implements Filter {
-
-  private static Pac4jMessages log = MessagesFactory.get(Pac4jMessages.class);
-
-  public static final String TEST_BASIC_AUTH = "testBasicAuth";
-
-  public static final String PAC4J_CALLBACK_URL = "pac4j.callbackUrl";
-
-  public static final String PAC4J_CALLBACK_PARAMETER = "pac4jCallback";
-
-  private static final String PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM = "pac4j.cookie.domain.suffix";
-
-  private CallbackFilter callbackFilter;
-
-  private RequiresAuthenticationFilter requiresAuthenticationFilter;
-  private MasterService masterService = null;
-  private KeystoreService keystoreService = null;
-  private AliasService aliasService = null;
-
-  @Override
-  public void init( FilterConfig filterConfig ) throws ServletException {
-    // JWT service
-    final ServletContext context = filterConfig.getServletContext();
-    CryptoService cryptoService = null;
-    String clusterName = null;
-    if (context != null) {
-      GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-      clusterName = (String) context.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE);
-      if (services != null) {
-        keystoreService = (KeystoreService) services.getService(GatewayServices.KEYSTORE_SERVICE);
-        cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
-        aliasService = (AliasService) services.getService(GatewayServices.ALIAS_SERVICE);
-        masterService = (MasterService) services.getService("MasterService");
-      }
-    }
-    // crypto service, alias service and cluster name are mandatory
-    if (cryptoService == null || aliasService == null || clusterName == null) {
-      log.cryptoServiceAndAliasServiceAndClusterNameRequired();
-      throw new ServletException("The crypto service, alias service and cluster name are required.");
-    }
-    try {
-      aliasService.getPasswordFromAliasForCluster(clusterName, KnoxSessionStore.PAC4J_PASSWORD, true);
-    } catch (AliasServiceException e) {
-      log.unableToGenerateAPasswordForEncryption(e);
-      throw new ServletException("Unable to generate a password for encryption.");
-    }
-
-    // url to SSO authentication provider
-    String pac4jCallbackUrl = filterConfig.getInitParameter(PAC4J_CALLBACK_URL);
-    if (pac4jCallbackUrl == null) {
-      log.ssoAuthenticationProviderUrlRequired();
-      throw new ServletException("Required pac4j callback URL is missing.");
-    }
-    // add the callback parameter to know it's a callback
-    pac4jCallbackUrl = CommonHelper.addParameter(pac4jCallbackUrl, PAC4J_CALLBACK_PARAMETER, "true");
-
-    final Config config;
-    final String clientName;
-    // client name from servlet parameter (mandatory)
-    final String clientNameParameter = filterConfig.getInitParameter(Pac4jConstants.CLIENT_NAME);
-    if (clientNameParameter == null) {
-      log.clientNameParameterRequired();
-      throw new ServletException("Required pac4j clientName parameter is missing.");
-    }
-    if (TEST_BASIC_AUTH.equalsIgnoreCase(clientNameParameter)) {
-      // test configuration
-      final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());
-      indirectBasicAuthClient.setRealmName("Knox TEST");
-      config = new Config(pac4jCallbackUrl, indirectBasicAuthClient);
-      clientName = "IndirectBasicAuthClient";
-    } else {
-      // get clients from the init parameters
-      final Map<String, String> properties = new HashMap<>();
-      final Enumeration<String> names = filterConfig.getInitParameterNames();
-      addDefaultConfig(clientNameParameter, properties);
-      while (names.hasMoreElements()) {
-        final String key = names.nextElement();
-        properties.put(key, filterConfig.getInitParameter(key));
-      }
-      final PropertiesConfigFactory propertiesConfigFactory = new PropertiesConfigFactory(pac4jCallbackUrl, properties);
-      config = propertiesConfigFactory.build();
-      final List<Client> clients = config.getClients().getClients();
-      if (clients == null || clients.size() == 0) {
-        log.atLeastOnePac4jClientMustBeDefined();
-        throw new ServletException("At least one pac4j client must be defined.");
-      }
-      if (CommonHelper.isBlank(clientNameParameter)) {
-        clientName = clients.get(0).getName();
-      } else {
-        clientName = clientNameParameter;
-      }
-    }
-
-    callbackFilter = new CallbackFilter();
-    requiresAuthenticationFilter = new RequiresAuthenticationFilter();
-    requiresAuthenticationFilter.setClientName(clientName);
-    requiresAuthenticationFilter.setConfig(config);
-
-    final String domainSuffix = filterConfig.getInitParameter(PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM);
-    config.setSessionStore(new KnoxSessionStore(cryptoService, clusterName, domainSuffix));
-    ConfigSingleton.setConfig(config);
-  }
-
-  private void addDefaultConfig(String clientNameParameter, Map<String, String> properties) {
-    // add default saml params
-    if (clientNameParameter.contains("SAML2Client")) {
-      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PATH,
-          keystoreService.getKeystorePath());
-
-      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PASSWORD,
-          new String(masterService.getMasterSecret()));
-
-      // check for provisioned alias for private key
-      char[] gip = null;
-      try {
-        gip = aliasService.getGatewayIdentityPassphrase();
-      }
-      catch(AliasServiceException ase) {
-        log.noPrivateKeyPasshraseProvisioned(ase);
-      }
-      if (gip != null) {
-        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
-            new String(gip));
-      }
-      else {
-        // no alias provisioned then use the master
-        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
-            new String(masterService.getMasterSecret()));
-      }
-    }
-  }
-
-  @Override
-  public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-
-    final HttpServletRequest request = (HttpServletRequest) servletRequest;
-    final HttpServletResponse response = (HttpServletResponse) servletResponse;
-    final J2EContext context = new J2EContext(request, response, ConfigSingleton.getConfig().getSessionStore());
-
-    // it's a callback from an identity provider
-    if (request.getParameter(PAC4J_CALLBACK_PARAMETER) != null) {
-      // apply CallbackFilter
-      callbackFilter.doFilter(servletRequest, servletResponse, filterChain);
-    } else {
-      // otherwise just apply security and requires authentication
-      // apply RequiresAuthenticationFilter
-      requiresAuthenticationFilter.doFilter(servletRequest, servletResponse, filterChain);
-    }
-  }
-
-  @Override
-  public void destroy() { }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java
deleted file mode 100644
index ec5c368..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j.filter;
-
-import org.apache.hadoop.gateway.audit.api.*;
-import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
-import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-import org.pac4j.core.config.ConfigSingleton;
-import org.pac4j.core.context.J2EContext;
-import org.pac4j.core.profile.ProfileManager;
-import org.pac4j.core.profile.UserProfile;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.security.auth.Subject;
-import javax.servlet.*;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * <p>This filter retrieves the authenticated user saved by the pac4j provider and injects it into the J2E HTTP request.</p>
- *
- * @since 0.8.0
- */
-public class Pac4jIdentityAdapter implements Filter {
-
-  private static final Logger logger = LoggerFactory.getLogger(Pac4jIdentityAdapter.class);
-
-  private static AuditService auditService = AuditServiceFactory.getAuditService();
-  private static Auditor auditor = auditService.getAuditor(
-      AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME,
-      AuditConstants.KNOX_COMPONENT_NAME );
-
-  private String testIdentifier;
-
-  @Override
-  public void init( FilterConfig filterConfig ) throws ServletException {
-  }
-
-  public void destroy() {
-  }
-
-  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
-      throws IOException, ServletException {
-
-    final HttpServletRequest request = (HttpServletRequest) servletRequest;
-    final HttpServletResponse response = (HttpServletResponse) servletResponse;
-    final J2EContext context = new J2EContext(request, response, ConfigSingleton.getConfig().getSessionStore());
-    final ProfileManager manager = new ProfileManager(context);
-    final UserProfile profile = manager.get(true);
-    logger.debug("User authenticated as: {}", profile);
-    manager.remove(true);
-    final String id = profile.getId();
-    testIdentifier = id;
-    PrimaryPrincipal pp = new PrimaryPrincipal(id);
-    Subject subject = new Subject();
-    subject.getPrincipals().add(pp);
-    auditService.getContext().setUsername(id);
-    String sourceUri = (String)request.getAttribute( AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME );
-    auditor.audit(Action.AUTHENTICATION, sourceUri, ResourceType.URI, ActionOutcome.SUCCESS);
-    
-    doAs(request, response, chain, subject);
-  }
-  
-  private void doAs(final ServletRequest request,
-      final ServletResponse response, final FilterChain chain, Subject subject)
-      throws IOException, ServletException {
-    try {
-      Subject.doAs(
-          subject,
-          new PrivilegedExceptionAction<Object>() {
-            public Object run() throws Exception {
-              chain.doFilter(request, response);
-              return null;
-            }
-          }
-          );
-    }
-    catch (PrivilegedActionException e) {
-      Throwable t = e.getCause();
-      if (t instanceof IOException) {
-        throw (IOException) t;
-      }
-      else if (t instanceof ServletException) {
-        throw (ServletException) t;
-      }
-      else {
-        throw new ServletException(t);
-      }
-    }
-  }
-
-  /**
-   * For tests only.
-   */
-  public static void setAuditService(AuditService auditService) {
-    Pac4jIdentityAdapter.auditService = auditService;
-  }
-
-  /**
-   * For tests only.
-   */
-  public static void setAuditor(Auditor auditor) {
-    Pac4jIdentityAdapter.auditor = auditor;
-  }
-
-  /**
-   * For tests only.
-     */
-  public String getTestIdentifier() {
-    return testIdentifier;
-  }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java
deleted file mode 100644
index 1d7c567..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j.session;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.hadoop.gateway.services.security.CryptoService;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
-import org.apache.hadoop.gateway.util.Urls;
-import org.pac4j.core.context.ContextHelper;
-import org.pac4j.core.context.Cookie;
-import org.pac4j.core.context.WebContext;
-import org.pac4j.core.context.session.SessionStore;
-import org.pac4j.core.exception.TechnicalException;
-import org.pac4j.core.util.JavaSerializationHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Serializable;
-
-/**
- * Specific session store where data are saved into cookies (and not in memory).
- * Each data is encrypted and base64 encoded before being saved as a cookie (for security reasons).
- *
- * @since 0.8.0
- */
-public class KnoxSessionStore implements SessionStore {
-
-    private static final Logger logger = LoggerFactory.getLogger(KnoxSessionStore.class);
-
-    public static final String PAC4J_PASSWORD = "pac4j.password";
-
-    public static final String PAC4J_SESSION_PREFIX = "pac4j.session.";
-
-    private final JavaSerializationHelper javaSerializationHelper;
-
-    private final CryptoService cryptoService;
-
-    private final String clusterName;
-
-    private final String domainSuffix;
-
-    public KnoxSessionStore(final CryptoService cryptoService, final String clusterName, final String domainSuffix) {
-        javaSerializationHelper = new JavaSerializationHelper();
-        this.cryptoService = cryptoService;
-        this.clusterName = clusterName;
-        this.domainSuffix = domainSuffix;
-    }
-
-    public String getOrCreateSessionId(WebContext context) {
-        return null;
-    }
-
-    private Serializable decryptBase64(final String v) {
-        if (v != null && v.length() > 0) {
-            byte[] bytes = Base64.decodeBase64(v);
-            EncryptionResult result = EncryptionResult.fromByteArray(bytes);
-            byte[] clear = cryptoService.decryptForCluster(this.clusterName,
-                    PAC4J_PASSWORD,
-                    result.cipher,
-                    result.iv,
-                    result.salt);
-            if (clear != null) {
-                return javaSerializationHelper.unserializeFromBytes(clear);
-            }
-        }
-        return null;
-    }
-
-    public Object get(WebContext context, String key) {
-        final Cookie cookie = ContextHelper.getCookie(context, PAC4J_SESSION_PREFIX + key);
-        Object value = null;
-        if (cookie != null) {
-            value = decryptBase64(cookie.getValue());
-        }
-        logger.debug("Get from session: {} = {}", key, value);
-        return value;
-    }
-
-    private String encryptBase64(final Object o) {
-        if (o == null || o.equals("")) {
-            return null;
-        } else {
-            final byte[] bytes = javaSerializationHelper.serializeToBytes((Serializable) o);
-            EncryptionResult result = cryptoService.encryptForCluster(this.clusterName, PAC4J_PASSWORD, bytes);
-            return Base64.encodeBase64String(result.toByteAray());
-        }
-    }
-
-    public void set(WebContext context, String key, Object value) {
-        logger.debug("Save in session: {} = {}", key, value);
-        final Cookie cookie = new Cookie(PAC4J_SESSION_PREFIX + key, encryptBase64(value));
-        try {
-            String domain = Urls.getDomainName(context.getFullRequestURL(), this.domainSuffix);
-            if (domain == null) {
-                domain = context.getServerName();
-            }
-            cookie.setDomain(domain);
-        } catch (final Exception e) {
-            throw new TechnicalException(e);
-        }
-        cookie.setHttpOnly(true);
-        cookie.setSecure(ContextHelper.isHttpsOrSecure(context));
-        context.addResponseCookie(cookie);
-    }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
new file mode 100644
index 0000000..32e07e6
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j;
+
+import org.apache.knox.gateway.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+
+/**
+ * Logging messages for the pac4j provider.
+ *
+ * @since 0.8.0
+ */
+@Messages(logger="org.apache.hadoop.gateway.pac4j")
+public interface Pac4jMessages {
+
+  @Message( level = MessageLevel.ERROR, text = "pac4j callback URL required")
+  public void ssoAuthenticationProviderUrlRequired();
+
+  @Message( level = MessageLevel.ERROR, text = "pac4j clientName parameter required")
+  public void clientNameParameterRequired();
+
+  @Message( level = MessageLevel.ERROR, text = "At least one pac4j client must be defined")
+  public void atLeastOnePac4jClientMustBeDefined();
+
+  @Message( level = MessageLevel.ERROR, text = "Crypto service, alias service and cluster name required")
+  public void cryptoServiceAndAliasServiceAndClusterNameRequired();
+
+  @Message( level = MessageLevel.ERROR, text = "Unable to generate a password for encryption")
+  public void unableToGenerateAPasswordForEncryption(Exception e);
+
+  @Message( level = MessageLevel.INFO, text = 
+      "No private key passphrase alias found. Defaulting to master. Exception encountered: {0}")
+  public void noPrivateKeyPasshraseProvisioned(Exception e);
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
new file mode 100644
index 0000000..f027dd3
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
@@ -0,0 +1,78 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j.deploy;
+
+import org.apache.knox.gateway.deploy.DeploymentContext;
+import org.apache.knox.gateway.deploy.ProviderDeploymentContributorBase;
+import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
+import org.apache.knox.gateway.descriptor.ResourceDescriptor;
+import org.apache.knox.gateway.topology.Provider;
+import org.apache.knox.gateway.topology.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Descriptor of the pac4j provider. This module must be deployed for the KnoxSSO service.
+ *
+ * @since 0.8.0
+ */
+public class Pac4jFederationProviderContributor extends
+    ProviderDeploymentContributorBase {
+
+  private static final String ROLE = "federation";
+  private static final String NAME = "pac4j";
+  private static final String DISPATCHER_FILTER_CLASSNAME = "Pac4jDispatcherFilter";
+  private static final String IDENTITY_ADAPTER_CLASSNAME = "Pac4jIdentityAdapter";
+
+  @Override
+  public String getRole() {
+    return ROLE;
+  }
+
+  @Override
+  public String getName() {
+    return NAME;
+  }
+  
+  @Override
+  public void initializeContribution(DeploymentContext context) {
+    super.initializeContribution(context);
+  }
+
+  @Override
+  public void contributeProvider(DeploymentContext context, Provider provider) {
+  }
+
+  @Override
+  public void contributeFilter(DeploymentContext context, Provider provider, Service service,
+      ResourceDescriptor resource, List<FilterParamDescriptor> params) {
+    // blindly add all the provider params as filter init params
+    if (params == null) {
+      params = new ArrayList<FilterParamDescriptor>();
+    }
+    Map<String, String> providerParams = provider.getParams();
+    for(Entry<String, String> entry : providerParams.entrySet()) {
+      params.add( resource.createFilterParam().name( entry.getKey() ).value( entry.getValue() ) );
+    }
+    resource.addFilter().name( getName() ).role( getRole() ).impl( DISPATCHER_FILTER_CLASSNAME ).params( params );
+    resource.addFilter().name( getName() ).role( getRole() ).impl( IDENTITY_ADAPTER_CLASSNAME ).params( params );
+  }
+}


Mime
View raw message