You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2016/02/10 18:24:16 UTC

[6/6] cxf git commit: Fix JWT + add systests

Fix JWT + add systests


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/a245aade
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/a245aade
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/a245aade

Branch: refs/heads/master
Commit: a245aadeb595ddca6f919dce26a21f5a1465a1d9
Parents: 064fc77
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Feb 10 16:14:11 2016 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Feb 10 17:22:03 2016 +0000

----------------------------------------------------------------------
 .../sts/rest/RESTSecurityTokenServiceImpl.java  |   7 +-
 .../cxf/systest/sts/rest/RESTUnitTest.java      | 114 ++++++++++++++++++-
 2 files changed, 117 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/a245aade/services/sts/sts-core/src/main/java/org/apache/cxf/sts/rest/RESTSecurityTokenServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/rest/RESTSecurityTokenServiceImpl.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/rest/RESTSecurityTokenServiceImpl.java
index deb05da..2ce24bc 100644
--- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/rest/RESTSecurityTokenServiceImpl.java
+++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/rest/RESTSecurityTokenServiceImpl.java
@@ -98,7 +98,12 @@ public class RESTSecurityTokenServiceImpl extends SecurityTokenServiceImpl imple
             issueToken(tokenType, keyType, requestedClaims, appliesTo);
         RequestedSecurityTokenType requestedToken = getRequestedSecurityToken(response);
         
-        return Response.ok(requestedToken.getAny()).build();
+        if ("jwt".equals(tokenType)) {
+            // Discard the wrapper here
+            return Response.ok(((Element)requestedToken.getAny()).getTextContent()).build();
+        } else {
+            return Response.ok(requestedToken.getAny()).build();
+        }
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/cxf/blob/a245aade/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/RESTUnitTest.java
----------------------------------------------------------------------
diff --git a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/RESTUnitTest.java b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/RESTUnitTest.java
index 946809f..a5ff4c0 100644
--- a/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/RESTUnitTest.java
+++ b/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/rest/RESTUnitTest.java
@@ -18,7 +18,14 @@
  */
 package org.apache.cxf.systest.sts.rest;
 
+import java.io.IOException;
 import java.net.URL;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.List;
 
 import javax.security.auth.callback.CallbackHandler;
@@ -32,6 +39,10 @@ import org.w3c.dom.Element;
 import org.apache.cxf.Bus;
 import org.apache.cxf.bus.spring.SpringBusFactory;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.rs.security.jose.jwa.SignatureAlgorithm;
+import org.apache.cxf.rs.security.jose.jws.JwsJwtCompactConsumer;
+import org.apache.cxf.rs.security.jose.jwt.JwtConstants;
+import org.apache.cxf.rs.security.jose.jwt.JwtToken;
 import org.apache.cxf.rt.security.claims.Claim;
 import org.apache.cxf.rt.security.claims.ClaimCollection;
 import org.apache.cxf.rt.security.saml.utils.SAMLUtils;
@@ -48,11 +59,13 @@ import org.apache.wss4j.common.crypto.CryptoFactory;
 import org.apache.wss4j.common.saml.OpenSAMLUtil;
 import org.apache.wss4j.common.saml.SAMLKeyInfo;
 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
+import org.apache.wss4j.common.util.Loader;
 import org.apache.wss4j.dom.WSDocInfo;
 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
 import org.apache.wss4j.dom.handler.RequestData;
 import org.apache.wss4j.dom.processor.Processor;
 import org.apache.wss4j.dom.processor.SAMLTokenProcessor;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 
 /**
@@ -688,7 +701,6 @@ public class RESTUnitTest extends AbstractBusClientServerTestBase {
     }
     
     @org.junit.Test
-    @org.junit.Ignore
     public void testIssueJWTToken() throws Exception {
         SpringBusFactory bf = new SpringBusFactory();
         URL busFile = RESTUnitTest.class.getResource("cxf-client.xml");
@@ -698,12 +710,83 @@ public class RESTUnitTest extends AbstractBusClientServerTestBase {
         SpringBusFactory.setThreadDefaultBus(bus);
         
         String address = "https://localhost:" + STSPORT + "/SecurityTokenService/token";
-        WebClient client = WebClient.create(address, "alice", "clarinet", busFile.toString());
+        WebClient client = WebClient.create(address, busFile.toString());
+
+        client.type("application/json").accept("application/json");
+        client.path("jwt");
+        
+        Response response = client.get();
+        String token = response.readEntity(String.class);
+        assertNotNull(token);
+        
+        validateJWTToken(token, null);
+    }
+    
+    @org.junit.Test
+    public void testIssueJWTTokenAppliesTo() throws Exception {
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = RESTUnitTest.class.getResource("cxf-client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        SpringBusFactory.setDefaultBus(bus);
+        SpringBusFactory.setThreadDefaultBus(bus);
+        
+        String address = "https://localhost:" + STSPORT + "/SecurityTokenService/token";
+        WebClient client = WebClient.create(address, busFile.toString());
 
         client.type("application/json").accept("application/json");
         client.path("jwt");
+        client.query("appliesTo", DEFAULT_ADDRESS);
+        
+        Response response = client.get();
+        String token = response.readEntity(String.class);
+        assertNotNull(token);
         
-        client.get();
+        validateJWTToken(token, DEFAULT_ADDRESS);
+    }
+    
+    @org.junit.Test
+    public void testIssueJWTTokenClaims() throws Exception {
+        SpringBusFactory bf = new SpringBusFactory();
+        URL busFile = RESTUnitTest.class.getResource("cxf-client.xml");
+
+        Bus bus = bf.createBus(busFile.toString());
+        SpringBusFactory.setDefaultBus(bus);
+        SpringBusFactory.setThreadDefaultBus(bus);
+        
+        String address = "https://localhost:" + STSPORT + "/SecurityTokenService/token";
+        WebClient client = WebClient.create(address, busFile.toString());
+
+        client.type("application/json").accept("application/json");
+        client.path("jwt");
+        
+        // First check that the role isn't usually in the generated token
+        
+        Response response = client.get();
+        String token = response.readEntity(String.class);
+        assertNotNull(token);
+        
+        JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+        JwtToken jwt = jwtConsumer.getJwtToken();
+        
+        String role = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role";
+        assertTrue(jwt.getClaim(role) == null);
+        
+        // Now get another token specifying the role
+        client.query("claim", role);
+        
+        response = client.get();
+        token = response.readEntity(String.class);
+        assertNotNull(token);
+        
+        // Process the token
+        validateJWTToken(token, null);
+        
+        jwtConsumer = new JwsJwtCompactConsumer(token);
+        jwt = jwtConsumer.getJwtToken();
+        assertEquals("ordinary-user", jwt.getClaim(role));
+        
+        bus.shutdown(true);
     }
     
     private Element validateSAMLSecurityTokenResponse(
@@ -755,4 +838,29 @@ public class RESTUnitTest extends AbstractBusClientServerTestBase {
         );
     }
     
+    private void validateJWTToken(String token, String audience) 
+        throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
+        JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+        JwtToken jwt = jwtConsumer.getJwtToken();
+        
+        // Validate claims
+        Assert.assertEquals("DoubleItSTSIssuer", jwt.getClaim(JwtConstants.CLAIM_ISSUER));
+        if (audience != null) {
+            @SuppressWarnings("unchecked")
+            List<String> audiences = (List<String>)jwt.getClaim(JwtConstants.CLAIM_AUDIENCE);
+            assertEquals(1, audiences.size());
+            Assert.assertEquals(audience, audiences.get(0));
+        }
+        Assert.assertNotNull(jwt.getClaim(JwtConstants.CLAIM_EXPIRY));
+        Assert.assertNotNull(jwt.getClaim(JwtConstants.CLAIM_ISSUED_AT));
+
+        KeyStore keystore = KeyStore.getInstance("JKS");
+        keystore.load(Loader.getResource("servicestore.jks").openStream(), "sspass".toCharArray());
+        Certificate cert = keystore.getCertificate("mystskey");
+        Assert.assertNotNull(cert);
+        
+        Assert.assertTrue(jwtConsumer.verifySignatureWith((X509Certificate)cert, 
+                                                          SignatureAlgorithm.RS256));
+    }
+    
 }