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 2015/11/10 13:48:56 UTC
[1/3] cxf git commit: Store JWT tokens in the cache
Repository: cxf
Updated Branches:
refs/heads/3.1.x-fixes 2814cce0d -> 9320bea65
Store JWT tokens in the cache
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/24338419
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/24338419
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/24338419
Branch: refs/heads/3.1.x-fixes
Commit: 243384197f8c395ae001ae0c3ea87aa9724dcda0
Parents: 2814cce
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Nov 10 11:19:49 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Nov 10 12:48:43 2015 +0000
----------------------------------------------------------------------
.../token/provider/jwt/JWTTokenProvider.java | 44 ++++++++------------
.../token/provider/JWTTokenProviderTest.java | 34 +++++++++++++++
2 files changed, 52 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/24338419/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/jwt/JWTTokenProvider.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/jwt/JWTTokenProvider.java b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/jwt/JWTTokenProvider.java
index 0f5a383..5afffda 100644
--- a/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/jwt/JWTTokenProvider.java
+++ b/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/jwt/JWTTokenProvider.java
@@ -42,12 +42,14 @@ import org.apache.cxf.rs.security.jose.jwt.JwtClaims;
import org.apache.cxf.rs.security.jose.jwt.JwtToken;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.SignatureProperties;
+import org.apache.cxf.sts.cache.CacheUtils;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.token.provider.TokenProvider;
import org.apache.cxf.sts.token.provider.TokenProviderParameters;
import org.apache.cxf.sts.token.provider.TokenProviderResponse;
import org.apache.cxf.sts.token.realm.RealmProperties;
import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.Merlin;
import org.apache.wss4j.common.ext.WSPasswordCallback;
@@ -109,31 +111,6 @@ public class JWTTokenProvider implements TokenProvider {
JwtClaims claims = jwtClaimsProvider.getJwtClaims(jwtClaimsProviderParameters);
try {
- /*
- Document doc = DOMUtils.createDocument();
- SamlAssertionWrapper assertion = createSamlToken(tokenParameters, secret, doc);
- Element token = assertion.toDOM(doc);
-
- // set the token in cache (only if the token is signed)
- byte[] signatureValue = assertion.getSignatureValue();
- if (tokenParameters.getTokenStore() != null && signatureValue != null
- && signatureValue.length > 0) {
- DateTime validTill = null;
- if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)) {
- validTill = assertion.getSaml2().getConditions().getNotOnOrAfter();
- } else {
- validTill = assertion.getSaml1().getConditions().getNotOnOrAfter();
- }
-
- SecurityToken securityToken =
- CacheUtils.createSecurityTokenForStorage(token, assertion.getId(),
- validTill.toDate(), tokenParameters.getPrincipal(), tokenParameters.getRealm(),
- tokenParameters.getTokenRequirements().getRenewing());
- CacheUtils.storeTokenInCache(
- securityToken, tokenParameters.getTokenStore(), signatureValue);
- }
- */
-
JwtToken token = new JwtToken(claims);
String tokenData = signToken(token, jwtRealm, tokenParameters.getStsProperties(),
@@ -147,8 +124,23 @@ public class JWTTokenProvider implements TokenProvider {
if (claims.getIssuedAt() > 0) {
response.setCreated(new Date(claims.getIssuedAt() * 1000L));
}
+ Date expires = null;
if (claims.getExpiryTime() > 0) {
- response.setExpires(new Date(claims.getExpiryTime() * 1000L));
+ expires = new Date(claims.getExpiryTime() * 1000L);
+ response.setExpires(expires);
+ }
+
+ // set the token in cache (only if the token is signed)
+ if (signToken && tokenParameters.getTokenStore() != null) {
+ SecurityToken securityToken =
+ CacheUtils.createSecurityTokenForStorage(null, claims.getTokenId(),
+ expires, tokenParameters.getPrincipal(), tokenParameters.getRealm(),
+ tokenParameters.getTokenRequirements().getRenewing());
+ securityToken.setData(tokenData.getBytes());
+
+ String signature = tokenData.substring(tokenData.lastIndexOf(".") + 1);
+ CacheUtils.storeTokenInCache(
+ securityToken, tokenParameters.getTokenStore(), signature.getBytes());
}
LOG.fine("JWT Token successfully created");
http://git-wip-us.apache.org/repos/asf/cxf/blob/24338419/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTTokenProviderTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTTokenProviderTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTTokenProviderTest.java
index aed28ef..6273e0e 100644
--- a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTTokenProviderTest.java
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTTokenProviderTest.java
@@ -19,6 +19,7 @@
package org.apache.cxf.sts.token.provider;
import java.security.cert.X509Certificate;
+import java.util.Arrays;
import java.util.Properties;
import org.apache.cxf.jaxws.context.WebServiceContextImpl;
@@ -35,6 +36,7 @@ import org.apache.cxf.sts.request.KeyRequirements;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.service.EncryptionProperties;
import org.apache.cxf.sts.token.provider.jwt.JWTTokenProvider;
+import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.tokenstore.TokenStore;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
@@ -113,6 +115,38 @@ public class JWTTokenProviderTest extends org.junit.Assert {
assertTrue(jwtConsumer.verifySignatureWith(certs[0], SignatureAlgorithm.RS256));
}
+ @org.junit.Test
+ public void testCachedSignedJWT() throws Exception {
+ TokenProvider jwtTokenProvider = new JWTTokenProvider();
+ ((JWTTokenProvider)jwtTokenProvider).setSignToken(true);
+
+ TokenProviderParameters providerParameters = createProviderParameters();
+
+ assertTrue(jwtTokenProvider.canHandleToken(JWTTokenProvider.JWT_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = jwtTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ String token = (String)providerResponse.getToken();
+ assertNotNull(token);
+ assertTrue(token.split("\\.").length == 3);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("alice", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ Assert.assertEquals(providerResponse.getTokenId(), jwt.getClaim(JwtConstants.CLAIM_JWT_ID));
+ Assert.assertEquals(providerResponse.getCreated().getTime() / 1000L,
+ jwt.getClaim(JwtConstants.CLAIM_ISSUED_AT));
+ Assert.assertEquals(providerResponse.getExpires().getTime() / 1000L,
+ jwt.getClaim(JwtConstants.CLAIM_EXPIRY));
+
+ // Check that the token is stored correctly in the cache
+ String signature = token.substring(token.lastIndexOf(".") + 1);
+ SecurityToken secToken = tokenStore.getToken(Integer.toString(Arrays.hashCode(signature.getBytes())));
+ Assert.assertNotNull(secToken);
+ }
+
private TokenProviderParameters createProviderParameters() throws WSSecurityException {
TokenProviderParameters parameters = new TokenProviderParameters();
[3/3] cxf git commit: Removing unused variable
Posted by co...@apache.org.
Removing unused variable
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/9320bea6
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/9320bea6
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/9320bea6
Branch: refs/heads/3.1.x-fixes
Commit: 9320bea658e97e54d2bd9d47ad07313c388079f9
Parents: 362437e
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Nov 10 12:14:54 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Nov 10 12:48:46 2015 +0000
----------------------------------------------------------------------
parent/pom.xml | 1 -
1 file changed, 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/9320bea6/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 751f730..8244caf 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -76,7 +76,6 @@
<cxf.cglib.bundle.version>2.2_2</cxf.cglib.bundle.version>
<cxf.cglib.osgi.version>[2.1.3,3.0.0)</cxf.cglib.osgi.version>
<cxf.commons-codec.version>1.10</cxf.commons-codec.version>
- <cxf.commons-collections.version>3.2.1</cxf.commons-collections.version>
<cxf.commons-lang.version>2.6</cxf.commons-lang.version>
<cxf.commons-lang3.version>3.4</cxf.commons-lang3.version>
<cxf.derby.version>10.2.2.0</cxf.derby.version>
[2/3] cxf git commit: Adding some OnBehalfOf/ActAs tests for JWT
tokens
Posted by co...@apache.org.
Adding some OnBehalfOf/ActAs tests for JWT tokens
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/362437e2
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/362437e2
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/362437e2
Branch: refs/heads/3.1.x-fixes
Commit: 362437e222ea79e92078323d865fb0b2d7195610
Parents: 2433841
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Nov 10 12:12:17 2015 +0000
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Nov 10 12:48:45 2015 +0000
----------------------------------------------------------------------
.../sts/operation/IssueJWTClaimsUnitTest.java | 108 ++--
.../operation/IssueJWTOnbehalfofUnitTest.java | 507 +++++++++++++++++++
.../token/provider/JWTProviderActAsTest.java | 196 +++++++
.../provider/JWTProviderOnBehalfOfTest.java | 196 +++++++
4 files changed, 947 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/362437e2/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTClaimsUnitTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTClaimsUnitTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTClaimsUnitTest.java
index 5e92191..ab20e96 100644
--- a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTClaimsUnitTest.java
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTClaimsUnitTest.java
@@ -77,7 +77,6 @@ import org.apache.cxf.ws.security.sts.provider.model.OnBehalfOfType;
import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseCollectionType;
import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseType;
import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType;
-import org.apache.cxf.ws.security.sts.provider.model.RequestedSecurityTokenType;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.ext.WSSecurityException;
@@ -283,14 +282,12 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
}
/**
- * Test to successfully issue a SAML 2 token (realm "B") on-behalf-of a SAML 2 token
+ * Test to successfully issue a JWT token (realm "B") on-behalf-of a SAML 2 token
* which was issued by realm "A".
* The relationship type between realm A and B is: FederateClaims
- * TODO
*/
@org.junit.Test
- @org.junit.Ignore
- public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateClaims()
+ public void testIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateClaims()
throws Exception {
TokenIssueOperation issueOperation = new TokenIssueOperation();
@@ -298,13 +295,9 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
// Add Token Provider
List<TokenProvider> providerList = new ArrayList<TokenProvider>();
- SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
- samlTokenProvider.setRealmMap(realms);
- List<AttributeStatementProvider> customProviderList =
- new ArrayList<AttributeStatementProvider>();
- customProviderList.add(new ClaimsAttributeStatementProvider());
- samlTokenProvider.setAttributeStatementProviders(customProviderList);
- providerList.add(samlTokenProvider);
+ JWTTokenProvider tokenProvider = new JWTTokenProvider();
+ tokenProvider.setRealmMap(realms);
+ providerList.add(tokenProvider);
issueOperation.setTokenProviders(providerList);
TokenDelegationHandler delegationHandler = new SAMLDelegationHandler();
@@ -342,7 +335,7 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
RequestSecurityTokenType request = new RequestSecurityTokenType();
JAXBElement<String> tokenType =
new JAXBElement<String>(
- QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+ QNameConstants.TOKEN_TYPE, String.class, JWTTokenProvider.JWT_TOKEN_TYPE
);
request.getAny().add(tokenType);
@@ -392,57 +385,55 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
List<RequestSecurityTokenResponseType> securityTokenResponseList = issueToken(issueOperation,
request, webServiceContext);
- RequestSecurityTokenResponseType securityTokenResponse = securityTokenResponseList.get(0);
// Test the generated token.
- Element assertion = null;
- for (Object tokenObject : securityTokenResponse.getAny()) {
- if (tokenObject instanceof JAXBElement<?>
- && REQUESTED_SECURITY_TOKEN.equals(((JAXBElement<?>)tokenObject).getName())) {
- RequestedSecurityTokenType rstType =
- (RequestedSecurityTokenType)((JAXBElement<?>)tokenObject).getValue();
- assertion = (Element)rstType.getAny();
+ String jwtToken = null;
+ for (Object tokenObject : securityTokenResponseList.get(0).getAny()) {
+ if (tokenObject instanceof Element
+ && REQUESTED_SECURITY_TOKEN.getLocalPart().equals(((Element)tokenObject).getLocalName())
+ && REQUESTED_SECURITY_TOKEN.getNamespaceURI().equals(((Element)tokenObject).getNamespaceURI())) {
+ jwtToken = ((Element)tokenObject).getTextContent();
break;
}
}
- assertNotNull(assertion);
- String tokenString = DOM2Writer.nodeToString(assertion);
- assertTrue(tokenString.contains("AttributeStatement"));
- assertTrue(tokenString.contains("alice")); //subject unchanged
- assertTrue(tokenString.contains("DOE")); //transformed claim (to uppercase)
- assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
+
+ assertNotNull(jwtToken);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(jwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ // subject unchanged
+ Assert.assertEquals("alice", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ // transformed claim (to uppercase)
+ assertEquals(jwt.getClaim(ClaimTypes.LASTNAME.toString()), "DOE");
}
/**
- * Test to successfully issue a SAML 2 token (realm "B") on-behalf-of a SAML 2 token
+ * Test to successfully issue a JWT token (realm "B") on-behalf-of a SAML 2 token
* which was issued by realm "A".
* The relationship type between realm A and B is: FederateIdentity
* IdentityMapper is configured globally in STSPropertiesMBean
- * TODO
*/
@org.junit.Test
- @org.junit.Ignore
- public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentityGlobalConfig()
+ public void testIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateIdentityGlobalConfig()
throws Exception {
- runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(true);
+ runIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateIdentity(true);
}
/**
- * Test to successfully issue a SAML 2 token (realm "B") on-behalf-of a SAML 2 token
+ * Test to successfully issue a JWT token (realm "B") on-behalf-of a SAML 2 token
* which was issued by realm "A".
* The relationship type between realm A and B is: FederateIdentity
* IdentityMapper is configured in the Relationship
- * TODO
*/
@org.junit.Test
- @org.junit.Ignore
- public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentityRelationshipConfig()
+ public void testIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateIdentityRelationshipConfig()
throws Exception {
- runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(false);
+ runIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateIdentity(false);
}
- private void runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(
+ private void runIssueJWTTokenOnBehalfOfSaml2DifferentRealmFederateIdentity(
boolean useGlobalIdentityMapper) throws WSSecurityException {
TokenIssueOperation issueOperation = new TokenIssueOperation();
@@ -450,13 +441,9 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
// Add Token Provider
List<TokenProvider> providerList = new ArrayList<TokenProvider>();
- SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
- samlTokenProvider.setRealmMap(realms);
- List<AttributeStatementProvider> customProviderList =
- new ArrayList<AttributeStatementProvider>();
- customProviderList.add(new ClaimsAttributeStatementProvider());
- samlTokenProvider.setAttributeStatementProviders(customProviderList);
- providerList.add(samlTokenProvider);
+ JWTTokenProvider tokenProvider = new JWTTokenProvider();
+ tokenProvider.setRealmMap(realms);
+ providerList.add(tokenProvider);
issueOperation.setTokenProviders(providerList);
TokenDelegationHandler delegationHandler = new SAMLDelegationHandler();
@@ -500,7 +487,7 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
RequestSecurityTokenType request = new RequestSecurityTokenType();
JAXBElement<String> tokenType =
new JAXBElement<String>(
- QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+ QNameConstants.TOKEN_TYPE, String.class, JWTTokenProvider.JWT_TOKEN_TYPE
);
request.getAny().add(tokenType);
@@ -550,26 +537,27 @@ public class IssueJWTClaimsUnitTest extends org.junit.Assert {
List<RequestSecurityTokenResponseType> securityTokenResponseList = issueToken(issueOperation,
request, webServiceContext);
- RequestSecurityTokenResponseType securityTokenResponse = securityTokenResponseList.get(0);
// Test the generated token.
- Element assertion = null;
- for (Object tokenObject : securityTokenResponse.getAny()) {
- if (tokenObject instanceof JAXBElement<?>
- && REQUESTED_SECURITY_TOKEN.equals(((JAXBElement<?>)tokenObject).getName())) {
- RequestedSecurityTokenType rstType =
- (RequestedSecurityTokenType)((JAXBElement<?>)tokenObject).getValue();
- assertion = (Element)rstType.getAny();
+ String jwtToken = null;
+ for (Object tokenObject : securityTokenResponseList.get(0).getAny()) {
+ if (tokenObject instanceof Element
+ && REQUESTED_SECURITY_TOKEN.getLocalPart().equals(((Element)tokenObject).getLocalName())
+ && REQUESTED_SECURITY_TOKEN.getNamespaceURI().equals(((Element)tokenObject).getNamespaceURI())) {
+ jwtToken = ((Element)tokenObject).getTextContent();
break;
}
}
- assertNotNull(assertion);
- String tokenString = DOM2Writer.nodeToString(assertion);
- assertTrue(tokenString.contains("AttributeStatement"));
- assertTrue(tokenString.contains("ALICE")); //subject changed (to uppercase)
- assertTrue(tokenString.contains("doe")); //claim unchanged but requested
- assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
+ assertNotNull(jwtToken);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(jwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ // subject changed (to uppercase)
+ Assert.assertEquals("ALICE", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ // claim unchanged but requested
+ assertEquals(jwt.getClaim(ClaimTypes.LASTNAME.toString()), "doe");
}
http://git-wip-us.apache.org/repos/asf/cxf/blob/362437e2/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTOnbehalfofUnitTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTOnbehalfofUnitTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTOnbehalfofUnitTest.java
new file mode 100644
index 0000000..dc2352f
--- /dev/null
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueJWTOnbehalfofUnitTest.java
@@ -0,0 +1,507 @@
+/**
+ * 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.cxf.sts.operation;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.jaxws.context.WebServiceContextImpl;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.message.MessageImpl;
+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.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.STSPropertiesMBean;
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.common.PasswordCallbackHandler;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedKey;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.service.ServiceMBean;
+import org.apache.cxf.sts.service.StaticService;
+import org.apache.cxf.sts.token.delegation.SAMLDelegationHandler;
+import org.apache.cxf.sts.token.delegation.TokenDelegationHandler;
+import org.apache.cxf.sts.token.delegation.UsernameTokenDelegationHandler;
+import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProvider;
+import org.apache.cxf.sts.token.provider.TokenProviderParameters;
+import org.apache.cxf.sts.token.provider.TokenProviderResponse;
+import org.apache.cxf.sts.token.provider.jwt.JWTTokenProvider;
+import org.apache.cxf.sts.token.realm.RealmProperties;
+import org.apache.cxf.sts.token.validator.IssuerSAMLRealmCodec;
+import org.apache.cxf.sts.token.validator.SAMLTokenValidator;
+import org.apache.cxf.sts.token.validator.TokenValidator;
+import org.apache.cxf.sts.token.validator.UsernameTokenValidator;
+import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.cxf.ws.security.sts.provider.model.OnBehalfOfType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseCollectionType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenResponseType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType;
+import org.apache.cxf.ws.security.sts.provider.model.secext.AttributedString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.PasswordString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.crypto.CryptoType;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.principal.CustomTokenPrincipal;
+import org.apache.wss4j.dom.WSConstants;
+import org.junit.Assert;
+
+/**
+ * Issue JWT tokens on behalf of other tokens.
+ */
+public class IssueJWTOnbehalfofUnitTest extends org.junit.Assert {
+
+ public static final QName REQUESTED_SECURITY_TOKEN =
+ QNameConstants.WS_TRUST_FACTORY.createRequestedSecurityToken(null).getName();
+
+ /**
+ * Test to successfully issue a JWT token on-behalf-of a SAML 2 token
+ */
+ @org.junit.Test
+ public void testIssueJWTTokenOnBehalfOfSaml2() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ providerList.add(new JWTTokenProvider());
+ issueOperation.setTokenProviders(providerList);
+
+ // Add Token Validator
+ List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+ validatorList.add(new SAMLTokenValidator());
+ issueOperation.setTokenValidators(validatorList);
+
+ // Add Service
+ ServiceMBean service = new StaticService();
+ service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+ issueOperation.setServices(Collections.singletonList(service));
+
+ // Add STSProperties object
+ STSPropertiesMBean stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setEncryptionCrypto(crypto);
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ issueOperation.setStsProperties(stsProperties);
+
+ TokenDelegationHandler delegationHandler = new SAMLDelegationHandler();
+ issueOperation.setDelegationHandlers(Collections.singletonList(delegationHandler));
+
+ // Mock up a request
+ RequestSecurityTokenType request = new RequestSecurityTokenType();
+ JAXBElement<String> tokenType =
+ new JAXBElement<String>(
+ QNameConstants.TOKEN_TYPE, String.class, JWTTokenProvider.JWT_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+ // Get a SAML Token via the SAMLTokenProvider
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey", callbackHandler);
+ Document doc = samlToken.getOwnerDocument();
+ samlToken = (Element)doc.appendChild(samlToken);
+ OnBehalfOfType onbehalfof = new OnBehalfOfType();
+ onbehalfof.setAny(samlToken);
+
+ JAXBElement<OnBehalfOfType> onbehalfofType =
+ new JAXBElement<OnBehalfOfType>(
+ QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+ );
+ request.getAny().add(onbehalfofType);
+
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+ // Issue a token
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponse =
+ response.getRequestSecurityTokenResponse();
+ assertTrue(!securityTokenResponse.isEmpty());
+
+ // Test the generated token.
+ String jwtToken = null;
+ for (Object tokenObject : securityTokenResponse.get(0).getAny()) {
+ if (tokenObject instanceof Element
+ && REQUESTED_SECURITY_TOKEN.getLocalPart().equals(((Element)tokenObject).getLocalName())
+ && REQUESTED_SECURITY_TOKEN.getNamespaceURI().equals(((Element)tokenObject).getNamespaceURI())) {
+ jwtToken = ((Element)tokenObject).getTextContent();
+ break;
+ }
+ }
+
+ assertNotNull(jwtToken);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(jwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("alice", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ /**
+ * Test to successfully issue a JWT token on-behalf-of a UsernameToken
+ */
+ @org.junit.Test
+ public void testIssueJWTTokenOnBehalfOfUsernameToken() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ providerList.add(new JWTTokenProvider());
+ issueOperation.setTokenProviders(providerList);
+
+ // Add Token Validator
+ List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+ validatorList.add(new UsernameTokenValidator());
+ issueOperation.setTokenValidators(validatorList);
+
+ // Add Service
+ ServiceMBean service = new StaticService();
+ service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+ issueOperation.setServices(Collections.singletonList(service));
+
+ // Add STSProperties object
+ STSPropertiesMBean stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setEncryptionCrypto(crypto);
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ issueOperation.setStsProperties(stsProperties);
+
+ // Mock up a request
+ RequestSecurityTokenType request = new RequestSecurityTokenType();
+ JAXBElement<String> tokenType =
+ new JAXBElement<String>(
+ QNameConstants.TOKEN_TYPE, String.class, JWTTokenProvider.JWT_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+
+ // Create a UsernameToken
+ JAXBElement<UsernameTokenType> usernameTokenType = createUsernameToken("alice", "clarinet");
+ OnBehalfOfType onbehalfof = new OnBehalfOfType();
+ onbehalfof.setAny(usernameTokenType);
+
+ JAXBElement<OnBehalfOfType> onbehalfofType =
+ new JAXBElement<OnBehalfOfType>(
+ QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+ );
+ request.getAny().add(onbehalfofType);
+
+
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+ // Issue a token
+
+ // This should fail as the default DelegationHandler does not allow UsernameTokens
+ try {
+ issueOperation.issue(request, webServiceContext);
+ fail("Failure expected as UsernameTokens are not accepted for OnBehalfOf by default");
+ } catch (STSException ex) {
+ // expected
+ }
+
+ TokenDelegationHandler delegationHandler = new UsernameTokenDelegationHandler();
+ issueOperation.setDelegationHandlers(Collections.singletonList(delegationHandler));
+
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponse =
+ response.getRequestSecurityTokenResponse();
+ assertTrue(!securityTokenResponse.isEmpty());
+
+ // Test the generated token.
+ String jwtToken = null;
+ for (Object tokenObject : securityTokenResponse.get(0).getAny()) {
+ if (tokenObject instanceof Element
+ && REQUESTED_SECURITY_TOKEN.getLocalPart().equals(((Element)tokenObject).getLocalName())
+ && REQUESTED_SECURITY_TOKEN.getNamespaceURI().equals(((Element)tokenObject).getNamespaceURI())) {
+ jwtToken = ((Element)tokenObject).getTextContent();
+ break;
+ }
+ }
+
+ assertNotNull(jwtToken);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(jwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("alice", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ /**
+ * Test to successfully issue a JWT Token (realm "B") on-behalf-of a SAML 2 token
+ * on-behalf-of token issued by realm "A".
+ */
+ @org.junit.Test
+ public void testIssueJWTTokenOnBehalfOfSaml2DifferentRealm() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ JWTTokenProvider tokenProvider = new JWTTokenProvider();
+ providerList.add(tokenProvider);
+ issueOperation.setTokenProviders(providerList);
+
+ TokenDelegationHandler delegationHandler = new SAMLDelegationHandler();
+ issueOperation.setDelegationHandlers(Collections.singletonList(delegationHandler));
+
+ // Add Token Validator
+ List<TokenValidator> validatorList = new ArrayList<TokenValidator>();
+ SAMLTokenValidator samlTokenValidator = new SAMLTokenValidator();
+ samlTokenValidator.setSamlRealmCodec(new IssuerSAMLRealmCodec());
+ validatorList.add(samlTokenValidator);
+ issueOperation.setTokenValidators(validatorList);
+
+ // Add Service
+ ServiceMBean service = new StaticService();
+ service.setEndpoints(Collections.singletonList("http://dummy-service.com/dummy"));
+ issueOperation.setServices(Collections.singletonList(service));
+
+ // Add STSProperties object
+ STSPropertiesMBean stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setEncryptionCrypto(crypto);
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ stsProperties.setRealmParser(new CustomRealmParser());
+ stsProperties.setIdentityMapper(new CustomIdentityMapper());
+ issueOperation.setStsProperties(stsProperties);
+
+ Map<String, RealmProperties> realms = createSamlRealms();
+
+ // Mock up a request
+ RequestSecurityTokenType request = new RequestSecurityTokenType();
+ JAXBElement<String> tokenType =
+ new JAXBElement<String>(
+ QNameConstants.TOKEN_TYPE, String.class, JWTTokenProvider.JWT_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+ // Get a SAML Token via the SAMLTokenProvider
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey",
+ callbackHandler, realms, STSConstants.BEARER_KEY_KEYTYPE);
+ Document doc = samlToken.getOwnerDocument();
+ samlToken = (Element)doc.appendChild(samlToken);
+ OnBehalfOfType onbehalfof = new OnBehalfOfType();
+ onbehalfof.setAny(samlToken);
+
+ JAXBElement<OnBehalfOfType> onbehalfofType =
+ new JAXBElement<OnBehalfOfType>(
+ QNameConstants.ON_BEHALF_OF, OnBehalfOfType.class, onbehalfof
+ );
+ request.getAny().add(onbehalfofType);
+
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ msgCtx.put("url", "https");
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+
+ tokenProvider.setRealmMap(realms);
+
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponse =
+ response.getRequestSecurityTokenResponse();
+ assertTrue(!securityTokenResponse.isEmpty());
+
+ // Test the generated token.
+ String jwtToken = null;
+ for (Object tokenObject : securityTokenResponse.get(0).getAny()) {
+ if (tokenObject instanceof Element
+ && REQUESTED_SECURITY_TOKEN.getLocalPart().equals(((Element)tokenObject).getLocalName())
+ && REQUESTED_SECURITY_TOKEN.getNamespaceURI().equals(((Element)tokenObject).getNamespaceURI())) {
+ jwtToken = ((Element)tokenObject).getTextContent();
+ break;
+ }
+ }
+
+ assertNotNull(jwtToken);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(jwtToken);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("ALICE", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ /*
+ * Mock up an SAML assertion element
+ */
+ private Element createSAMLAssertion(
+ String tokenType, Crypto crypto, String signatureUsername, CallbackHandler callbackHandler
+ ) throws WSSecurityException {
+ return createSAMLAssertion(tokenType, crypto, signatureUsername,
+ callbackHandler, null, STSConstants.BEARER_KEY_KEYTYPE);
+ }
+
+ /*
+ * Mock up an SAML assertion element
+ */
+ private Element createSAMLAssertion(
+ String tokenType, Crypto crypto, String signatureUsername, CallbackHandler callbackHandler,
+ Map<String, RealmProperties> realms, String keyType
+ ) throws WSSecurityException {
+ SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
+ samlTokenProvider.setRealmMap(realms);
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ tokenType, keyType, crypto, signatureUsername, callbackHandler
+ );
+ if (realms != null) {
+ providerParameters.setRealm("A");
+ }
+ TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ return (Element)providerResponse.getToken();
+ }
+
+ private TokenProviderParameters createProviderParameters(
+ String tokenType, String keyType, Crypto crypto,
+ String signatureUsername, CallbackHandler callbackHandler
+ ) throws WSSecurityException {
+ TokenProviderParameters parameters = new TokenProviderParameters();
+
+ TokenRequirements tokenRequirements = new TokenRequirements();
+ tokenRequirements.setTokenType(tokenType);
+ parameters.setTokenRequirements(tokenRequirements);
+
+ KeyRequirements keyRequirements = new KeyRequirements();
+ keyRequirements.setKeyType(keyType);
+
+ CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+ cryptoType.setAlias("myclientkey");
+ X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
+ ReceivedKey receivedKey = new ReceivedKey();
+ receivedKey.setX509Cert(certs[0]);
+ keyRequirements.setReceivedKey(receivedKey);
+
+ parameters.setKeyRequirements(keyRequirements);
+
+ parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+ parameters.setWebServiceContext(webServiceContext);
+
+ parameters.setAppliesToAddress("http://dummy-service.com/dummy");
+
+ // Add STSProperties object
+ StaticSTSProperties stsProperties = new StaticSTSProperties();
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setSignatureUsername(signatureUsername);
+ stsProperties.setCallbackHandler(callbackHandler);
+ stsProperties.setIssuer("STS");
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setEncryptionCrypto(crypto);
+ parameters.setStsProperties(stsProperties);
+
+ parameters.setEncryptionProperties(new EncryptionProperties());
+
+ return parameters;
+ }
+
+ private JAXBElement<UsernameTokenType> createUsernameToken(String name, String password) {
+ UsernameTokenType usernameToken = new UsernameTokenType();
+ AttributedString username = new AttributedString();
+ username.setValue(name);
+ usernameToken.setUsername(username);
+
+ // Add a password
+ if (password != null) {
+ PasswordString passwordString = new PasswordString();
+ passwordString.setValue(password);
+ passwordString.setType(WSConstants.PASSWORD_TEXT);
+ JAXBElement<PasswordString> passwordType =
+ new JAXBElement<PasswordString>(
+ QNameConstants.PASSWORD, PasswordString.class, passwordString
+ );
+ usernameToken.getAny().add(passwordType);
+ }
+
+ JAXBElement<UsernameTokenType> tokenType =
+ new JAXBElement<UsernameTokenType>(
+ QNameConstants.USERNAME_TOKEN, UsernameTokenType.class, usernameToken
+ );
+
+ return tokenType;
+ }
+
+ private Map<String, RealmProperties> createSamlRealms() {
+ // Create Realms
+ Map<String, RealmProperties> samlRealms = new HashMap<String, RealmProperties>();
+ RealmProperties samlRealm = new RealmProperties();
+ samlRealm.setIssuer("A-Issuer");
+ samlRealms.put("A", samlRealm);
+ samlRealm = new RealmProperties();
+ samlRealm.setIssuer("B-Issuer");
+ samlRealms.put("B", samlRealm);
+ return samlRealms;
+ }
+
+ private Properties getEncryptionProperties() {
+ Properties properties = new Properties();
+ properties.put(
+ "org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"
+ );
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.password", "stsspass");
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.file", "stsstore.jks");
+
+ return properties;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/362437e2/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderActAsTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderActAsTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderActAsTest.java
new file mode 100644
index 0000000..9e0fcd6
--- /dev/null
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderActAsTest.java
@@ -0,0 +1,196 @@
+/**
+ * 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.cxf.sts.token.provider;
+
+import java.util.Properties;
+
+import javax.xml.bind.JAXBElement;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.jaxws.context.WebServiceContextImpl;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.message.MessageImpl;
+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.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.common.PasswordCallbackHandler;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.token.provider.jwt.JWTTokenProvider;
+import org.apache.cxf.ws.security.sts.provider.model.secext.AttributedString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.principal.CustomTokenPrincipal;
+import org.apache.wss4j.dom.WSConstants;
+import org.junit.Assert;
+
+/**
+ * Some unit tests for creating JWT Tokens with an ActAs element.
+ */
+public class JWTProviderActAsTest extends org.junit.Assert {
+
+ /**
+ * Create a JWT Token with ActAs from a UsernameToken
+ */
+ @org.junit.Test
+ public void testJWTActAsUsernameToken() throws Exception {
+ TokenProvider tokenProvider = new JWTTokenProvider();
+
+ UsernameTokenType usernameToken = new UsernameTokenType();
+ AttributedString username = new AttributedString();
+ username.setValue("bob");
+ usernameToken.setUsername(username);
+ JAXBElement<UsernameTokenType> usernameTokenType =
+ new JAXBElement<UsernameTokenType>(
+ QNameConstants.USERNAME_TOKEN, UsernameTokenType.class, usernameToken
+ );
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ JWTTokenProvider.JWT_TOKEN_TYPE, usernameTokenType
+ );
+ //Principal must be set in ReceivedToken/ActAs
+ providerParameters.getTokenRequirements().getActAs().setPrincipal(
+ new CustomTokenPrincipal(username.getValue()));
+
+ assertTrue(tokenProvider.canHandleToken(JWTTokenProvider.JWT_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = tokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ String token = (String)providerResponse.getToken();
+ assertNotNull(token);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("bob", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ /**
+ * Create a JWT Token with ActAs from a SAML Assertion
+ */
+ @org.junit.Test
+ public void testJWTActAsAssertion() throws Exception {
+ TokenProvider tokenProvider = new JWTTokenProvider();
+
+ String user = "alice";
+ Element saml1Assertion = getSAMLAssertion(user);
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ JWTTokenProvider.JWT_TOKEN_TYPE, saml1Assertion
+ );
+ //Principal must be set in ReceivedToken/ActAs
+ providerParameters.getTokenRequirements().getActAs().setPrincipal(
+ new CustomTokenPrincipal(user));
+
+ assertTrue(tokenProvider.canHandleToken(JWTTokenProvider.JWT_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = tokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ String token = (String)providerResponse.getToken();
+ assertNotNull(token);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals(user, jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ private Element getSAMLAssertion(String user) throws Exception {
+ TokenProvider samlTokenProvider = new SAMLTokenProvider();
+ TokenProviderParameters providerParameters =
+ createProviderParameters(WSConstants.WSS_SAML_TOKEN_TYPE, null);
+ providerParameters.getKeyRequirements().setKeyType(STSConstants.BEARER_KEY_KEYTYPE);
+ providerParameters.setPrincipal(new CustomTokenPrincipal(user));
+ assertTrue(samlTokenProvider.canHandleToken(WSConstants.WSS_SAML_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ return (Element)providerResponse.getToken();
+ }
+
+ private TokenProviderParameters createProviderParameters(
+ String tokenType, Object actAs
+ ) throws WSSecurityException {
+ TokenProviderParameters parameters = new TokenProviderParameters();
+
+ TokenRequirements tokenRequirements = new TokenRequirements();
+ tokenRequirements.setTokenType(tokenType);
+
+ if (actAs != null) {
+ ReceivedToken actAsToken = new ReceivedToken(actAs);
+ actAsToken.setState(STATE.VALID);
+ tokenRequirements.setActAs(actAsToken);
+
+ }
+ parameters.setTokenRequirements(tokenRequirements);
+
+ KeyRequirements keyRequirements = new KeyRequirements();
+ parameters.setKeyRequirements(keyRequirements);
+
+ parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+ parameters.setWebServiceContext(webServiceContext);
+
+ parameters.setAppliesToAddress("http://dummy-service.com/dummy");
+
+ // Add STSProperties object
+ StaticSTSProperties stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ parameters.setStsProperties(stsProperties);
+
+ parameters.setEncryptionProperties(new EncryptionProperties());
+
+ return parameters;
+ }
+
+ private Properties getEncryptionProperties() {
+ Properties properties = new Properties();
+ properties.put(
+ "org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"
+ );
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.password", "stsspass");
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.file", "stsstore.jks");
+
+ return properties;
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/362437e2/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderOnBehalfOfTest.java
----------------------------------------------------------------------
diff --git a/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderOnBehalfOfTest.java b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderOnBehalfOfTest.java
new file mode 100644
index 0000000..265b48c
--- /dev/null
+++ b/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/JWTProviderOnBehalfOfTest.java
@@ -0,0 +1,196 @@
+/**
+ * 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.cxf.sts.token.provider;
+
+import java.util.Properties;
+
+import javax.xml.bind.JAXBElement;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.jaxws.context.WebServiceContextImpl;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.message.MessageImpl;
+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.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.StaticSTSProperties;
+import org.apache.cxf.sts.common.PasswordCallbackHandler;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.ReceivedToken.STATE;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.token.provider.jwt.JWTTokenProvider;
+import org.apache.cxf.ws.security.sts.provider.model.secext.AttributedString;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.principal.CustomTokenPrincipal;
+import org.apache.wss4j.dom.WSConstants;
+import org.junit.Assert;
+
+/**
+ * Some unit tests for creating JWT Tokens with an OnBehalfOf element.
+ */
+public class JWTProviderOnBehalfOfTest extends org.junit.Assert {
+
+ /**
+ * Create a JWT Token with OnBehalfOf from a UsernameToken
+ */
+ @org.junit.Test
+ public void testJWTOnBehalfOfUsernameToken() throws Exception {
+ TokenProvider tokenProvider = new JWTTokenProvider();
+
+ UsernameTokenType usernameToken = new UsernameTokenType();
+ AttributedString username = new AttributedString();
+ username.setValue("bob");
+ usernameToken.setUsername(username);
+ JAXBElement<UsernameTokenType> usernameTokenType =
+ new JAXBElement<UsernameTokenType>(
+ QNameConstants.USERNAME_TOKEN, UsernameTokenType.class, usernameToken
+ );
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ JWTTokenProvider.JWT_TOKEN_TYPE, usernameTokenType
+ );
+ //Principal must be set in ReceivedToken/OnBehalfOf
+ providerParameters.getTokenRequirements().getOnBehalfOf().setPrincipal(
+ new CustomTokenPrincipal(username.getValue()));
+
+ assertTrue(tokenProvider.canHandleToken(JWTTokenProvider.JWT_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = tokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ String token = (String)providerResponse.getToken();
+ assertNotNull(token);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals("bob", jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ /**
+ * Create a JWT Token with OnBehalfOf from a SAML Assertion
+ */
+ @org.junit.Test
+ public void testJWTOnBehalfOfAssertion() throws Exception {
+ TokenProvider tokenProvider = new JWTTokenProvider();
+
+ String user = "alice";
+ Element saml1Assertion = getSAMLAssertion(user);
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ JWTTokenProvider.JWT_TOKEN_TYPE, saml1Assertion
+ );
+ //Principal must be set in ReceivedToken/OnBehalfOf
+ providerParameters.getTokenRequirements().getOnBehalfOf().setPrincipal(
+ new CustomTokenPrincipal(user));
+
+ assertTrue(tokenProvider.canHandleToken(JWTTokenProvider.JWT_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = tokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ String token = (String)providerResponse.getToken();
+ assertNotNull(token);
+
+ // Validate the token
+ JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(token);
+ JwtToken jwt = jwtConsumer.getJwtToken();
+ Assert.assertEquals(user, jwt.getClaim(JwtConstants.CLAIM_SUBJECT));
+ }
+
+ private Element getSAMLAssertion(String user) throws Exception {
+ TokenProvider samlTokenProvider = new SAMLTokenProvider();
+ TokenProviderParameters providerParameters =
+ createProviderParameters(WSConstants.WSS_SAML_TOKEN_TYPE, null);
+ providerParameters.getKeyRequirements().setKeyType(STSConstants.BEARER_KEY_KEYTYPE);
+ providerParameters.setPrincipal(new CustomTokenPrincipal(user));
+ assertTrue(samlTokenProvider.canHandleToken(WSConstants.WSS_SAML_TOKEN_TYPE));
+ TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ return (Element)providerResponse.getToken();
+ }
+
+ private TokenProviderParameters createProviderParameters(
+ String tokenType, Object onBehalfOf
+ ) throws WSSecurityException {
+ TokenProviderParameters parameters = new TokenProviderParameters();
+
+ TokenRequirements tokenRequirements = new TokenRequirements();
+ tokenRequirements.setTokenType(tokenType);
+
+ if (onBehalfOf != null) {
+ ReceivedToken onBehalfOfToken = new ReceivedToken(onBehalfOf);
+ onBehalfOfToken.setState(STATE.VALID);
+ tokenRequirements.setOnBehalfOf(onBehalfOfToken);
+
+ }
+ parameters.setTokenRequirements(tokenRequirements);
+
+ KeyRequirements keyRequirements = new KeyRequirements();
+ parameters.setKeyRequirements(keyRequirements);
+
+ parameters.setPrincipal(new CustomTokenPrincipal("alice"));
+ // Mock up message context
+ MessageImpl msg = new MessageImpl();
+ WrappedMessageContext msgCtx = new WrappedMessageContext(msg);
+ WebServiceContextImpl webServiceContext = new WebServiceContextImpl(msgCtx);
+ parameters.setWebServiceContext(webServiceContext);
+
+ parameters.setAppliesToAddress("http://dummy-service.com/dummy");
+
+ // Add STSProperties object
+ StaticSTSProperties stsProperties = new StaticSTSProperties();
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ parameters.setStsProperties(stsProperties);
+
+ parameters.setEncryptionProperties(new EncryptionProperties());
+
+ return parameters;
+ }
+
+ private Properties getEncryptionProperties() {
+ Properties properties = new Properties();
+ properties.put(
+ "org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin"
+ );
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.password", "stsspass");
+ properties.put("org.apache.wss4j.crypto.merlin.keystore.file", "stsstore.jks");
+
+ return properties;
+ }
+
+
+
+}