[jboss-cvs] Picketlink SVN: r1091 - in federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core: wstrust/plugins/saml and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Jul 14 18:24:22 EDT 2011


Author: sguilhen at redhat.com
Date: 2011-07-14 18:24:22 -0400 (Thu, 14 Jul 2011)
New Revision: 1091

Added:
   federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAML11TokenProvider.java
Modified:
   federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/sts/AbstractSecurityTokenProvider.java
Log:
Fixed logic in AbstractSecurityTokenProvider that prevented the revocation registries from being loaded.

Modified: federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/sts/AbstractSecurityTokenProvider.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/sts/AbstractSecurityTokenProvider.java	2011-07-14 15:04:56 UTC (rev 1090)
+++ federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/sts/AbstractSecurityTokenProvider.java	2011-07-14 22:24:22 UTC (rev 1091)
@@ -107,66 +107,64 @@
                pae.printStackTrace();
             }
          }
+      }
+      if (this.tokenRegistry == null)
+         tokenRegistry = new DefaultTokenRegistry();
 
-         if (this.tokenRegistry == null)
-            tokenRegistry = new DefaultTokenRegistry();
-
-         // check if a revocation registry option has been set.
-         String registryOption = this.properties.get(REVOCATION_REGISTRY);
-         if (registryOption == null)
+      // check if a revocation registry option has been set.
+      String registryOption = this.properties.get(REVOCATION_REGISTRY);
+      if (registryOption == null)
+      {
+         if (logger.isDebugEnabled())
+            logger.debug("Revocation registry option not specified: cancelled ids will not be persisted!");
+      }
+      else
+      {
+         // if a file is to be used as registry, check if the user has specified the file name.
+         if ("FILE".equalsIgnoreCase(registryOption))
          {
-            if (logger.isDebugEnabled())
-               logger.debug("Revocation registry option not specified: cancelled ids will not be persisted!");
+            String registryFile = this.properties.get(REVOCATION_REGISTRY_FILE);
+            if (registryFile != null)
+               this.revocationRegistry = new FileBasedRevocationRegistry(registryFile);
+            else
+               this.revocationRegistry = new FileBasedRevocationRegistry();
          }
+         // another option is to use the default JPA registry to store the revoked ids.
+         else if ("JPA".equalsIgnoreCase(registryOption))
+         {
+            String configuration = this.properties.get(REVOCATION_REGISTRY_JPA_CONFIG);
+            if (configuration != null)
+               this.revocationRegistry = new JPABasedRevocationRegistry(configuration);
+            else
+               this.revocationRegistry = new JPABasedRevocationRegistry();
+         }
+         // the user has specified its own registry implementation class.
          else
          {
-            // if a file is to be used as registry, check if the user has specified the file name.
-            if ("FILE".equalsIgnoreCase(registryOption))
+            try
             {
-               String registryFile = this.properties.get(REVOCATION_REGISTRY_FILE);
-               if (registryFile != null)
-                  this.revocationRegistry = new FileBasedRevocationRegistry(registryFile);
-               else
-                  this.revocationRegistry = new FileBasedRevocationRegistry();
-            }
-            // another option is to use the default JPA registry to store the revoked ids.
-            else if ("JPA".equalsIgnoreCase(registryOption))
-            {
-               String configuration = this.properties.get(REVOCATION_REGISTRY_JPA_CONFIG);
-               if (configuration != null)
-                  this.revocationRegistry = new JPABasedRevocationRegistry(configuration);
-               else
-                  this.revocationRegistry = new JPABasedRevocationRegistry();
-            }
-            // the user has specified its own registry implementation class.
-            else
-            {
-               try
+               Class<?> clazz = SecurityActions.loadClass(getClass(), registryOption);
+               if (clazz != null)
                {
-                  Class<?> clazz = SecurityActions.loadClass(getClass(), registryOption);
-                  if (clazz != null)
+                  Object object = clazz.newInstance();
+                  if (object instanceof RevocationRegistry)
+                     this.revocationRegistry = (RevocationRegistry) object;
+                  else
                   {
-                     Object object = clazz.newInstance();
-                     if (object instanceof RevocationRegistry)
-                        this.revocationRegistry = (RevocationRegistry) object;
-                     else
-                     {
-                        logger.warn(registryOption
-                              + " is not an instance of RevocationRegistry - using default registry");
-                     }
+                     logger.warn(registryOption
+                           + " is not an instance of RevocationRegistry - using default registry");
                   }
                }
-               catch (Exception pae)
-               {
-                  logger.warn("Error instantiating revocation registry class - using default registry");
-                  pae.printStackTrace();
-               }
             }
+            catch (Exception pae)
+            {
+               logger.warn("Error instantiating revocation registry class - using default registry");
+               pae.printStackTrace();
+            }
          }
-
-         if (this.revocationRegistry == null)
-            this.revocationRegistry = new DefaultRevocationRegistry();
       }
-   }
 
+      if (this.revocationRegistry == null)
+         this.revocationRegistry = new DefaultRevocationRegistry();
+   }
 }
\ No newline at end of file

Added: federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAML11TokenProvider.java
===================================================================
--- federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAML11TokenProvider.java	                        (rev 0)
+++ federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAML11TokenProvider.java	2011-07-14 22:24:22 UTC (rev 1091)
@@ -0,0 +1,383 @@
+package org.picketlink.identity.federation.core.wstrust.plugins.saml;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+import org.apache.log4j.Logger;
+import org.picketlink.identity.federation.core.exceptions.ProcessingException;
+import org.picketlink.identity.federation.core.interfaces.ProtocolContext;
+import org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider;
+import org.picketlink.identity.federation.core.saml.v1.SAML11Constants;
+import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
+import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLConstants;
+import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
+import org.picketlink.identity.federation.core.sts.AbstractSecurityTokenProvider;
+import org.picketlink.identity.federation.core.wstrust.SecurityToken;
+import org.picketlink.identity.federation.core.wstrust.StandardSecurityToken;
+import org.picketlink.identity.federation.core.wstrust.WSTrustConstants;
+import org.picketlink.identity.federation.core.wstrust.WSTrustRequestContext;
+import org.picketlink.identity.federation.core.wstrust.WSTrustUtil;
+import org.picketlink.identity.federation.core.wstrust.wrappers.Lifetime;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11AssertionType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11AudienceRestrictionCondition;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11AuthenticationStatementType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11ConditionsType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11NameIdentifierType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11StatementAbstractType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11SubjectConfirmationType;
+import org.picketlink.identity.federation.saml.v1.assertion.SAML11SubjectType;
+import org.picketlink.identity.federation.ws.policy.AppliesTo;
+import org.picketlink.identity.federation.ws.trust.RequestedReferenceType;
+import org.picketlink.identity.federation.ws.trust.StatusType;
+import org.picketlink.identity.federation.ws.wss.secext.KeyIdentifierType;
+import org.picketlink.identity.xmlsec.w3.xmldsig.KeyInfoType;
+import org.w3c.dom.Element;
+
+public class SAML11TokenProvider extends AbstractSecurityTokenProvider
+{
+   protected static Logger logger = Logger.getLogger(SAML11TokenProvider.class);
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @seeorg.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#cancelToken(org.picketlink.identity.
+    * federation.core.interfaces.ProtocolContext)
+    */
+   @Override
+   public void cancelToken(ProtocolContext context) throws ProcessingException
+   {
+      if (!(context instanceof WSTrustRequestContext))
+         return;
+
+      WSTrustRequestContext wstContext = (WSTrustRequestContext) context;
+
+      // get the SAML assertion that will be canceled.
+      Element token = wstContext.getRequestSecurityToken().getCancelTargetElement();
+      if (token == null)
+         throw new ProcessingException("Invalid cancel request: missing required CancelTarget");
+      Element assertionElement = (Element) token.getFirstChild();
+      if (!this.isSAMLAssertion(assertionElement))
+         throw new ProcessingException("CancelTarget doesn't not contain a SAMLV1.1 assertion");
+
+      // get the assertion ID and add it to the canceled assertions set.
+      String assertionId = assertionElement.getAttribute("AssertionID");
+      this.revocationRegistry.revokeToken(SAMLUtil.SAML11_TOKEN_TYPE, assertionId);
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#issueToken(org.picketlink.identity.federation
+    * .core.interfaces.ProtocolContext)
+    */
+   @Override
+   public void issueToken(ProtocolContext context) throws ProcessingException
+   {
+      if (!(context instanceof WSTrustRequestContext))
+         return;
+
+      WSTrustRequestContext wstContext = (WSTrustRequestContext) context;
+      // generate an id for the new assertion.
+      String assertionID = IDGenerator.create("ID_");
+
+      // lifetime and audience restrictions.
+      Lifetime lifetime = wstContext.getRequestSecurityToken().getLifetime();
+      SAML11AudienceRestrictionCondition restriction = null;
+      AppliesTo appliesTo = wstContext.getRequestSecurityToken().getAppliesTo();
+      if (appliesTo != null)
+      {
+         restriction = new SAML11AudienceRestrictionCondition();
+         restriction.add(URI.create(WSTrustUtil.parseAppliesTo(appliesTo)));
+      }
+      SAML11ConditionsType conditions = new SAML11ConditionsType();
+      conditions.setNotBefore(lifetime.getCreated());
+      conditions.setNotOnOrAfter(lifetime.getExpires());
+      conditions.add(restriction);
+
+      // the assertion principal (default is caller principal)
+      Principal principal = wstContext.getCallerPrincipal();
+
+      String confirmationMethod = null;
+      KeyInfoType keyInfoType = null;
+      // if there is a on-behalf-of principal, we have the sender vouches confirmation method.
+      if (wstContext.getOnBehalfOfPrincipal() != null)
+      {
+         principal = wstContext.getOnBehalfOfPrincipal();
+         confirmationMethod = SAMLUtil.SAML11_SENDER_VOUCHES_URI;
+      }
+      // if there is a proof-of-possession token in the context, we have the holder of key confirmation method.
+      else if (wstContext.getProofTokenInfo() != null)
+      {
+         confirmationMethod = SAMLUtil.SAML11_HOLDER_OF_KEY_URI;
+         keyInfoType = wstContext.getProofTokenInfo();
+      }
+      else
+         confirmationMethod = SAMLUtil.SAML11_BEARER_URI;
+
+      SAML11SubjectConfirmationType subjectConfirmation = new SAML11SubjectConfirmationType();
+      subjectConfirmation.addConfirmationMethod(URI.create(confirmationMethod));
+      // TODO: set the key info.
+
+      // create a subject using the caller principal or on-behalf-of principal.
+      String subjectName = principal == null ? "ANONYMOUS" : principal.getName();
+      SAML11NameIdentifierType nameId = new SAML11NameIdentifierType(subjectName);
+      nameId.setFormat(URI.create(SAML11Constants.FORMAT_UNSPECIFIED));
+      SAML11SubjectType subject = new SAML11SubjectType();
+      subject.setChoice(new SAML11SubjectType.SAML11SubjectTypeChoice(nameId));
+      subject.setSubjectConfirmation(subjectConfirmation);
+
+      // add the subject to an auth statement.
+      SAML11AuthenticationStatementType authStatement = new SAML11AuthenticationStatementType(URI
+            .create("urn:picketlink:auth"), lifetime.getCreated());
+      authStatement.setSubject(subject);
+
+      // TODO: add attribute statements.
+
+      // create the SAML assertion.
+      SAML11AssertionType assertion = new SAML11AssertionType(assertionID, lifetime.getCreated());
+      assertion.add(authStatement);
+      assertion.setConditions(conditions);
+      assertion.setIssuer(wstContext.getTokenIssuer());
+
+      // convert the constructed assertion to element.
+      Element assertionElement = null;
+      try
+      {
+         assertionElement = SAMLUtil.toElement(assertion);
+      }
+      catch (Exception e)
+      {
+         throw new ProcessingException("Failed to marshall SAMLV1.1 assertion", e);
+      }
+      SecurityToken token = new StandardSecurityToken(wstContext.getRequestSecurityToken().getTokenType().toString(),
+            assertionElement, assertionID);
+      wstContext.setSecurityToken(token);
+
+      // set the SAML assertion attached reference.
+      KeyIdentifierType keyIdentifier = WSTrustUtil.createKeyIdentifier(SAMLUtil.SAML11_VALUE_TYPE, "#" + assertionID);
+      Map<QName, String> attributes = new HashMap<QName, String>();
+      attributes.put(new QName(WSTrustConstants.WSSE11_NS, "TokenType", WSTrustConstants.WSSE.PREFIX_11),
+            SAMLUtil.SAML11_TOKEN_TYPE);
+      RequestedReferenceType attachedReference = WSTrustUtil.createRequestedReference(keyIdentifier, attributes);
+      wstContext.setAttachedReference(attachedReference);
+
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#renewToken(org.picketlink.identity.federation
+    * .core.interfaces.ProtocolContext)
+    */
+   @Override
+   public void renewToken(ProtocolContext context) throws ProcessingException
+   {
+      if (!(context instanceof WSTrustRequestContext))
+         return;
+
+      WSTrustRequestContext wstContext = (WSTrustRequestContext) context;
+      // get the specified assertion that must be renewed.
+      Element token = wstContext.getRequestSecurityToken().getRenewTargetElement();
+      if (token == null)
+         throw new ProcessingException("Invalid renew request: missing required RenewTarget");
+      Element oldAssertionElement = (Element) token.getFirstChild();
+      if (!this.isSAMLAssertion(oldAssertionElement))
+         throw new ProcessingException("RenewTarget doesn't not contain a SAMLV1.1 assertion");
+
+      // get the JAXB representation of the old assertion.
+      SAML11AssertionType oldAssertion = null;
+      try
+      {
+         oldAssertion = SAMLUtil.saml11FromElement(oldAssertionElement);
+      }
+      catch (Exception je)
+      {
+         throw new ProcessingException("Error unmarshalling assertion", je);
+      }
+
+      // canceled assertions cannot be renewed.
+      if (this.revocationRegistry.isRevoked(SAMLUtil.SAML11_TOKEN_TYPE, oldAssertion.getID()))
+         throw new ProcessingException("SAMLV1.1 Assertion with id " + oldAssertion.getID()
+               + " has been canceled and cannot be renewed");
+
+      // adjust the lifetime for the renewed assertion.
+      SAML11ConditionsType conditions = oldAssertion.getConditions();
+      conditions.setNotBefore(wstContext.getRequestSecurityToken().getLifetime().getCreated());
+      conditions.setNotOnOrAfter(wstContext.getRequestSecurityToken().getLifetime().getExpires());
+
+      // create a new unique ID for the renewed assertion.
+      String assertionID = IDGenerator.create("ID_");
+
+      // get the list of all assertion statements - should include the auth statement that contains the subject.
+      List<SAML11StatementAbstractType> statements = new ArrayList<SAML11StatementAbstractType>();
+      statements.addAll(oldAssertion.getStatements());
+
+      // create the new assertion.
+      SAML11AssertionType newAssertion = new SAML11AssertionType(assertionID, conditions.getNotBefore());
+      newAssertion.addAllStatements(statements);
+      newAssertion.setConditions(conditions);
+      newAssertion.setIssuer(wstContext.getTokenIssuer());
+
+      // create a security token with the new assertion.
+      Element assertionElement = null;
+      try
+      {
+         assertionElement = SAMLUtil.toElement(newAssertion);
+      }
+      catch (Exception e)
+      {
+         throw new ProcessingException("Failed to marshall SAMLV1.1 assertion", e);
+      }
+      SecurityToken securityToken = new StandardSecurityToken(wstContext.getRequestSecurityToken().getTokenType()
+            .toString(), assertionElement, assertionID);
+      wstContext.setSecurityToken(securityToken);
+
+      // set the SAML assertion attached reference.
+      KeyIdentifierType keyIdentifier = WSTrustUtil.createKeyIdentifier(SAMLUtil.SAML11_VALUE_TYPE, "#" + assertionID);
+      Map<QName, String> attributes = new HashMap<QName, String>();
+      attributes.put(new QName(WSTrustConstants.WSSE11_NS, "TokenType"), SAMLUtil.SAML11_TOKEN_TYPE);
+      RequestedReferenceType attachedReference = WSTrustUtil.createRequestedReference(keyIdentifier, attributes);
+      wstContext.setAttachedReference(attachedReference);
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see
+    * org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#validateToken(org.picketlink.identity
+    * .federation.core.interfaces.ProtocolContext)
+    */
+   @Override
+   public void validateToken(ProtocolContext context) throws ProcessingException
+   {
+      if (!(context instanceof WSTrustRequestContext))
+         return;
+
+      WSTrustRequestContext wstContext = (WSTrustRequestContext) context;
+      if (logger.isTraceEnabled())
+         logger.trace("SAML V1.1 token validation started");
+
+      // get the SAML assertion that must be validated.
+      Element token = wstContext.getRequestSecurityToken().getValidateTargetElement();
+      if (token == null)
+         throw new ProcessingException("Bad validate request: missing required ValidateTarget");
+
+      String code = WSTrustConstants.STATUS_CODE_VALID;
+      String reason = "SAMLV1.1 Assertion successfuly validated";
+
+      SAML11AssertionType assertion = null;
+      Element assertionElement = (Element) token.getFirstChild();
+      if (!this.isSAMLAssertion(assertionElement))
+      {
+         code = WSTrustConstants.STATUS_CODE_INVALID;
+         reason = "Validation failure: supplied token is not a SAMLV1.1 Assertion";
+      }
+      else
+      {
+         try
+         {
+            assertion = SAMLUtil.saml11FromElement(assertionElement);
+         }
+         catch (Exception e)
+         {
+            throw new ProcessingException("Unmarshalling error:", e);
+         }
+      }
+
+      // check if the assertion has been canceled before.
+      if (this.revocationRegistry.isRevoked(SAMLUtil.SAML11_TOKEN_TYPE, assertion.getID()))
+      {
+         code = WSTrustConstants.STATUS_CODE_INVALID;
+         reason = "Validation failure: assertion with id " + assertion.getID() + " has been canceled";
+      }
+
+      // check the assertion lifetime.
+      try
+      {
+         if (AssertionUtil.hasExpired(assertion))
+         {
+            code = WSTrustConstants.STATUS_CODE_INVALID;
+            reason = "Validation failure: assertion expired or used before its lifetime period";
+         }
+      }
+      catch (Exception ce)
+      {
+         code = WSTrustConstants.STATUS_CODE_INVALID;
+         reason = "Validation failure: unable to verify assertion lifetime: " + ce.getMessage();
+      }
+
+      // construct the status and set it on the request context.
+      StatusType status = new StatusType();
+      status.setCode(code);
+      status.setReason(reason);
+      wstContext.setStatus(status);
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#family()
+    */
+   @Override
+   public String family()
+   {
+      return SecurityTokenProvider.FAMILY_TYPE.WS_TRUST.toString();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#getSupportedQName()
+    */
+   @Override
+   public QName getSupportedQName()
+   {
+      return new QName(tokenType(), JBossSAMLConstants.ASSERTION.get());
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#supports(java.lang.String)
+    */
+   @Override
+   public boolean supports(String namespace)
+   {
+      return WSTrustConstants.BASE_NAMESPACE.equals(namespace);
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
+    * @see org.picketlink.identity.federation.core.interfaces.SecurityTokenProvider#tokenType()
+    */
+   @Override
+   public String tokenType()
+   {
+      return SAMLUtil.SAML11_TOKEN_TYPE;
+   }
+
+   /**
+    * <p>
+    * Checks whether the specified element is a SAMLV1.1 assertion or not.
+    * </p>
+    * 
+    * @param element
+    *           the {@code Element} being verified.
+    * @return {@code true} if the element is a SAMLV1.1 assertion; {@code false} otherwise.
+    */
+   private boolean isSAMLAssertion(Element element)
+   {
+      return element == null ? false : "Assertion".equals(element.getLocalName())
+            && SAML11Constants.ASSERTION_11_NSURI.equals(element.getNamespaceURI());
+   }
+
+}



More information about the jboss-cvs-commits mailing list