You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/10/25 19:20:48 UTC

[12/17] knox git commit: Merge branch 'master' into KNOX-998-Package_Restructuring

http://git-wip-us.apache.org/repos/asf/knox/blob/58780d37/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
----------------------------------------------------------------------
diff --cc gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
index 27b1a30,0000000..e765c27
mode 100644,000000..100644
--- a/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
+++ b/gateway-spi/src/main/java/org/apache/knox/gateway/services/security/token/impl/JWTToken.java
@@@ -1,273 -1,0 +1,281 @@@
 +  /**
 +   * 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.services.security.token.impl;
 +
- import java.io.UnsupportedEncodingException;
 +import java.text.ParseException;
 +import java.util.Date;
 +import java.util.ArrayList;
 +import java.util.List;
- import java.util.Map;
 +
- import org.apache.commons.codec.binary.Base64;
 +import org.apache.knox.gateway.i18n.messages.MessagesFactory;
 +
 +import com.nimbusds.jose.JOSEException;
 +import com.nimbusds.jose.JWSAlgorithm;
 +import com.nimbusds.jose.JWSHeader;
 +import com.nimbusds.jose.JWSSigner;
 +import com.nimbusds.jose.JWSVerifier;
 +import com.nimbusds.jose.Payload;
 +import com.nimbusds.jose.util.Base64URL;
 +import com.nimbusds.jwt.JWTClaimsSet;
 +import com.nimbusds.jwt.SignedJWT;
 +
 +public class JWTToken implements JWT {
 +  private static JWTProviderMessages log = MessagesFactory.get( JWTProviderMessages.class );
 +
 +  SignedJWT jwt = null;
 +
 +  private JWTToken(String header, String claims, String signature) throws ParseException {
 +    jwt = new SignedJWT(new Base64URL(header), new Base64URL(claims), new Base64URL(signature));
 +  }
 +
 +  public JWTToken(String serializedJWT) throws ParseException {
 +    try {
 +      jwt = SignedJWT.parse(serializedJWT);
 +    } catch (ParseException e) {
 +      log.unableToParseToken(e);
 +      throw e;
 +    }
 +  }
 +
 +  public JWTToken(String alg, String[] claimsArray) {
 +    this(alg, claimsArray, null);
 +  }
 +
 +  public JWTToken(String alg, String[] claimsArray, List<String> audiences) {
 +    JWSHeader header = new JWSHeader(new JWSAlgorithm(alg));
 +
 +    if (claimsArray[2] != null) {
 +      if (audiences == null) {
 +        audiences = new ArrayList<String>();
 +      }
 +      audiences.add(claimsArray[2]);
 +    }
 +    JWTClaimsSet claims = null;
 +    JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder()
 +    .issuer(claimsArray[0])
 +    .subject(claimsArray[1])
 +    .audience(audiences);
 +    if(claimsArray[3] != null) {
 +      builder = builder.expirationTime(new Date(Long.parseLong(claimsArray[3])));
 +    }
 +
 +    claims = builder.build();
 +
 +    jwt = new SignedJWT(header, claims);
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getPayloadToSign()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getPayloadToSign()
 +   */
 +  @Override
 +  public String getHeader() {
 +    JWSHeader header = jwt.getHeader();
 +    return header.toString();
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getPayloadToSign()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getPayloadToSign()
 +   */
 +  @Override
 +  public String getClaims() {
 +    String c = null;
 +    JWTClaimsSet claims = null;
 +    try {
 +      claims = (JWTClaimsSet) jwt.getJWTClaimsSet();
 +      c = claims.toJSONObject().toJSONString();
 +    } catch (ParseException e) {
 +      log.unableToParseToken(e);
 +    }
 +    return c;
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getPayloadToSign()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getPayloadToSign()
 +   */
 +  @Override
 +  public String getPayload() {
 +    Payload payload = jwt.getPayload();
 +    return payload.toString();
 +  }
 +
 +  public String toString() {
 +    return jwt.serialize();
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#setSignaturePayload(byte[])
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#setSignaturePayload(byte[])
 +   */
 +  @Override
 +  public void setSignaturePayload(byte[] payload) {
 +//    this.payload = payload;
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getSignaturePayload()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getSignaturePayload()
 +   */
 +  @Override
 +  public byte[] getSignaturePayload() {
 +    byte[] b = null;
 +    Base64URL b64 = jwt.getSignature();
 +    if (b64 != null) {
 +      b = b64.decode();
 +    }
 +    return b;
 +  }
 +
 +  public static JWTToken parseToken(String wireToken) throws ParseException {
 +    log.parsingToken(wireToken);
 +    String[] parts = wireToken.split("\\.");
 +    return new JWTToken(parts[0], parts[1], parts[2]);
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getClaim(java.lang.String)
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getClaim(java.lang.String)
 +   */
 +  @Override
 +  public String getClaim(String claimName) {
 +    String claim = null;
 +
 +    try {
 +      claim = jwt.getJWTClaimsSet().getStringClaim(claimName);
 +    } catch (ParseException e) {
 +      log.unableToParseToken(e);
 +    }
 +
 +    return claim;
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getSubject()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getSubject()
 +   */
 +  @Override
 +  public String getSubject() {
 +    return getClaim(JWT.SUBJECT);
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getIssuer()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getIssuer()
 +   */
 +  @Override
 +  public String getIssuer() {
 +    return getClaim(JWT.ISSUER);
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getAudience()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getAudience()
 +   */
 +  @Override
 +  public String getAudience() {
 +    String[] claim = null;
 +    String c = null;
 +
 +    claim = getAudienceClaims();
 +    if (claim != null) {
 +      c = claim[0];
 +    }
 +
 +    return c;
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getAudienceClaims()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getAudienceClaims()
 +   */
 +  @Override
 +  public String[] getAudienceClaims() {
 +    String[] claims = null;
 +
 +    try {
 +      claims = jwt.getJWTClaimsSet().getStringArrayClaim(JWT.AUDIENCE);
 +    } catch (ParseException e) {
 +      log.unableToParseToken(e);
 +    }
 +
 +    return claims;
 +  }
 +
 +  /* (non-Javadoc)
-    * @see JWT#getExpires()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getExpires()
 +   */
 +  @Override
 +  public String getExpires() {
 +    Date expires = getExpiresDate();
 +    if (expires != null) {
 +      return String.valueOf(expires.getTime());
 +    }
 +    return null;
 +  }
 +
 +  @Override
 +  public Date getExpiresDate() {
 +    Date date = null;
 +    try {
 +      date = jwt.getJWTClaimsSet().getExpirationTime();
 +    } catch (ParseException e) {
 +      log.unableToParseToken(e);
 +    }
 +    return date;
 +  }
 +
++  @Override
++  public Date getNotBeforeDate() {
++    Date date = null;
++    try {
++      date = jwt.getJWTClaimsSet().getNotBeforeTime();
++    } catch (ParseException e) {
++      log.unableToParseToken(e);
++    }
++    return date;
++  }
++
 +  /* (non-Javadoc)
-    * @see JWT#getPrincipal()
++   * @see org.apache.knox.gateway.services.security.token.impl.JWT#getPrincipal()
 +   */
 +  @Override
 +  public String getPrincipal() {
 +    return getClaim(JWT.PRINCIPAL);
 +  }
 +
 +
 +  /* (non-Javadoc)
 +   * @see org.apache.knox.gateway.services.security.token.impl.JWT#sign(JWSSigner)
 +   */
 +  @Override
 +  public void sign(JWSSigner signer) {
 +    try {
 +      jwt.sign(signer);
 +    } catch (JOSEException e) {
 +      log.unableToSignToken(e);
 +    }
 +  }
 +
 +  /* (non-Javadoc)
 +   * @see org.apache.knox.gateway.services.security.token.impl.JWT#verify(JWSVerifier)
 +   */
 +  public boolean verify(JWSVerifier verifier) {
 +    boolean rc = false;
 +
 +    try {
 +      rc = jwt.verify(verifier);
 +    } catch (JOSEException e) {
 +      // TODO Auto-generated catch block
 +      log.unableToVerifyToken(e);
 +    }
 +
 +    return rc;
 +  }
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/58780d37/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
----------------------------------------------------------------------
diff --cc gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
index 1b0df9e,0000000..2c23e92
mode 100644,000000..100644
--- a/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
+++ b/gateway-spi/src/test/java/org/apache/knox/gateway/services/security/token/impl/JWTTokenTest.java
@@@ -1,223 -1,0 +1,240 @@@
 +/**
 + * 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.services.security.token.impl;
 +
 +import java.security.KeyPair;
 +import java.security.KeyPairGenerator;
 +import java.security.NoSuchAlgorithmException;
 +import java.security.interfaces.RSAPrivateKey;
 +import java.security.interfaces.RSAPublicKey;
++import java.text.ParseException;
 +import java.util.ArrayList;
 +import java.util.Date;
++import java.util.List;
 +
++import org.junit.BeforeClass;
 +import org.junit.Test;
 +
 +import com.nimbusds.jose.JWSAlgorithm;
 +import com.nimbusds.jose.JWSSigner;
 +import com.nimbusds.jose.JWSVerifier;
 +import com.nimbusds.jose.crypto.RSASSASigner;
 +import com.nimbusds.jose.crypto.RSASSAVerifier;
 +
 +public class JWTTokenTest extends org.junit.Assert {
 +  private static final String JWT_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E";
 +  private static final String HEADER = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
 +
-   private RSAPublicKey publicKey;
-   private RSAPrivateKey privateKey;
++  private static RSAPublicKey publicKey;
++  private static RSAPrivateKey privateKey;
 +
-   public JWTTokenTest() throws Exception, NoSuchAlgorithmException {
++  @BeforeClass
++  public static void setup() throws Exception, NoSuchAlgorithmException {
 +    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
 +    kpg.initialize(2048);
 +
 +    KeyPair kp = kpg.genKeyPair();
 +    publicKey = (RSAPublicKey) kp.getPublic();
 +    privateKey = (RSAPrivateKey) kp.getPrivate();
 +  }
 +
 +  @Test
 +  public void testTokenParsing() throws Exception {
 +    JWTToken token = JWTToken.parseToken(JWT_TOKEN);
 +    assertEquals(token.getHeader(), HEADER);
 +
 +    assertEquals(token.getClaim("jti"), "aa7f8d0a95c");
 +  }
 +
 +  @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);
++    JWT 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>();
++    List<String> audiences = new ArrayList<String>();
 +    audiences.add("https://login.example.com");
 +
-     JWTToken token = new JWTToken("RS256", claims, audiences);
++    JWT 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>();
++    List<String> audiences = new ArrayList<String>();
 +    audiences.add("https://login.example.com");
 +    audiences.add("KNOXSSO");
 +
-     JWTToken token = new JWTToken("RS256", claims, audiences);
++    JWT 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;
++    List<String> audiences = null;
 +
-     JWTToken token = new JWTToken("RS256", claims, audiences);
++    JWT token = new JWTToken("RS256", claims, audiences);
 +
 +    assertEquals("KNOXSSO", token.getIssuer());
 +    assertEquals("john.doe@example.com", token.getSubject());
 +    assertEquals(null, token.getAudience());
 +    assertArrayEquals(null, token.getAudienceClaims());
 +  }
 +
 +  @Test
 +  public void testTokenCreationRS512() 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(JWSAlgorithm.RS512.getName(), claims);
 +
 +    assertEquals("KNOXSSO", token.getIssuer());
 +    assertEquals("john.doe@example.com", token.getSubject());
 +    assertEquals("https://login.example.com", token.getAudience());
 +    assertTrue(token.getHeader().contains(JWSAlgorithm.RS512.getName()));
 +  }
 +
 +  @Test
 +  public void testTokenSignature() 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);
- 
++    JWT token = new JWTToken("RS256", claims);
 +
 +    assertEquals("KNOXSSO", token.getIssuer());
 +    assertEquals("john.doe@example.com", token.getSubject());
 +    assertEquals("https://login.example.com", token.getAudience());
 +
 +    // Sign the token
 +    JWSSigner signer = new RSASSASigner(privateKey);
 +    token.sign(signer);
 +    assertTrue(token.getSignaturePayload().length > 0);
 +
 +    // Verify the signature
 +    JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
 +    assertTrue(token.verify(verifier));
 +  }
 +
 +  @Test
 +  public void testTokenSignatureRS512() 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(JWSAlgorithm.RS512.getName(), claims);
++    JWT token = new JWTToken(JWSAlgorithm.RS512.getName(), claims);
 +
 +    assertEquals("KNOXSSO", token.getIssuer());
 +    assertEquals("john.doe@example.com", token.getSubject());
 +    assertEquals("https://login.example.com", token.getAudience());
 +    assertTrue(token.getHeader().contains(JWSAlgorithm.RS512.getName()));
 +
 +    // Sign the token
 +    JWSSigner signer = new RSASSASigner(privateKey);
 +    token.sign(signer);
 +    assertTrue(token.getSignaturePayload().length > 0);
 +
 +    // Verify the signature
 +    JWSVerifier verifier = new RSASSAVerifier((RSAPublicKey) publicKey);
 +    assertTrue(token.verify(verifier));
 +  }
 +
 +  @Test
 +  public void testTokenExpiry() 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);
++    JWT token = new JWTToken("RS256", claims);
 +
 +    assertNotNull(token.getExpires());
 +    assertNotNull(token.getExpiresDate());
 +    assertEquals(token.getExpiresDate(), new Date(Long.valueOf(token.getExpires())));
 +  }
++
++  @Test
++  public void testUnsignedToken() throws Exception {
++      String unsignedToken = "eyJhbGciOiJub25lIn0.eyJzdWIiOiJhbGljZSIsImp0aSI6ImY2YmNj"
++          + "MDVjLWI4MTktNGM0Mi1iMGMyLWJlYmY1MDE4YWFiZiJ9.";
++
++      try {
++          new JWTToken(unsignedToken);
++          fail("Failure expected on an unsigned token");
++      } catch (ParseException ex) {
++          // expected
++      }
++  }
++
 +}

http://git-wip-us.apache.org/repos/asf/knox/blob/58780d37/pom.xml
----------------------------------------------------------------------