Author: sguilhen(a)redhat.com
Date: 2009-11-12 18:56:38 -0500 (Thu, 12 Nov 2009)
New Revision: 934
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/JBossSTS.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
Log:
JBID-212: implemented renew token logic in StandardRequestHandler and SAML20TokenProvider
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/JBossSTS.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/JBossSTS.java 2009-11-12
23:28:01 UTC (rev 933)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/JBossSTS.java 2009-11-12
23:56:38 UTC (rev 934)
@@ -133,9 +133,13 @@
Document doc = handler.postProcess((Document)((DOMSource)source).getNode(),
request);
return new DOMSource(doc);
}
-
else if (requestType.equals(WSTrustConstants.RENEW_REQUEST))
- return this.marshallResponse(handler.renew(request,
this.context.getUserPrincipal()));
+ {
+ Source source = this.marshallResponse(handler.renew(request,
this.context.getUserPrincipal()));
+ // we need to sign/encrypt renewed tokens.
+ Document document = handler.postProcess((Document)((DOMSource)
source).getNode(), request);
+ return new DOMSource(document);
+ }
else if (requestType.equals(WSTrustConstants.CANCEL_REQUEST))
return this.marshallResponse(handler.cancel(request,
this.context.getUserPrincipal()));
else if (requestType.equals(WSTrustConstants.VALIDATE_REQUEST))
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java 2009-11-12
23:28:01 UTC (rev 933)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/StandardRequestHandler.java 2009-11-12
23:56:38 UTC (rev 934)
@@ -32,7 +32,6 @@
import javax.xml.bind.JAXBElement;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;
-import javax.xml.namespace.QName;
import org.apache.log4j.Logger;
import org.jboss.identity.federation.core.exceptions.ProcessingException;
@@ -288,72 +287,69 @@
public RequestSecurityTokenResponse renew(RequestSecurityToken request, Principal
callerPrincipal)
throws WSTrustException
{
- Document rstDocument = request.getRSTDocument();
- if (rstDocument == null)
- throw new IllegalArgumentException("Request does not contain the DOM
Document");
-
- SecurityTokenProvider provider = null;
-
- // first try to obtain the security token provider using the applies-to contents.
- AppliesTo appliesTo = request.getAppliesTo();
- PublicKey providerPublicKey = null;
- if (appliesTo != null)
+ // first validate the provided token signature to make sure it has been issued by
this STS and hasn't been tempered.
+ if (trace)
+ log.trace("Validating token for renew request " +
request.getContext());
+ if (request.getRenewTarget() == null)
+ throw new WSTrustException("Unable to renew token: renew target is
null");
+
+ Node securityToken = request.getRenewTargetElement().getFirstChild();
+ if (this.configuration.signIssuedToken() &&
this.configuration.getSTSKeyPair() != null)
{
- String serviceName = WSTrustUtil.parseAppliesTo(appliesTo);
- if (serviceName != null)
+ KeyPair keyPair = this.configuration.getSTSKeyPair();
+ try
{
- provider = this.configuration.getProviderForService(serviceName);
-
request.setTokenType(URI.create(this.configuration.getTokenTypeForService(serviceName)));
- providerPublicKey =
this.configuration.getServiceProviderPublicKey(serviceName);
+ Document tokenDocument = DocumentUtil.createDocument();
+ Node importedNode = tokenDocument.importNode(securityToken, true);
+ tokenDocument.appendChild(importedNode);
+ if (!XMLSignatureUtil.validate(tokenDocument, keyPair.getPublic()))
+ throw new WSTrustException("Validation failure during renewal:
digital signature is invalid");
}
+ catch (Exception e)
+ {
+ throw new WSTrustException("Validation failure during renewal: unable to
verify digital signature", e);
+ }
}
- // if applies-to is not available or if no provider was found for the service, use
the token type.
- if (provider == null && request.getTokenType() != null)
+ else
{
- provider =
this.configuration.getProviderForTokenType(request.getTokenType().toString());
+ if (trace)
+ log.trace("Security Token digital signature has NOT been verified.
Either the STS has been configured"
+ + "not to sign tokens or the STS key pair has not been properly
specified.");
}
- else if (appliesTo == null && request.getTokenType() == null)
- throw new WSTrustException("Either AppliesTo or TokenType must be present
in a security token request");
-
- if (provider != null)
+
+ // set default values where needed.
+ if (request.getLifetime() == null &&
this.configuration.getIssuedTokenTimeout() != 0)
{
- // create the request context and delegate token generation to the provider.
- WSTrustRequestContext requestContext = new WSTrustRequestContext(request,
callerPrincipal);
- requestContext.setTokenIssuer(this.configuration.getSTSName());
- if (request.getLifetime() == null &&
this.configuration.getIssuedTokenTimeout() != 0)
- {
- // if no lifetime has been specified, use the configured timeout value.
-
request.setLifetime(WSTrustUtil.createDefaultLifetime(this.configuration.getIssuedTokenTimeout()));
- }
- requestContext.setServiceProviderPublicKey(providerPublicKey);
- provider.renewToken(requestContext);
+ // if no lifetime has been specified, use the configured timeout value.
+ if (log.isDebugEnabled())
+ log.debug("Lifetime has not been specified. Using the default timeout
value.");
+
request.setLifetime(WSTrustUtil.createDefaultLifetime(this.configuration.getIssuedTokenTimeout()));
+ }
- if (requestContext.getSecurityToken() == null)
- throw new WSTrustException("Token issued by provider " +
provider.getClass().getName() + " is null");
+ // create a context and dispatch to the proper security token provider for
renewal.
+ WSTrustRequestContext context = new WSTrustRequestContext(request,
callerPrincipal);
+ SecurityTokenProvider provider =
this.configuration.getProviderForTokenElementNS(securityToken.getLocalName(),
+ securityToken.getNamespaceURI());
+ if (provider == null)
+ throw new WSTrustException("No SecurityTokenProvider configured for "
+ securityToken.getNamespaceURI() + ":"
+ + securityToken.getLocalName());
+ provider.renewToken(context);
+
+ // create the WS-Trust response with the renewed token.
+ RequestedSecurityTokenType requestedSecurityToken = new
RequestedSecurityTokenType();
+ requestedSecurityToken.setAny(context.getSecurityToken().getTokenValue());
- // construct the ws-trust security token response.
- RequestedSecurityTokenType requestedSecurityToken = new
RequestedSecurityTokenType();
-
requestedSecurityToken.setAny(requestContext.getSecurityToken().getTokenValue());
-
- RequestSecurityTokenResponse response = new RequestSecurityTokenResponse();
- if (request.getContext() != null)
- response.setContext(request.getContext());
-
- response.setTokenType(request.getTokenType());
- response.setLifetime(request.getLifetime());
- response.setAppliesTo(appliesTo);
- response.setRequestedSecurityToken(requestedSecurityToken);
-
- // set the attached and unattached references.
- if (requestContext.getAttachedReference() != null)
-
response.setRequestedAttachedReference(requestContext.getAttachedReference());
- if (requestContext.getUnattachedReference() != null)
-
response.setRequestedUnattachedReference(requestContext.getUnattachedReference());
-
- return response;
- }
- else
- throw new WSTrustException("Unable to find a token provider for the token
request");
+ RequestSecurityTokenResponse response = new RequestSecurityTokenResponse();
+ if (request.getContext() != null)
+ response.setContext(request.getContext());
+ response.setTokenType(request.getTokenType());
+ response.setLifetime(request.getLifetime());
+ response.setRequestedSecurityToken(requestedSecurityToken);
+ if (context.getAttachedReference() != null)
+ response.setRequestedAttachedReference(context.getAttachedReference());
+ if (context.getUnattachedReference() != null)
+ response.setRequestedUnattachedReference(context.getUnattachedReference());
+ return response;
}
/*
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java 2009-11-12
23:28:01 UTC (rev 933)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/plugins/saml/SAML20TokenProvider.java 2009-11-12
23:56:38 UTC (rev 934)
@@ -70,8 +70,7 @@
{
private static Logger logger = Logger.getLogger(SAML20TokenProvider.class);
-
- @SuppressWarnings("unused")
+
private Map<String, String> properties;
/*
@@ -83,7 +82,7 @@
{
this.properties = properties;
}
-
+
/*
* (non-Javadoc)
*
@@ -103,7 +102,6 @@
{
// generate an id for the new assertion.
String assertionID = IDGenerator.create("ID_");
-
issueToken(context, assertionID);
}
@@ -114,11 +112,58 @@
*/
public void renewToken(WSTrustRequestContext context) throws WSTrustException
{
- Element assertion = (Element)
context.getRequestSecurityToken().getRenewTarget().getAny();
-
- String id = assertion.getAttribute("ID");
+ // get the specified assertion that must be renewed.
+ Element token = (Element)
context.getRequestSecurityToken().getRenewTargetElement();
+ if (token == null)
+ throw new WSTrustException("Invalid renew request: missing required
RenewTarget");
+ Element oldAssertionElement = (Element) token.getFirstChild();
+ if (!this.isAssertion(oldAssertionElement))
+ throw new WSTrustException("RenewTarget doesn't not contain a SAMLV2.0
assertion");
- issueToken(context, id); //Just reissue
+ // get the JAXB representation of the old assertion.
+ AssertionType oldAssertion = null;
+ try
+ {
+ oldAssertion = SAMLUtil.fromElement(oldAssertionElement);
+ }
+ catch (JAXBException je)
+ {
+ throw new WSTrustException("Error unmarshalling assertion", je);
+ }
+
+ // adjust the lifetime for the renewed assertion.
+ ConditionsType conditions = oldAssertion.getConditions();
+
conditions.setNotBefore(context.getRequestSecurityToken().getLifetime().getCreated());
+
conditions.setNotOnOrAfter(context.getRequestSecurityToken().getLifetime().getExpires());
+
+ // create a new unique ID for the renewed assertion.
+ String assertionID = IDGenerator.create("ID_");
+
+ // create the new assertion.
+ AssertionType newAssertion = SAMLAssertionFactory.createAssertion(assertionID,
oldAssertion.getIssuer(), context
+ .getRequestSecurityToken().getLifetime().getCreated(), conditions,
oldAssertion.getSubject(), oldAssertion
+ .getStatementOrAuthnStatementOrAuthzDecisionStatement());
+
+ // create a security token with the new assertion.
+ Element assertionElement = null;
+ try
+ {
+ assertionElement = SAMLUtil.toElement(newAssertion);
+ }
+ catch (Exception e)
+ {
+ throw new WSTrustException("Failed to marshall SAMLV2 assertion", e);
+ }
+ SecurityToken securityToken = new
StandardSecurityToken(context.getRequestSecurityToken().getTokenType().toString(),
+ assertionElement, assertionID);
+ context.setSecurityToken(securityToken);
+
+ // set the SAML assertion attached reference.
+ KeyIdentifierType keyIdentifier =
WSTrustUtil.createKeyIdentifier(SAMLUtil.SAML2_VALUE_TYPE, "#" + assertionID);
+ Map<QName, String> attributes = new HashMap<QName, String>();
+ attributes.put(new QName(WSTrustConstants.WSSE11_NS, "TokenType"),
SAMLUtil.SAML2_TOKEN_TYPE);
+ RequestedReferenceType attachedReference =
WSTrustUtil.createRequestedReference(keyIdentifier, attributes);
+ context.setAttachedReference(attachedReference);
}
/*
@@ -131,28 +176,28 @@
{
if (logger.isTraceEnabled())
logger.trace("SAML V2.0 token validation started");
-
+
// get the SAML assertion that must be validated.
ValidateTargetType validateTarget =
context.getRequestSecurityToken().getValidateTarget();
- if(validateTarget == null)
- throw new WSTrustException("Invalid validate message: missing required
ValidateTarget");
-
+ if (validateTarget == null)
+ throw new WSTrustException("Bad validate request: missing required
ValidateTarget");
+
String code = WSTrustConstants.STATUS_CODE_VALID;
String reason = "SAMLV2.0 Assertion successfuly validated";
-
+
AssertionType assertion = null;
-
+
Object assertionObj = validateTarget.getAny();
- if(assertionObj instanceof JAXBElement)
+ if (assertionObj instanceof JAXBElement)
{
JAXBElement<AssertionType> assertionType =
(JAXBElement<AssertionType>) validateTarget.getAny();
- assertion = assertionType.getValue();
+ assertion = assertionType.getValue();
}
- else if(assertionObj instanceof Element)
+ else if (assertionObj instanceof Element)
{
Element assertionElement = (Element) assertionObj;
-
- if(!this.isAssertion(assertionElement))
+
+ if (!this.isAssertion(assertionElement))
{
code = WSTrustConstants.STATUS_CODE_INVALID;
reason = "Validation failure: supplied token is not a SAMLV2.0
Assertion";
@@ -165,21 +210,21 @@
}
catch (JAXBException e)
{
- throw new WSTrustException("Unmarshalling error:",e);
+ throw new WSTrustException("Unmarshalling error:", e);
}
}
}
-
+
// check the assertion lifetime.
try
- {
- if(AssertionUtil.hasExpired(assertion))
+ {
+ if (AssertionUtil.hasExpired(assertion))
{
code = WSTrustConstants.STATUS_CODE_INVALID;
reason = "Validation failure: assertion expired or used before its
lifetime period";
}
}
- catch(Exception ce)
+ catch (Exception ce)
{
code = WSTrustConstants.STATUS_CODE_INVALID;
reason = "Validation failure: unable to verify assertion lifetime: " +
ce.getMessage();
@@ -191,7 +236,7 @@
status.setReason(reason);
context.setStatus(status);
}
-
+
/**
* <p>
* Checks whether the specified element is a SAMLV2.0 assertion or not.
@@ -205,7 +250,7 @@
return element == null ? false :
"Assertion".equals(element.getLocalName())
&&
WSTrustConstants.SAML2_ASSERTION_NS.equals(element.getNamespaceURI());
}
-
+
/**
* Issue a SAML assertion token with the provided ID
* @param context
@@ -234,7 +279,7 @@
else
confirmationMethod = SAMLUtil.SAML2_BEARER_URI;
// TODO: implement the SENDER_VOUCHES scenario.
-
+
SubjectConfirmationType subjectConfirmation =
SAMLAssertionFactory.createSubjectConfirmation(null,
confirmationMethod, keyInfoDataType);
@@ -247,12 +292,12 @@
// create the attribute statements if necessary.
List<StatementAbstractType> statements = null;
Map<String, Object> claimedAttributes = context.getClaimedAttributes();
- if(claimedAttributes != null)
+ if (claimedAttributes != null)
{
statements = new ArrayList<StatementAbstractType>();
statements.add(StatementUtil.createAttributeStatement(claimedAttributes));
}
-
+
// create the SAML assertion.
NameIDType issuerID = SAMLAssertionFactory.createNameID(null, null,
context.getTokenIssuer());
AssertionType assertion = SAMLAssertionFactory.createAssertion(assertionID,
issuerID, lifetime.getCreated(),
Modified:
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java
===================================================================
---
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2009-11-12
23:28:01 UTC (rev 933)
+++
identity-federation/trunk/jboss-identity-fed-core/src/main/java/org/jboss/identity/federation/core/wstrust/wrappers/RequestSecurityToken.java 2009-11-12
23:56:38 UTC (rev 934)
@@ -1102,6 +1102,28 @@
/**
* <p>
+ * Returns the element in the document that represents the renew target type.
+ * </p>
+ *
+ * @return the {@code Element} that represents the renew target type, or {@code null}
if no renew target is found in
+ * the document.
+ */
+ public Element getRenewTargetElement()
+ {
+ if(this.rstDocument == null)
+ throw new IllegalStateException("RST Document is null");
+ String ns = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/";
+ String localName = "RenewTarget";
+
+ NodeList nodeList = rstDocument.getElementsByTagNameNS(ns,localName);
+ if(nodeList != null && nodeList.getLength() > 0)
+ return (Element) nodeList.item(0);
+ else
+ return null;
+ }
+
+ /**
+ * <p>
* Sets the {@code ValidateTarged} section of the request. This elements identifies
the token that is to be
* validated.
* </p>