Author: coheigea
Date: Tue Nov 29 17:02:41 2011
New Revision: 1207972
URL: http://svn.apache.org/viewvc?rev=1207972&view=rev
Log:
[CXF-3928] - Add token validation for OnBehalfOf element in TokenIssueOperation
- Patch applied
Added:
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
Modified:
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/request/ReceivedToken.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/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
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=1207972&r1=1207971&r2=1207972&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 Nov 29 17:02:41 2011
@@ -37,7 +37,6 @@ import org.w3c.dom.Element;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.helpers.DOMUtils;
-
import org.apache.cxf.sts.QNameConstants;
import org.apache.cxf.sts.RealmParser;
import org.apache.cxf.sts.STSConstants;
@@ -45,6 +44,8 @@ import org.apache.cxf.sts.STSPropertiesM
import org.apache.cxf.sts.cache.STSTokenStore;
import org.apache.cxf.sts.claims.RequestClaimCollection;
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.RequestParser;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.service.EncryptionProperties;
@@ -52,6 +53,9 @@ 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.validator.TokenValidator;
+import org.apache.cxf.sts.token.validator.TokenValidatorParameters;
+import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.cxf.ws.security.sts.provider.model.LifetimeType;
@@ -72,9 +76,12 @@ import org.apache.ws.security.message.WS
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.util.XmlSchemaDateFormat;
+
+
/**
* This abstract class contains some common functionality for different
operations.
*/
+@SuppressWarnings("")
public abstract class AbstractOperation {
public static final QName TOKEN_TYPE =
@@ -86,6 +93,7 @@ public abstract class AbstractOperation
protected boolean encryptIssuedToken;
protected List<ServiceMBean> services;
protected List<TokenProvider> tokenProviders = new
ArrayList<TokenProvider>();
+ protected List<TokenValidator> tokenValidators = new
ArrayList<TokenValidator>();
protected boolean returnReferences = true;
protected STSTokenStore tokenStore;
@@ -124,6 +132,14 @@ public abstract class AbstractOperation
public List<TokenProvider> getTokenProviders() {
return tokenProviders;
}
+
+ public void setTokenValidators(List<TokenValidator> tokenValidators) {
+ this.tokenValidators = tokenValidators;
+ }
+
+ public List<TokenValidator> getTokenValidators() {
+ return tokenValidators;
+ }
/**
* Check the arguments from the STSProvider and parse the request.
@@ -487,4 +503,47 @@ public abstract class AbstractOperation
return null;
}
+ protected TokenValidatorResponse validateReceivedToken(
+ WebServiceContext context, String realm,
+ TokenRequirements tokenRequirements, ReceivedToken token) {
+ token.setValidationState(STATE.NONE);
+
+ tokenRequirements.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);
+
+ TokenValidatorResponse tokenResponse = null;
+ for (TokenValidator tokenValidator : tokenValidators) {
+ boolean canHandle = false;
+ if (realm == null) {
+ canHandle = tokenValidator.canHandleToken(token);
+ } else {
+ canHandle = tokenValidator.canHandleToken(token, realm);
+ }
+ if (canHandle) {
+ try {
+ tokenResponse =
tokenValidator.validateToken(validatorParameters);
+ token.setValidationState(
+ tokenResponse.isValid() ? STATE.VALID :
STATE.INVALID
+ );
+ // The parsed principal is set if available. It's up to
other components to
+ // deal with the STATE of the validation
+ token.setPrincipal(tokenResponse.getPrincipal());
+ } catch (RuntimeException ex) {
+ LOG.log(Level.WARNING, "Failed to validate the token", ex);
+ token.setValidationState(STATE.INVALID);
+ }
+ break;
+ }
+ }
+ return tokenResponse;
+ }
+
+
}
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=1207972&r1=1207971&r2=1207972&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 Nov 29 17:02:41 2011
@@ -20,8 +20,10 @@
package org.apache.cxf.sts.operation;
import java.net.URI;
+import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -29,11 +31,14 @@ 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.ClaimsManager;
import org.apache.cxf.sts.claims.RequestClaim;
import org.apache.cxf.sts.claims.RequestClaimCollection;
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.RequestParser;
import org.apache.cxf.sts.request.TokenRequirements;
import org.apache.cxf.sts.service.EncryptionProperties;
@@ -41,6 +46,7 @@ import org.apache.cxf.sts.token.provider
import org.apache.cxf.sts.token.provider.TokenProviderParameters;
import org.apache.cxf.sts.token.provider.TokenProviderResponse;
import org.apache.cxf.sts.token.provider.TokenReference;
+import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.cxf.ws.security.sts.provider.model.BinarySecretType;
import org.apache.cxf.ws.security.sts.provider.model.EntropyType;
@@ -62,8 +68,8 @@ public class TokenIssueOperation extends
private static final Logger LOG =
LogUtils.getL7dLogger(TokenIssueOperation.class);
- private ClaimsManager claimsManager;
-
+ private ClaimsManager claimsManager;
+
public ClaimsManager getClaimsManager() {
return claimsManager;
}
@@ -71,11 +77,11 @@ public class TokenIssueOperation extends
public void setClaimsManager(ClaimsManager claimsManager) {
this.claimsManager = claimsManager;
}
-
-
+
+
public RequestSecurityTokenResponseCollectionType issue(
- RequestSecurityTokenType request,
- WebServiceContext context
+ RequestSecurityTokenType request,
+ WebServiceContext context
) {
RequestSecurityTokenResponseType response = issueSingle(request,
context);
RequestSecurityTokenResponseCollectionType responseCollection =
@@ -83,45 +89,89 @@ public class TokenIssueOperation extends
responseCollection.getRequestSecurityTokenResponse().add(response);
return responseCollection;
}
-
+
public RequestSecurityTokenResponseType issueSingle(
- RequestSecurityTokenType request,
- WebServiceContext context
+ RequestSecurityTokenType request,
+ WebServiceContext context
) {
RequestParser requestParser = parseRequest(request, context);
-
+
TokenProviderParameters providerParameters =
createTokenProviderParameters(requestParser, context);
-
+
// Check if the requested claims can be handled by the configured
claim handlers
RequestClaimCollection requestedClaims =
providerParameters.getRequestedClaims();
if (requestedClaims != null) {
List<URI> unhandledClaimTypes = new ArrayList<URI>();
for (RequestClaim requestedClaim : requestedClaims) {
if
(!claimsManager.getSupportedClaimTypes().contains(requestedClaim.getClaimType())
- && !requestedClaim.isOptional()) {
+ && !requestedClaim.isOptional()) {
unhandledClaimTypes.add(requestedClaim.getClaimType());
}
}
-
+
if (unhandledClaimTypes.size() > 0) {
LOG.log(Level.WARNING, "The requested claim " +
unhandledClaimTypes.toString()
- + " cannot be fulfilled by the STS.");
+ + " cannot be fulfilled by the STS.");
throw new STSException(
- "The requested claim " + unhandledClaimTypes.toString()
- + " cannot be fulfilled by the STS."
+ "The requested claim " +
unhandledClaimTypes.toString()
+ + " cannot be fulfilled by the STS."
);
}
}
-
+
providerParameters.setClaimsManager(claimsManager);
-
- // create token
+ String realm = providerParameters.getRealm();
+
TokenRequirements tokenRequirements =
requestParser.getTokenRequirements();
String tokenType = tokenRequirements.getTokenType();
+
+
+ // Validate OnBehalfOf token if present
+ if (providerParameters.getTokenRequirements().getOnBehalfOf() != null)
{
+ 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);
+ }
+ }
+ } else {
+ //[TODO] Add plugin for validation out-of-band
+ // Example:
+ // If the requestor is in the possession of a certificate
(mutual ssl handshake)
+ // the STS trusts the token sent in OnBehalfOf element
+ }
+ if (tokenResponse != null) {
+ Map<String, Object> additionalProperties =
tokenResponse.getAdditionalProperties();
+ if (additionalProperties != null) {
+
providerParameters.setAdditionalProperties(additionalProperties);
+ }
+ }
+ }
+
+ // create token
TokenProviderResponse tokenResponse = null;
- String realm = providerParameters.getRealm();
for (TokenProvider tokenProvider : tokenProviders) {
- if (tokenProvider.canHandleToken(tokenType, realm)) {
+ boolean canHandle = false;
+ if (realm == null) {
+ canHandle = tokenProvider.canHandleToken(tokenType);
+ } else {
+ canHandle = tokenProvider.canHandleToken(tokenType, realm);
+ }
+ if (canHandle) {
try {
tokenResponse =
tokenProvider.createToken(providerParameters);
} catch (STSException ex) {
@@ -137,8 +187,8 @@ public class TokenIssueOperation extends
if (tokenResponse == null || tokenResponse.getToken() == null) {
LOG.log(Level.WARNING, "No token provider found for requested
token type: " + tokenType);
throw new STSException(
- "No token provider found for requested token type: " +
tokenType,
- STSException.REQUEST_FAILED
+ "No token provider found for requested token type: " +
tokenType,
+ STSException.REQUEST_FAILED
);
}
// prepare response
@@ -147,7 +197,7 @@ public class TokenIssueOperation extends
EncryptionProperties encryptionProperties =
providerParameters.getEncryptionProperties();
RequestSecurityTokenResponseType response =
createResponse(
- encryptionProperties, tokenResponse, tokenRequirements,
keyRequirements, context
+ encryptionProperties, tokenResponse,
tokenRequirements, keyRequirements, context
);
return response;
} catch (Throwable ex) {
@@ -157,15 +207,15 @@ public class TokenIssueOperation extends
}
private RequestSecurityTokenResponseType createResponse(
- EncryptionProperties encryptionProperties,
- TokenProviderResponse tokenResponse,
- TokenRequirements tokenRequirements,
- KeyRequirements keyRequirements,
- WebServiceContext webServiceContext
+ EncryptionProperties encryptionProperties,
+ TokenProviderResponse tokenResponse,
+ TokenRequirements tokenRequirements,
+ KeyRequirements keyRequirements,
+ WebServiceContext webServiceContext
) throws WSSecurityException {
RequestSecurityTokenResponseType response =
QNameConstants.WS_TRUST_FACTORY.createRequestSecurityTokenResponseType();
-
+
String context = tokenRequirements.getContext();
if (context != null) {
response.setContext(context);
@@ -203,16 +253,16 @@ public class TokenIssueOperation extends
} else {
requestedAttachedReferenceType =
createRequestedReference(
- tokenResponse.getTokenId(),
tokenRequirements.getTokenType(), true
+ tokenResponse.getTokenId(),
tokenRequirements.getTokenType(), true
);
}
-
+
JAXBElement<RequestedReferenceType> requestedAttachedReference =
QNameConstants.WS_TRUST_FACTORY.createRequestedAttachedReference(
- requestedAttachedReferenceType
+ requestedAttachedReferenceType
);
response.getAny().add(requestedAttachedReference);
-
+
// RequestedUnattachedReference
TokenReference unAttachedReference =
tokenResponse.getUnAttachedReference();
RequestedReferenceType requestedUnattachedReferenceType = null;
@@ -221,17 +271,17 @@ public class TokenIssueOperation extends
} else {
requestedUnattachedReferenceType =
createRequestedReference(
- tokenResponse.getTokenId(),
tokenRequirements.getTokenType(), false
+ tokenResponse.getTokenId(),
tokenRequirements.getTokenType(), false
);
}
-
+
JAXBElement<RequestedReferenceType> requestedUnattachedReference =
QNameConstants.WS_TRUST_FACTORY.createRequestedUnattachedReference(
- requestedUnattachedReferenceType
+ requestedUnattachedReferenceType
);
response.getAny().add(requestedUnattachedReference);
}
-
+
// AppliesTo
response.getAny().add(tokenRequirements.getAppliesTo());
@@ -255,7 +305,7 @@ public class TokenIssueOperation extends
QNameConstants.WS_TRUST_FACTORY.createRequestedProofToken(requestedProofTokenType);
response.getAny().add(requestedProofToken);
}
-
+
// Entropy
if (tokenResponse.isComputedKey() && tokenResponse.getEntropy() !=
null) {
Object token =
@@ -266,12 +316,12 @@ public class TokenIssueOperation extends
QNameConstants.WS_TRUST_FACTORY.createEntropy(entropyType);
response.getAny().add(entropyElement);
}
-
+
// Lifetime
LifetimeType lifetime = createLifetime(tokenResponse.getLifetime());
JAXBElement<LifetimeType> lifetimeType =
QNameConstants.WS_TRUST_FACTORY.createLifetime(lifetime);
response.getAny().add(lifetimeType);
-
+
// KeySize
long keySize = tokenResponse.getKeySize();
if (keySize <= 0) {
@@ -282,19 +332,19 @@ public class TokenIssueOperation extends
QNameConstants.WS_TRUST_FACTORY.createKeySize(keySize);
response.getAny().add(keySizeType);
}
-
+
return response;
}
-
+
/**
* Construct a token containing the secret to return to the client. If
encryptIssuedToken is set
* then the token is wrapped in an EncryptedKey DOM element, otherwise it
is returned in a
* BinarySecretType JAXBElement.
*/
private Object constructSecretToken(
- byte[] secret,
- EncryptionProperties encryptionProperties,
- KeyRequirements keyRequirements
+ byte[] secret,
+ EncryptionProperties encryptionProperties,
+ KeyRequirements keyRequirements
) throws WSSecurityException {
if (encryptIssuedToken) {
return encryptSecret(secret, encryptionProperties,
keyRequirements);
@@ -308,5 +358,5 @@ public class TokenIssueOperation extends
return binarySecret;
}
}
-
+
}
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=1207972&r1=1207971&r2=1207972&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 Nov 29 17:02:41 2011
@@ -20,8 +20,6 @@
package org.apache.cxf.sts.operation;
import java.security.Principal;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -32,8 +30,8 @@ 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;
-import org.apache.cxf.sts.request.KeyRequirements;
import org.apache.cxf.sts.request.ReceivedToken;
import org.apache.cxf.sts.request.RequestParser;
import org.apache.cxf.sts.request.TokenRequirements;
@@ -41,8 +39,6 @@ import org.apache.cxf.sts.token.provider
import org.apache.cxf.sts.token.provider.TokenProviderParameters;
import org.apache.cxf.sts.token.provider.TokenProviderResponse;
import org.apache.cxf.sts.token.provider.TokenReference;
-import org.apache.cxf.sts.token.validator.TokenValidator;
-import org.apache.cxf.sts.token.validator.TokenValidatorParameters;
import org.apache.cxf.sts.token.validator.TokenValidatorResponse;
import org.apache.cxf.ws.security.sts.provider.STSException;
import org.apache.cxf.ws.security.sts.provider.model.LifetimeType;
@@ -61,23 +57,13 @@ public class TokenValidateOperation exte
private static final Logger LOG =
LogUtils.getL7dLogger(TokenValidateOperation.class);
- private List<TokenValidator> tokenValidators = new
ArrayList<TokenValidator>();
-
- public void setTokenValidators(List<TokenValidator> tokenValidators) {
- this.tokenValidators = tokenValidators;
- }
-
- public List<TokenValidator> getTokenValidators() {
- return tokenValidators;
- }
-
+
public RequestSecurityTokenResponseType validate(
RequestSecurityTokenType request,
WebServiceContext context
) {
RequestParser requestParser = parseRequest(request, context);
- KeyRequirements keyRequirements = requestParser.getKeyRequirements();
TokenRequirements tokenRequirements =
requestParser.getTokenRequirements();
ReceivedToken validateTarget = tokenRequirements.getValidateTarget();
@@ -92,31 +78,16 @@ public class TokenValidateOperation exte
);
}
- TokenValidatorParameters validatorParameters = new
TokenValidatorParameters();
- validatorParameters.setStsProperties(stsProperties);
- validatorParameters.setPrincipal(context.getUserPrincipal());
- validatorParameters.setWebServiceContext(context);
- validatorParameters.setTokenStore(getTokenStore());
+ // Get the realm of the request
+ String realm = null;
+ if (stsProperties.getRealmParser() != null) {
+ RealmParser realmParser = stsProperties.getRealmParser();
+ realm = realmParser.parseRealm(context);
+ }
- validatorParameters.setKeyRequirements(keyRequirements);
- validatorParameters.setTokenRequirements(tokenRequirements);
+ TokenValidatorResponse tokenResponse = validateReceivedToken(
+ context, realm, tokenRequirements, validateTarget);
- //
- // Validate token
- //
- TokenValidatorResponse tokenResponse = null;
- for (TokenValidator tokenValidator : tokenValidators) {
- if (tokenValidator.canHandleToken(validateTarget)) {
- try {
- tokenResponse =
tokenValidator.validateToken(validatorParameters);
- } catch (RuntimeException ex) {
- LOG.log(Level.WARNING, "", ex);
- tokenResponse = new TokenValidatorResponse();
- tokenResponse.setValid(false);
- }
- break;
- }
- }
if (tokenResponse == null) {
LOG.fine("No Token Validator has been found that can handle this
token");
tokenResponse = new TokenValidatorResponse();
@@ -151,9 +122,15 @@ public class TokenValidateOperation exte
if (additionalProperties != null) {
providerParameters.setAdditionalProperties(additionalProperties);
}
- String realm = providerParameters.getRealm();
+ realm = providerParameters.getRealm();
for (TokenProvider tokenProvider : tokenProviders) {
- if (tokenProvider.canHandleToken(tokenType, realm)) {
+ boolean canHandle = false;
+ if (realm == null) {
+ canHandle = tokenProvider.canHandleToken(tokenType);
+ } else {
+ canHandle = tokenProvider.canHandleToken(tokenType, realm);
+ }
+ if (canHandle) {
try {
tokenProviderResponse =
tokenProvider.createToken(providerParameters);
} catch (STSException ex) {
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/ReceivedToken.java
Tue Nov 29 17:02:41 2011
@@ -18,6 +18,7 @@
*/
package org.apache.cxf.sts.request;
+import java.security.Principal;
import java.util.logging.Logger;
import javax.xml.bind.JAXBElement;
@@ -41,6 +42,11 @@ public class ReceivedToken {
private boolean isBinarySecurityToken;
private boolean isUsernameToken;
private boolean isDOMElement;
+ private String tokenContext; // WS-Security, OnBehalfOf, ActAs
+ private STATE validationState;
+ private Principal principal;
+
+ public enum STATE { VALID, INVALID, NONE };
public ReceivedToken(Object receivedToken) throws STSException {
if (receivedToken instanceof JAXBElement<?>) {
@@ -104,4 +110,28 @@ public class ReceivedToken {
this.isDOMElement = domElement;
}
+ public String getTokenContext() {
+ return tokenContext;
+ }
+
+ public void setTokenContext(String tokenContext) {
+ this.tokenContext = tokenContext;
+ }
+
+ public STATE getValidationState() {
+ return validationState;
+ }
+
+ public void setValidationState(STATE validationState) {
+ this.validationState = validationState;
+ }
+
+ public Principal getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(Principal principal) {
+ this.principal = principal;
+ }
+
}
\ No newline at end of file
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=1207972&r1=1207971&r2=1207972&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 Nov 29 17:02:41 2011
@@ -31,16 +31,15 @@ import org.apache.cxf.sts.STSConstants;
import org.apache.cxf.sts.STSPropertiesMBean;
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.ws.security.sts.provider.STSException;
-import org.apache.ws.security.SAMLTokenPrincipal;
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.CryptoType;
import org.apache.ws.security.message.WSSecEncryptedKey;
-import org.apache.ws.security.saml.ext.AssertionWrapper;
import org.apache.ws.security.saml.ext.bean.KeyInfoBean;
import org.apache.ws.security.saml.ext.bean.KeyInfoBean.CERT_IDENTIFIER;
import org.apache.ws.security.saml.ext.bean.SubjectBean;
@@ -84,16 +83,11 @@ public class DefaultSubjectProvider impl
Principal principal = null;
ReceivedToken receivedToken =
providerParameters.getTokenRequirements().getOnBehalfOf();
//[TODO] ActAs support
- if (receivedToken != null && receivedToken.isDOMElement()) {
- LOG.fine("Received token is DOM element: " +
receivedToken.isDOMElement());
- Element receivedTokenElement = (Element)receivedToken.getToken();
- try {
- AssertionWrapper assertion = new
AssertionWrapper(receivedTokenElement);
- principal = new SAMLTokenPrincipal(assertion);
- } catch (WSSecurityException e) {
- LOG.log(Level.WARNING, "Failed to parse OnBehalfOf element",
e);
- throw new STSException("Unknown OnBehalfOf element",
STSException.REQUEST_FAILED);
- }
+ //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();
} else {
principal = providerParameters.getPrincipal();
}
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=1207972&r1=1207971&r2=1207972&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 Nov 29 17:02:41 2011
@@ -137,6 +137,9 @@ public class SAMLTokenValidator implemen
Element validateTargetElement = (Element)validateTarget.getToken();
AssertionWrapper assertion = new
AssertionWrapper(validateTargetElement);
+ SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
+ response.setPrincipal(samlPrincipal);
+
SecurityToken secToken = null;
if (tokenParameters.getTokenStore() != null) {
int hash = 0;
@@ -212,8 +215,6 @@ public class SAMLTokenValidator implemen
}
}
- SAMLTokenPrincipal samlPrincipal = new
SAMLTokenPrincipal(assertion);
- response.setPrincipal(samlPrincipal);
response.setTokenRealm(tokenRealm);
response.setValid(true);
} catch (WSSecurityException ex) {
Modified:
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java?rev=1207972&r1=1207971&r2=1207972&view=diff
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
(original)
+++
cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/validator/UsernameTokenValidator.java
Tue Nov 29 17:02:41 2011
@@ -44,6 +44,7 @@ import org.apache.cxf.sts.token.realm.Us
import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
+import org.apache.ws.security.CustomTokenPrincipal;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityException;
@@ -167,6 +168,8 @@ public class UsernameTokenValidator impl
boolean bspCompliant = wssConfig.isWsiBSPCompliant();
UsernameToken ut =
new UsernameToken(usernameTokenElement,
allowNamespaceQualifiedPasswordTypes, bspCompliant);
+ // The parsed principal is set independent whether validation is
successful or not
+ response.setPrincipal(new CustomTokenPrincipal(ut.getName()));
if (ut.getPassword() == null) {
return response;
}
Added:
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=1207972&view=auto
==============================================================================
---
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
(added)
+++
cxf/trunk/services/sts/sts-core/src/test/java/org/apache/cxf/sts/operation/IssueOnbehalfofUnitTest.java
Tue Nov 29 17:02:41 2011
@@ -0,0 +1,516 @@
+/**
+ * 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.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.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.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.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.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.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.RequestedSecurityTokenType;
+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.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.SAML2Constants;
+import org.apache.ws.security.util.DOM2Writer;
+
+
+/**
+ * Some unit tests for the issue operation.
+ */
+public class IssueOnbehalfofUnitTest extends org.junit.Assert {
+
+ public static final QName REQUESTED_SECURITY_TOKEN =
+
QNameConstants.WS_TRUST_FACTORY.createRequestedSecurityToken(null).getName();
+
+ /**
+ * Test to successfully issue a SAML 2 token on-behalf-of a SAML 2 token
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfSaml2() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ providerList.add(new SAMLTokenProvider());
+ 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);
+
+ // 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);
+
+ // 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 to successfully issue a SAML 2 token on-behalf-of a UsernameToken
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfUsernameToken() throws Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ providerList.add(new SAMLTokenProvider());
+ 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,
WSConstants.WSS_SAML2_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
+ RequestSecurityTokenResponseCollectionType response =
+ issueOperation.issue(request, webServiceContext);
+ List<RequestSecurityTokenResponseType> securityTokenResponse =
+ response.getRequestSecurityTokenResponse();
+ assertTrue(!securityTokenResponse.isEmpty());
+ }
+
+ /**
+ * Test to successfully issue a SAML 2 token on-behalf-of a UsernameToken
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfInvalidUsernameToken() throws
Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ providerList.add(new SAMLTokenProvider());
+ 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,
WSConstants.WSS_SAML2_TOKEN_TYPE
+ );
+ request.getAny().add(tokenType);
+
+
+ // Create a UsernameToken without password
+ JAXBElement<UsernameTokenType> usernameTokenType =
createUsernameToken("alice", null);
+ 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 will fail as the UsernameToken validation fails
+ try {
+ issueOperation.issue(request, webServiceContext);
+ fail("Failure expected as no principal is available to create SAML
assertion");
+ } catch (STSException ex) {
+ // expected
+ }
+ }
+
+
+ /**
+ * Test to successfully issue a SAML 2 token (realm "B") on-behalf-of a
SAML 2 token
+ * on-behalf-of token is issued by realm "A".
+ */
+ @org.junit.Test
+ public void testIssueSaml2TokenOnBehalfOfSaml2DifferentRealm() throws
Exception {
+ TokenIssueOperation issueOperation = new TokenIssueOperation();
+
+ // Add Token Provider
+ List<TokenProvider> providerList = new ArrayList<TokenProvider>();
+ SAMLTokenProvider samlTokenProvider = new SAMLTokenProvider();
+ 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 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, SAMLRealm> realms = getSamlRealms();
+
+ // 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);
+
+ // Get a SAML Token via the SAMLTokenProvider
+ CallbackHandler callbackHandler = new PasswordCallbackHandler();
+ Element samlToken =
+ createSAMLAssertion(WSConstants.WSS_SAML2_TOKEN_TYPE, crypto,
"mystskey",
+ callbackHandler, realms);
+ 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);
+
+ // Validate a token - this will fail as the tokenProvider doesn't
understand how to handle
+ // realm "B"
+ //try {
+ // issueOperation.issue(request, webServiceContext);
+ //} catch (STSException ex) {
+ // // expected
+ //}
+
+ samlTokenProvider.setRealmMap(realms);
+
+ 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"));
+ assertTrue(tokenString.contains(SAML2Constants.CONF_BEARER));
+ }
+
+
+ /*
+ * 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);
+ }
+
+ /*
+ * 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);
+
+ TokenProviderParameters providerParameters =
+ createProviderParameters(
+ tokenType, STSConstants.BEARER_KEY_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 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;
+ }
+
+ 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, SAMLRealm> getSamlRealms() {
+ // 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;
+ }
+
+ private Properties getEncryptionProperties() {
+ Properties properties = new Properties();
+ properties.put(
+ "org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin"
+ );
+
properties.put("org.apache.ws.security.crypto.merlin.keystore.password",
"stsspass");
+ properties.put("org.apache.ws.security.crypto.merlin.keystore.file",
"stsstore.jks");
+
+ return properties;
+ }
+
+
+}