You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by ow...@apache.org on 2012/03/06 18:33:05 UTC
svn commit: r1297588 [1/2] - in /cxf/trunk/services/sts:
sts-core/src/main/java/org/apache/cxf/sts/
sts-core/src/main/java/org/apache/cxf/sts/claims/
sts-core/src/main/java/org/apache/cxf/sts/operation/
sts-core/src/main/java/org/apache/cxf/sts/token/p...
Author: owulff
Date: Tue Mar 6 17:33:04 2012
New Revision: 1297588
URL: http://svn.apache.org/viewvc?rev=1297588&view=rev
Log:
[CXF-3882] Support for Claims transformation in validate or issue RST
Added:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsMapper.java
- copied, changed from r1297436, cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/Relationship.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RelationshipResolver.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomClaimsMapper.java
cxf/trunk/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/username_onbehalfof/UsernameTokenValidator.java
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSPropertiesMBean.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/StaticSTSProperties.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/ValidateTokenTransformationUnitTest.java
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/token/provider/SAMLProviderOnBehalfOfTest.java
cxf/trunk/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/common/DoubleItPortTypeImpl.java
cxf/trunk/services/sts/systests/basic/src/test/java/org/apache/cxf/systest/sts/intermediary_transformation/IntermediaryCachingPortTypeImpl.java
cxf/trunk/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-transport.xml
cxf/trunk/services/sts/systests/basic/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-x509.xml
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSPropertiesMBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSPropertiesMBean.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSPropertiesMBean.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/STSPropertiesMBean.java Tue Mar 6 17:33:04 2012
@@ -19,9 +19,13 @@
package org.apache.cxf.sts;
+import java.util.List;
+
import javax.security.auth.callback.CallbackHandler;
import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.token.realm.Relationship;
+import org.apache.cxf.sts.token.realm.RelationshipResolver;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.ws.security.components.crypto.Crypto;
@@ -159,4 +163,22 @@ public interface STSPropertiesMBean {
*/
IdentityMapper getIdentityMapper();
+ /**
+ * Set the list of Relationship objects to use.
+ * @param relationships the List<Relationship> object to use.
+ */
+ void setRelationships(List<Relationship> relationships);
+
+ /**
+ * Get the list of Relationship objects to use.
+ * @return the List<Relationship> object to use.
+ */
+ List<Relationship> getRelationships();
+
+ /**
+ * Get the RelationshipResolver objects to use.
+ * @return the RelationshipResolver object to use.
+ */
+ RelationshipResolver getRelationshipResolver();
+
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/StaticSTSProperties.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/StaticSTSProperties.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/StaticSTSProperties.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/StaticSTSProperties.java Tue Mar 6 17:33:04 2012
@@ -21,6 +21,7 @@ package org.apache.cxf.sts;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
@@ -32,6 +33,8 @@ import org.apache.cxf.common.logging.Log
import org.apache.cxf.phase.PhaseInterceptorChain;
import org.apache.cxf.resource.ResourceManager;
import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.sts.token.realm.Relationship;
+import org.apache.cxf.sts.token.realm.RelationshipResolver;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityException;
@@ -58,6 +61,8 @@ public class StaticSTSProperties impleme
private EncryptionProperties encryptionProperties = new EncryptionProperties();
private RealmParser realmParser;
private IdentityMapper identityMapper;
+ private List<Relationship> relationships;
+ private RelationshipResolver relationshipResolver;
/**
* Load the CallbackHandler, Crypto objects, if necessary.
@@ -349,6 +354,18 @@ public class StaticSTSProperties impleme
}
return handler;
}
+
+ public void setRelationships(List<Relationship> relationships) {
+ this.relationships = relationships;
+ this.relationshipResolver = new RelationshipResolver(this.relationships);
+ }
+
+ public List<Relationship> getRelationships() {
+ return relationships;
+ }
+ public RelationshipResolver getRelationshipResolver() {
+ return relationshipResolver;
+ }
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsManager.java Tue Mar 6 17:33:04 2012
@@ -20,12 +20,22 @@
package org.apache.cxf.sts.claims;
import java.net.URI;
+import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.logging.Level;
import java.util.logging.Logger;
+import org.w3c.dom.Element;
+
import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.token.realm.Relationship;
import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.opensaml.common.SAMLVersion;
+import org.opensaml.xml.XMLObject;
+
/**
* This class holds various ClaimsHandler implementations.
@@ -55,22 +65,60 @@ public class ClaimsManager {
}
}
}
-
+
public ClaimCollection retrieveClaimValues(RequestClaimCollection claims, ClaimsParameters parameters) {
- if (claimHandlers != null && claimHandlers.size() > 0 && claims != null && claims.size() > 0) {
- ClaimCollection returnCollection = new ClaimCollection();
- for (ClaimsHandler handler : claimHandlers) {
- ClaimCollection claimCollection = handler.retrieveClaimValues(claims, parameters);
- if (claimCollection != null && claimCollection.size() != 0) {
- returnCollection.addAll(claimCollection);
+ Relationship relationship = null;
+ if (parameters.getAdditionalProperties() != null) {
+ relationship = (Relationship)parameters.getAdditionalProperties().get(
+ Relationship.class.getName());
+ }
+
+ if (relationship == null || relationship.getType().equals(Relationship.FED_TYPE_IDENTITY)) {
+ // Federate identity. Identity already mapped.
+ // Call all configured claims handlers to retrieve the required claims
+ if (claimHandlers != null && claimHandlers.size() > 0 && claims != null && claims.size() > 0) {
+ ClaimCollection returnCollection = new ClaimCollection();
+ for (ClaimsHandler handler : claimHandlers) {
+ ClaimCollection claimCollection = handler.retrieveClaimValues(claims, parameters);
+ if (claimCollection != null && claimCollection.size() != 0) {
+ returnCollection.addAll(claimCollection);
+ }
}
+ validateClaimValues(claims, returnCollection);
+ return returnCollection;
+ }
+
+ } else {
+ // Federate claims
+ ClaimsMapper claimsMapper = relationship.getClaimsMapper();
+ if (claimsMapper == null) {
+ LOG.log(Level.SEVERE, "ClaimsMapper required to federate claims but not configured.");
+ throw new STSException("ClaimsMapper required to federate claims but not configured",
+ STSException.BAD_REQUEST);
+ }
+
+ // Get the claims of the received token (only SAML supported)
+ // Consider refactoring to use a CallbackHandler and keep ClaimsManager token independent
+ AssertionWrapper assertion =
+ (AssertionWrapper)parameters.getAdditionalProperties().get(AssertionWrapper.class.getName());
+ List<Claim> claimList = null;
+ if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)) {
+ claimList = this.parseClaimsInAssertion(assertion.getSaml2());
+ } else {
+ claimList = this.parseClaimsInAssertion(assertion.getSaml1());
}
- validateClaimValues(claims, returnCollection);
- return returnCollection;
+ ClaimCollection sourceClaims = new ClaimCollection();
+ sourceClaims.addAll(claimList);
+
+ ClaimCollection targetClaims = claimsMapper.mapClaims(relationship.getSourceRealm(),
+ sourceClaims, relationship.getTargetRealm(), parameters);
+ validateClaimValues(claims, targetClaims);
+ return targetClaims;
}
+
return null;
}
-
+
private boolean validateClaimValues(RequestClaimCollection requestedClaims, ClaimCollection claims) {
for (RequestClaim claim : requestedClaims) {
URI claimType = claim.getClaimType();
@@ -80,6 +128,13 @@ public class ClaimsManager {
if (c.getClaimType().equals(claimType)) {
found = true;
break;
+ } else {
+ StringBuffer sb = new StringBuffer();
+ sb.append(c.getNamespace()).append('/').append(c.getClaimType());
+ if (sb.toString().equals(claimType.toString())) {
+ found = true;
+ break;
+ }
}
}
if (!found) {
@@ -89,10 +144,94 @@ public class ClaimsManager {
}
}
return true;
-
+
+ }
+
+
+ protected List<Claim> parseClaimsInAssertion(org.opensaml.saml1.core.Assertion assertion) {
+ List<org.opensaml.saml1.core.AttributeStatement> attributeStatements =
+ assertion.getAttributeStatements();
+ if (attributeStatements == null || attributeStatements.isEmpty()) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("No attribute statements found");
+ }
+ return Collections.emptyList();
+ }
+ ClaimCollection collection = new ClaimCollection();
+
+ for (org.opensaml.saml1.core.AttributeStatement statement : attributeStatements) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("parsing statement: " + statement.getElementQName());
+ }
+
+ List<org.opensaml.saml1.core.Attribute> attributes = statement.getAttributes();
+ for (org.opensaml.saml1.core.Attribute attribute : attributes) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("parsing attribute: " + attribute.getAttributeName());
+ }
+ Claim c = new Claim();
+ c.setIssuer(assertion.getIssuer());
+ c.setClaimType(URI.create(attribute.getAttributeName()));
+ try {
+ c.setClaimType(new URI(attribute.getAttributeName()));
+ } catch (URISyntaxException e) {
+ LOG.warning("Invalid attribute name in attributestatement: " + e.getMessage());
+ continue;
+ }
+ for (XMLObject attributeValue : attribute.getAttributeValues()) {
+ Element attributeValueElement = attributeValue.getDOM();
+ String value = attributeValueElement.getTextContent();
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest(" [" + value + "]");
+ }
+ c.setValue(value);
+ collection.add(c);
+ break;
+ }
+ }
+ }
+ return collection;
+ }
+
+ protected List<Claim> parseClaimsInAssertion(org.opensaml.saml2.core.Assertion assertion) {
+ List<org.opensaml.saml2.core.AttributeStatement> attributeStatements =
+ assertion.getAttributeStatements();
+ if (attributeStatements == null || attributeStatements.isEmpty()) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("No attribute statements found");
+ }
+ return Collections.emptyList();
+ }
+
+ List<Claim> collection = new ArrayList<Claim>();
+
+ for (org.opensaml.saml2.core.AttributeStatement statement : attributeStatements) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("parsing statement: " + statement.getElementQName());
+ }
+ List<org.opensaml.saml2.core.Attribute> attributes = statement.getAttributes();
+ for (org.opensaml.saml2.core.Attribute attribute : attributes) {
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest("parsing attribute: " + attribute.getName());
+ }
+ Claim c = new Claim();
+ c.setClaimType(URI.create(attribute.getName()));
+ c.setIssuer(assertion.getIssuer().getNameQualifier());
+ for (XMLObject attributeValue : attribute.getAttributeValues()) {
+ Element attributeValueElement = attributeValue.getDOM();
+ String value = attributeValueElement.getTextContent();
+ if (LOG.isLoggable(Level.FINEST)) {
+ LOG.finest(" [" + value + "]");
+ }
+ c.setValue(value);
+ collection.add(c);
+ break;
+ }
+ }
+ }
+ return collection;
+
}
-
-
+
}
-
\ No newline at end of file
Copied: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsMapper.java (from r1297436, cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java)
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsMapper.java?p2=cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsMapper.java&p1=cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java&r1=1297436&r2=1297588&rev=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/claims/ClaimsMapper.java Tue Mar 6 17:33:04 2012
@@ -16,34 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.cxf.sts.operation;
-import java.security.Principal;
-
-import org.apache.cxf.sts.IdentityMapper;
-import org.apache.ws.security.CustomTokenPrincipal;
+package org.apache.cxf.sts.claims;
/**
- * A test implementation of RealmParser.
+ * This interface defines a pluggable way of mapping claims from a source realm to a target
+ * realm.
*/
-public class CustomIdentityMapper implements IdentityMapper {
-
+public interface ClaimsMapper {
+
/**
- * Map a principal in the source realm to the target realm
+ * Map a collection of claims in the source realm to the target realm
* @param sourceRealm the source realm of the Principal
- * @param sourcePrincipal the principal in the source realm
+ * @param sourceClaims the claims collection in the source realm
* @param targetRealm the target realm of the Principal
- * @return the principal in the target realm
+ * @return claims collection of the target realm
*/
- public Principal mapPrincipal(String sourceRealm, Principal sourcePrincipal, String targetRealm) {
- if ("A".equals(sourceRealm)) {
- String name = sourcePrincipal.getName().toUpperCase();
- return new CustomTokenPrincipal(name);
- } else if ("B".equals(sourceRealm)) {
- String name = sourcePrincipal.getName().toLowerCase();
- return new CustomTokenPrincipal(name);
- }
- return null;
- }
+ ClaimCollection mapClaims(String sourceRealm,
+ ClaimCollection sourceClaims, String targetRealm, ClaimsParameters parameters);
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/AbstractOperation.java Tue Mar 6 17:33:04 2012
@@ -20,6 +20,7 @@
package org.apache.cxf.sts.operation;
import java.net.URI;
+import java.security.Principal;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
@@ -38,6 +39,7 @@ import org.w3c.dom.Element;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.sts.IdentityMapper;
import org.apache.cxf.sts.QNameConstants;
import org.apache.cxf.sts.RealmParser;
import org.apache.cxf.sts.STSConstants;
@@ -56,6 +58,8 @@ import org.apache.cxf.sts.service.Servic
import org.apache.cxf.sts.token.provider.TokenProvider;
import org.apache.cxf.sts.token.provider.TokenProviderParameters;
import org.apache.cxf.sts.token.provider.TokenReference;
+import org.apache.cxf.sts.token.realm.Relationship;
+import org.apache.cxf.sts.token.realm.RelationshipResolver;
import org.apache.cxf.sts.token.validator.TokenValidator;
import org.apache.cxf.sts.token.validator.TokenValidatorParameters;
import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
@@ -523,15 +527,16 @@ public abstract class AbstractOperation
TokenRequirements tokenRequirements, ReceivedToken token) {
token.setValidationState(STATE.NONE);
- tokenRequirements.setValidateTarget(token);
-
+ TokenRequirements validateRequirements = new TokenRequirements();
+ validateRequirements.setValidateTarget(token);
+
TokenValidatorParameters validatorParameters = new TokenValidatorParameters();
validatorParameters.setStsProperties(stsProperties);
validatorParameters.setPrincipal(context.getUserPrincipal());
validatorParameters.setWebServiceContext(context);
validatorParameters.setTokenStore(getTokenStore());
validatorParameters.setKeyRequirements(null);
- validatorParameters.setTokenRequirements(tokenRequirements);
+ validatorParameters.setTokenRequirements(validateRequirements);
TokenValidatorResponse tokenResponse = null;
for (TokenValidator tokenValidator : tokenValidators) {
@@ -580,5 +585,55 @@ public abstract class AbstractOperation
}
}
}
+
+ protected void processValidToken(TokenProviderParameters providerParameters,
+ ReceivedToken validatedToken, TokenValidatorResponse tokenResponse) {
+ // Map the principal (if it exists)
+ Principal responsePrincipal = tokenResponse.getPrincipal();
+ if (responsePrincipal != null) {
+ String targetRealm = providerParameters.getRealm();
+ String sourceRealm = tokenResponse.getTokenRealm();
+
+ if (sourceRealm != null && !sourceRealm.equals(targetRealm)) {
+ RelationshipResolver relRes = stsProperties.getRelationshipResolver();
+ Relationship relationship = null;
+ if (relRes != null) {
+ relationship = relRes.resolveRelationship(sourceRealm, targetRealm);
+ if (relationship != null) {
+ tokenResponse.getAdditionalProperties().put(
+ Relationship.class.getName(), relationship);
+ }
+ }
+
+ if (relationship == null || relationship.getType().equals(Relationship.FED_TYPE_IDENTITY)) {
+ // federate identity
+ IdentityMapper identityMapper = null;
+ if (relationship == null) {
+ identityMapper = stsProperties.getIdentityMapper();
+ } else {
+ identityMapper = relationship.getIdentityMapper();
+ }
+ if (identityMapper != null) {
+ Principal targetPrincipal =
+ identityMapper.mapPrincipal(sourceRealm, responsePrincipal, targetRealm);
+ validatedToken.setPrincipal(targetPrincipal);
+ } else {
+ LOG.log(Level.SEVERE,
+ "No IdentityMapper configured in STSProperties or Relationship");
+ throw new STSException("Error in providing a token", STSException.REQUEST_FAILED);
+ }
+ } else if (relationship.getType().equals(Relationship.FED_TYPE_CLAIMS)) {
+ // federate claims
+ // Claims are transformed at the time when the claims are required to create a token
+ // (ex. ClaimsAttributeStatementProvider)
+ // principal remains unchanged
+
+ } else {
+ LOG.log(Level.SEVERE, "Unkown federation type: " + relationship.getType());
+ throw new STSException("Error in providing a token", STSException.BAD_REQUEST);
+ }
+ }
+ }
+ }
}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenIssueOperation.java Tue Mar 6 17:33:04 2012
@@ -19,7 +19,6 @@
package org.apache.cxf.sts.operation;
-import java.security.Principal;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -28,7 +27,6 @@ import javax.xml.bind.JAXBElement;
import javax.xml.ws.WebServiceContext;
import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.sts.IdentityMapper;
import org.apache.cxf.sts.QNameConstants;
import org.apache.cxf.sts.claims.RequestClaimCollection;
import org.apache.cxf.sts.request.KeyRequirements;
@@ -61,7 +59,7 @@ import org.apache.ws.security.WSSecurity
*/
public class TokenIssueOperation extends AbstractOperation implements IssueOperation, IssueSingleOperation {
- private static final Logger LOG = LogUtils.getL7dLogger(TokenIssueOperation.class);
+ static final Logger LOG = LogUtils.getL7dLogger(TokenIssueOperation.class);
public RequestSecurityTokenResponseCollectionType issue(
@@ -99,23 +97,12 @@ public class TokenIssueOperation extends
ReceivedToken validateTarget = providerParameters.getTokenRequirements().getOnBehalfOf();
TokenValidatorResponse tokenResponse = validateReceivedToken(
context, realm, tokenRequirements, validateTarget);
-
+
if (tokenResponse == null) {
LOG.fine("No Token Validator has been found that can handle this token");
} else if (validateTarget.getValidationState().equals(STATE.VALID)) {
- // Map the principal (if it exists)
- Principal responsePrincipal = tokenResponse.getPrincipal();
- if (responsePrincipal != null) {
- String targetRealm = providerParameters.getRealm();
- String sourceRealm = tokenResponse.getTokenRealm();
- IdentityMapper identityMapper = stsProperties.getIdentityMapper();
- if (sourceRealm != null && !sourceRealm.equals(targetRealm) && identityMapper != null) {
- Principal targetPrincipal =
- identityMapper.mapPrincipal(sourceRealm, responsePrincipal, targetRealm);
- validateTarget.setPrincipal(targetPrincipal);
- }
- }
+ processValidToken(providerParameters, validateTarget, tokenResponse);
} else {
//[TODO] Add plugin for validation out-of-band
// Example:
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/operation/TokenValidateOperation.java Tue Mar 6 17:33:04 2012
@@ -19,7 +19,6 @@
package org.apache.cxf.sts.operation;
-import java.security.Principal;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -28,7 +27,6 @@ import javax.xml.bind.JAXBElement;
import javax.xml.ws.WebServiceContext;
import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.sts.IdentityMapper;
import org.apache.cxf.sts.QNameConstants;
import org.apache.cxf.sts.RealmParser;
import org.apache.cxf.sts.STSConstants;
@@ -104,20 +102,7 @@ public class TokenValidateOperation exte
TokenProviderParameters providerParameters =
createTokenProviderParameters(requestParser, context);
- // Map the principal (if it exists)
- Principal responsePrincipal = tokenResponse.getPrincipal();
- if (responsePrincipal != null) {
- String targetRealm = providerParameters.getRealm();
- String sourceRealm = tokenResponse.getTokenRealm();
- IdentityMapper identityMapper = stsProperties.getIdentityMapper();
- if (sourceRealm != null && !sourceRealm.equals(targetRealm) && identityMapper != null) {
- Principal targetPrincipal =
- identityMapper.mapPrincipal(sourceRealm, responsePrincipal, targetRealm);
- providerParameters.setPrincipal(targetPrincipal);
- } else {
- providerParameters.setPrincipal(responsePrincipal);
- }
- }
+ processValidToken(providerParameters, validateTarget, tokenResponse);
// Check if the requested claims can be handled by the configured claim handlers
RequestClaimCollection requestedClaims = providerParameters.getRequestedClaims();
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java Tue Mar 6 17:33:04 2012
@@ -91,13 +91,20 @@ public class DefaultSubjectProvider impl
String confirmationMethod = getSubjectConfirmationMethod(tokenType, keyType);
Principal principal = null;
- ReceivedToken receivedToken = providerParameters.getTokenRequirements().getOnBehalfOf();
+ ReceivedToken receivedToken = null;
//[TODO] ActAs support
//TokenValidator in IssueOperation has validated the ReceivedToken
//if validation was successful, the principal was set in ReceivedToken
- if (receivedToken != null && receivedToken.getPrincipal() != null
- && receivedToken.getValidationState().equals(STATE.VALID)) {
- principal = receivedToken.getPrincipal();
+ if (providerParameters.getTokenRequirements().getOnBehalfOf() != null) {
+ receivedToken = providerParameters.getTokenRequirements().getOnBehalfOf();
+ if (receivedToken.getValidationState().equals(STATE.VALID)) {
+ principal = receivedToken.getPrincipal();
+ }
+ } else if (providerParameters.getTokenRequirements().getValidateTarget() != null) {
+ receivedToken = providerParameters.getTokenRequirements().getValidateTarget();
+ if (receivedToken.getValidationState().equals(STATE.VALID)) {
+ principal = receivedToken.getPrincipal();
+ }
} else {
principal = providerParameters.getPrincipal();
}
Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/Relationship.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/Relationship.java?rev=1297588&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/Relationship.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/Relationship.java Tue Mar 6 17:33:04 2012
@@ -0,0 +1,88 @@
+/**
+ * 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.realm;
+
+
+import org.apache.cxf.sts.IdentityMapper;
+import org.apache.cxf.sts.claims.ClaimsMapper;
+
+
+/**
+ * This class holds the parameters that will be required to define
+ * a one-way relationship between a source and target realm.
+ * Two types of relationships are supported: FederatedIdentity and FederatedClaims
+ * If the realm of received token in the RST differs with the target realm either
+ * the configured IdentityMapper of ClaimsMapper are called depending on the type of relationship.
+ */
+public class Relationship {
+
+ public static final String FED_TYPE_IDENTITY = "FederatedIdentity";
+ public static final String FED_TYPE_CLAIMS = "FederatedClaims";
+
+
+ private String sourceRealm;
+ private String targetRealm;
+ private IdentityMapper identityMapper;
+ private ClaimsMapper claimsMapper;
+ private String type;
+
+
+ public void setSourceRealm(String sourceRealm) {
+ this.sourceRealm = sourceRealm;
+ }
+
+ public String getSourceRealm() {
+ return sourceRealm;
+ }
+
+ public void setTargetRealm(String targetRealm) {
+ this.targetRealm = targetRealm;
+ }
+
+ public String getTargetRealm() {
+ return targetRealm;
+ }
+
+ public void setIdentityMapper(IdentityMapper identityMapper) {
+ this.identityMapper = identityMapper;
+ }
+
+ public IdentityMapper getIdentityMapper() {
+ return identityMapper;
+ }
+
+ public void setClaimsMapper(ClaimsMapper claimsMapper) {
+ this.claimsMapper = claimsMapper;
+ }
+
+ public ClaimsMapper getClaimsMapper() {
+ return claimsMapper;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+}
+
Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RelationshipResolver.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RelationshipResolver.java?rev=1297588&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RelationshipResolver.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/realm/RelationshipResolver.java Tue Mar 6 17:33:04 2012
@@ -0,0 +1,51 @@
+/**
+ * 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.realm;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RelationshipResolver {
+
+ private Map<String, Relationship> relationshipMap;
+
+
+ public RelationshipResolver(List<Relationship> relationships) {
+ relationshipMap = new HashMap<String, Relationship>();
+ for (Relationship rel : relationships) {
+ String key = generateKey(rel.getSourceRealm(), rel.getTargetRealm());
+ relationshipMap.put(key, rel);
+ }
+ }
+
+ public Relationship resolveRelationship(String sourceRealm, String targetRealm) {
+ String key = generateKey(sourceRealm, targetRealm);
+ return relationshipMap.get(key);
+ }
+
+
+ private String generateKey(String sourceRealm, String targetRealm) {
+ return new StringBuffer().append(sourceRealm).append(">").append(targetRealm).toString();
+
+ }
+
+
+}
Modified: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java (original)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/SAMLTokenValidator.java Tue Mar 6 17:33:04 2012
@@ -20,7 +20,9 @@ package org.apache.cxf.sts.token.validat
import java.security.cert.X509Certificate;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -223,6 +225,11 @@ public class SAMLTokenValidator implemen
}
}
+ // Add the AssertionWrapper to the properties, as the claims are required to be transformed
+ Map<String, Object> addProps = new HashMap<String, Object>();
+ addProps.put(AssertionWrapper.class.getName(), assertion);
+ response.setAdditionalProperties(addProps);
+
response.setTokenRealm(tokenRealm);
response.setValid(true);
} catch (WSSecurityException ex) {
Added: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomClaimsMapper.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomClaimsMapper.java?rev=1297588&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomClaimsMapper.java (added)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomClaimsMapper.java Tue Mar 6 17:33:04 2012
@@ -0,0 +1,55 @@
+/**
+ * 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 org.apache.cxf.sts.claims.Claim;
+import org.apache.cxf.sts.claims.ClaimCollection;
+import org.apache.cxf.sts.claims.ClaimsMapper;
+import org.apache.cxf.sts.claims.ClaimsParameters;
+
+/**
+ * A test implementation of ClaimsMapper.
+ */
+public class CustomClaimsMapper implements ClaimsMapper {
+
+ /**
+ * transforms the claim values to upper-case
+ */
+ public ClaimCollection mapClaims(String sourceRealm,
+ ClaimCollection sourceClaims, String targetRealm,
+ ClaimsParameters parameters) {
+
+ ClaimCollection targetClaims = new ClaimCollection();
+
+ for (Claim c : sourceClaims) {
+ Claim nc = new Claim();
+ nc.setClaimType(c.getClaimType());
+ nc.setIssuer(c.getIssuer());
+ nc.setNamespace(c.getNamespace());
+ nc.setOriginalIssuer(c.getOriginalIssuer());
+ nc.setPrincipal(c.getPrincipal());
+ nc.setValue(c.getValue().toUpperCase());
+ targetClaims.add(nc);
+ }
+
+ return targetClaims;
+ }
+
+}
Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/CustomIdentityMapper.java Tue Mar 6 17:33:04 2012
@@ -24,7 +24,7 @@ import org.apache.cxf.sts.IdentityMapper
import org.apache.ws.security.CustomTokenPrincipal;
/**
- * A test implementation of RealmParser.
+ * A test implementation of IdentityMapper.
*/
public class CustomIdentityMapper implements IdentityMapper {
Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java Tue Mar 6 17:33:04 2012
@@ -324,7 +324,7 @@ public class IssueOnbehalfofUnitTest ext
stsProperties.setIdentityMapper(new CustomIdentityMapper());
issueOperation.setStsProperties(stsProperties);
- Map<String, SAMLRealm> realms = getSamlRealms();
+ Map<String, SAMLRealm> realms = createSamlRealms();
// Mock up a request
RequestSecurityTokenType request = new RequestSecurityTokenType();
@@ -391,7 +391,7 @@ public class IssueOnbehalfofUnitTest ext
assertTrue(tokenString.contains("AttributeStatement"));
assertTrue(tokenString.contains("ALICE"));
assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
- }
+ }
/*
@@ -489,7 +489,7 @@ public class IssueOnbehalfofUnitTest ext
return tokenType;
}
- private Map<String, SAMLRealm> getSamlRealms() {
+ private Map<String, SAMLRealm> createSamlRealms() {
// Create Realms
Map<String, SAMLRealm> samlRealms = new HashMap<String, SAMLRealm>();
SAMLRealm samlRealm = new SAMLRealm();
Modified: cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java?rev=1297588&r1=1297587&r2=1297588&view=diff
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java (original)
+++ cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueSamlClaimsUnitTest.java Tue Mar 6 17:33:04 2012
@@ -21,9 +21,12 @@ package org.apache.cxf.sts.operation;
import java.security.Principal;
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;
@@ -40,23 +43,39 @@ import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.STSPropertiesMBean;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.claims.ClaimTypes;
+import org.apache.cxf.sts.claims.ClaimsAttributeStatementProvider;
import org.apache.cxf.sts.claims.ClaimsHandler;
import org.apache.cxf.sts.claims.ClaimsManager;
+import org.apache.cxf.sts.claims.ClaimsMapper;
+import org.apache.cxf.sts.claims.RequestClaim;
+import org.apache.cxf.sts.claims.RequestClaimCollection;
import org.apache.cxf.sts.common.CustomAttributeProvider;
import org.apache.cxf.sts.common.CustomClaimsHandler;
import org.apache.cxf.sts.common.PasswordCallbackHandler;
+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.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.AttributeStatementProvider;
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.realm.Relationship;
+import org.apache.cxf.sts.token.realm.SAMLRealm;
+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.ws.security.sts.provider.model.ClaimsType;
+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.ws.security.CustomTokenPrincipal;
import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.saml.ext.builder.SAML1Constants;
@@ -155,7 +174,7 @@ public class IssueSamlClaimsUnitTest ext
assertTrue(tokenString.contains("AttributeStatement"));
assertTrue(tokenString.contains("alice"));
assertTrue(tokenString.contains(SAML1Constants.CONF_BEARER));
- assertTrue(tokenString.contains(ClaimTypes.FIRSTNAME.toString()));
+ assertTrue(tokenString.contains(ClaimTypes.LASTNAME.toString()));
}
/**
@@ -242,7 +261,7 @@ public class IssueSamlClaimsUnitTest ext
assertTrue(tokenString.contains("AttributeStatement"));
assertTrue(tokenString.contains("alice"));
assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
- assertTrue(tokenString.contains(ClaimTypes.FIRSTNAME.toString()));
+ assertTrue(tokenString.contains(ClaimTypes.LASTNAME.toString()));
}
/**
@@ -342,9 +361,330 @@ public class IssueSamlClaimsUnitTest ext
assertTrue(tokenString.contains("AttributeStatement"));
assertTrue(tokenString.contains("alice"));
assertTrue(tokenString.contains(SAML1Constants.CONF_BEARER));
- assertTrue(tokenString.contains(ClaimTypes.FIRSTNAME.toString()));
+ assertTrue(tokenString.contains(ClaimTypes.LASTNAME.toString()));
}
+ /**
+ * Test to successfully issue a SAML 2 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
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateClaims() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ Map<String, SAMLRealm> realms = createSamlRealms();
+
+ // 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);
+ issueOperation.setTokenProviders(providerList);
+
+ // 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 Relationship list
+ List<Relationship> relationshipList = new ArrayList<Relationship>();
+ Relationship rs = createRelationship();
+ relationshipList.add(rs);
+
+ // Add STSProperties object
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ STSPropertiesMBean stsProperties = createSTSPropertiesMBean(crypto);
+ stsProperties.setRealmParser(new CustomRealmParser());
+ stsProperties.setIdentityMapper(new CustomIdentityMapper());
+ stsProperties.setRelationships(relationshipList);
+ issueOperation.setStsProperties(stsProperties);
+
+ // Set the ClaimsManager
+ ClaimsManager claimsManager = new ClaimsManager();
+ ClaimsHandler claimsHandler = new CustomClaimsHandler();
+ claimsManager.setClaimHandlers(Collections.singletonList(claimsHandler));
+ issueOperation.setClaimsManager(claimsManager);
+
+ // Mock up a request
+ RequestSecurityTokenType request = new RequestSecurityTokenType();
+ JAXBElement<String> tokenType =
+ new JAXBElement<String>(
+ QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+ // Add a ClaimsType
+ ClaimsType claimsType = new ClaimsType();
+ claimsType.setDialect(STSConstants.IDT_NS_05_05);
+
+ Document doc = DOMUtils.createDocument();
+ Element claimType = createClaimsType(doc);
+ claimsType.getAny().add(claimType);
+
+ JAXBElement<ClaimsType> claimsTypeJaxb =
+ new JAXBElement<ClaimsType>(
+ QNameConstants.CLAIMS, ClaimsType.class, claimsType
+ );
+ request.getAny().add(claimsTypeJaxb);
+
+ //request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy"));
+
+ // create a SAML Token via the SAMLTokenProvider which contains claims
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey",
+ callbackHandler, realms);
+ Document docToken = samlToken.getOwnerDocument();
+ samlToken = (Element)docToken.appendChild(samlToken);
+ String samlString = DOM2Writer.nodeToString(samlToken);
+ assertTrue(samlString.contains("AttributeStatement"));
+ assertTrue(samlString.contains("alice"));
+ assertTrue(samlString.contains("doe"));
+ assertTrue(samlString.contains(SAML2Constants.CONF_BEARER));
+
+ // add SAML token as On-Behalf-Of element
+ 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);
+
+ // run the test
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponseList =
+ response.getRequestSecurityTokenResponse();
+
+ assertTrue(!securityTokenResponseList.isEmpty());
+ 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();
+ 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));
+ }
+
+ /**
+ * Test to successfully issue a SAML 2 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
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentityGlobalConfig()
+ throws Exception {
+ runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(true);
+ }
+
+
+ /**
+ * Test to successfully issue a SAML 2 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
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentityRelationshipConfig()
+ throws Exception {
+ runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(false);
+ }
+
+ private void runIssueSaml2TokenOnBehalfOfSaml2DifferentRealmFederateIdentity(
+ boolean useGlobalIdentityMapper) throws WSSecurityException {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ Map<String, SAMLRealm> realms = createSamlRealms();
+
+ // 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);
+ issueOperation.setTokenProviders(providerList);
+
+ // 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 Relationship list
+ List<Relationship> relationshipList = new ArrayList<Relationship>();
+ Relationship rs = createRelationship();
+ rs.setType(Relationship.FED_TYPE_IDENTITY);
+ rs.setIdentityMapper(new CustomIdentityMapper());
+ relationshipList.add(rs);
+
+ // Add STSProperties object
+ Crypto crypto = CryptoFactory.getInstance(getEncryptionProperties());
+ STSPropertiesMBean stsProperties = createSTSPropertiesMBean(crypto);
+ stsProperties.setRealmParser(new CustomRealmParser());
+
+ if (useGlobalIdentityMapper) {
+ stsProperties.setIdentityMapper(new CustomIdentityMapper());
+ } else {
+ stsProperties.setRelationships(relationshipList);
+ }
+
+ issueOperation.setStsProperties(stsProperties);
+
+ // Set the ClaimsManager
+ ClaimsManager claimsManager = new ClaimsManager();
+ claimsManager.setClaimHandlers(Collections.singletonList((ClaimsHandler)new CustomClaimsHandler()));
+ issueOperation.setClaimsManager(claimsManager);
+
+ // Mock up a request
+ RequestSecurityTokenType request = new RequestSecurityTokenType();
+ JAXBElement<String> tokenType =
+ new JAXBElement<String>(
+ QNameConstants.TOKEN_TYPE, String.class, WSConstants.WSS_SAML2_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+ // Add a ClaimsType
+ ClaimsType claimsType = new ClaimsType();
+ claimsType.setDialect(STSConstants.IDT_NS_05_05);
+
+ Document doc = DOMUtils.createDocument();
+ Element claimType = createClaimsType(doc);
+ claimsType.getAny().add(claimType);
+
+ JAXBElement<ClaimsType> claimsTypeJaxb =
+ new JAXBElement<ClaimsType>(
+ QNameConstants.CLAIMS, ClaimsType.class, claimsType
+ );
+ request.getAny().add(claimsTypeJaxb);
+
+ //request.getAny().add(createAppliesToElement("http://dummy-service.com/dummy"));
+
+ // create a SAML Token via the SAMLTokenProvider which contains claims
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto, "mystskey",
+ callbackHandler, realms);
+ Document docToken = samlToken.getOwnerDocument();
+ samlToken = (Element)docToken.appendChild(samlToken);
+ String samlString = DOM2Writer.nodeToString(samlToken);
+ assertTrue(samlString.contains("AttributeStatement"));
+ assertTrue(samlString.contains("alice"));
+ assertTrue(samlString.contains("doe"));
+ assertTrue(samlString.contains(SAML2Constants.CONF_BEARER));
+
+ // add SAML token as On-Behalf-Of element
+ 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);
+
+ // run the test
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponseList =
+ response.getRequestSecurityTokenResponse();
+
+ assertTrue(!securityTokenResponseList.isEmpty());
+ 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();
+ 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));
+ }
+
+
+ private Relationship createRelationship() {
+ Relationship rs = new Relationship();
+ ClaimsMapper claimsMapper = new CustomClaimsMapper();
+ rs.setClaimsMapper(claimsMapper);
+ rs.setSourceRealm("A");
+ rs.setTargetRealm("B");
+ rs.setType(Relationship.FED_TYPE_CLAIMS);
+ return rs;
+ }
+
+
+ /*
+ * Create STSPropertiesMBean object
+ */
+ private STSPropertiesMBean createSTSPropertiesMBean(Crypto crypto) throws WSSecurityException {
+ STSPropertiesMBean stsProperties = new StaticSTSProperties();
+ stsProperties.setEncryptionCrypto(crypto);
+ stsProperties.setSignatureCrypto(crypto);
+ stsProperties.setEncryptionUsername("myservicekey");
+ stsProperties.setSignatureUsername("mystskey");
+ stsProperties.setCallbackHandler(new PasswordCallbackHandler());
+ stsProperties.setIssuer("STS");
+ return stsProperties;
+ }
+
+
/*
* Create a security context object
*/
@@ -409,11 +749,102 @@ public class IssueSamlClaimsUnitTest ext
private Element createClaimsType(Document doc) {
Element claimType = doc.createElementNS(STSConstants.IDT_NS_05_05, "ClaimType");
claimType.setAttributeNS(
- null, "Uri", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"
+ null, "Uri", ClaimTypes.LASTNAME.toString()
);
claimType.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", STSConstants.IDT_NS_05_05);
return claimType;
}
+ private Map<String, SAMLRealm> createSamlRealms() {
+ // Create Realms
+ Map<String, SAMLRealm> samlRealms = new HashMap<String, SAMLRealm>();
+ SAMLRealm samlRealm = new SAMLRealm();
+ samlRealm.setIssuer("A-Issuer");
+ samlRealms.put("A", samlRealm);
+ samlRealm = new SAMLRealm();
+ samlRealm.setIssuer("B-Issuer");
+ samlRealms.put("B", samlRealm);
+ return samlRealms;
+ }
+
+ /*
+ * Mock up an SAML assertion element
+ */
+ private Element createSAMLAssertion(
+ String tokenType, Crypto crypto, String signatureUsername, CallbackHandler callbackHandler,
+ Map<String, SAMLRealm> realms
+ ) throws WSSecurityException {
+
+ SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
+ samlTokenProvider.setRealmMap(realms);
+ List<AttributeStatementProvider> customProviderList =
+ new ArrayList<AttributeStatementProvider>();
+ customProviderList.add(new ClaimsAttributeStatementProvider());
+ samlTokenProvider.setAttributeStatementProviders(customProviderList);
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ tokenType, STSConstants.BEARER_KEY_KEYTYPE, crypto, signatureUsername, callbackHandler
+ );
+ if (realms != null) {
+ providerParameters.setRealm("A");
+ }
+
+ // Set the ClaimsManager
+ ClaimsManager claimsManager = new ClaimsManager();
+ ClaimsHandler claimsHandler = new CustomClaimsHandler();
+ claimsManager.setClaimHandlers(Collections.singletonList(claimsHandler));
+ providerParameters.setClaimsManager(claimsManager);
+
+ RequestClaimCollection requestedClaims = new RequestClaimCollection();
+ RequestClaim requestClaim = new RequestClaim();
+ requestClaim.setClaimType(ClaimTypes.LASTNAME);
+ requestClaim.setOptional(false);
+ requestedClaims.add(requestClaim);
+ providerParameters.setRequestedClaims(requestedClaims);
+
+ TokenProviderResponse providerResponse = samlTokenProvider.createToken(providerParameters);
+ assertTrue(providerResponse != null);
+ assertTrue(providerResponse.getToken() != null && providerResponse.getTokenId() != null);
+
+ return 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);
+ 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");
+ parameters.setStsProperties(stsProperties);
+
+ parameters.setEncryptionProperties(new EncryptionProperties());
+
+ return parameters;
+ }
+
}