Package org.jboss.identity.federation.core.wstrust

Source Code of org.jboss.identity.federation.core.wstrust.StandardRequestHandler

/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.identity.federation.core.wstrust;

import java.net.URI;
import java.security.KeyPair;
import java.security.Principal;
import java.security.PublicKey;

import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.SignatureMethod;

import org.apache.log4j.Logger;
import org.jboss.identity.federation.core.saml.v2.util.DocumentUtil;
import org.jboss.identity.federation.core.util.XMLSignatureUtil;
import org.jboss.identity.federation.core.wstrust.plugins.saml.SAMLUtil;
import org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
import org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityTokenResponse;
import org.jboss.identity.federation.ws.policy.AppliesTo;
import org.jboss.identity.federation.ws.trust.RequestedSecurityTokenType;
import org.jboss.identity.federation.ws.trust.StatusType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
* <p>
* Default implementation of the {@code WSTrustRequestHandler} interface. It creates the request context containing the
* original WS-Trust request as well as any information that may be relevant to the token processing, and delegates the
* actual token handling processing to the appropriate {@code SecurityTokenProvider}.
* </p>
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
*/
public class StandardRequestHandler implements WSTrustRequestHandler
{
   private static Logger log = Logger.getLogger(StandardRequestHandler.class);

   private boolean trace = log.isTraceEnabled();

   private STSConfiguration configuration;

   /*
    * (non-Javadoc)
    * @see org.jboss.identity.federation.core.wstrust.WSTrustRequestHandler#initialize(
    *   org.jboss.identity.federation.core.wstrust.STSConfiguration)
    */
   public void initialize(STSConfiguration configuration)
   {
      this.configuration = configuration;
   }

   /*
    * (non-Javadoc)
    * @see org.jboss.identity.federation.core.wstrust.WSTrustRequestHandler#issue(
    *   org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken, java.security.Principal)
    */
   public RequestSecurityTokenResponse issue(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)
      {
         String serviceName = WSTrustUtil.parseAppliesTo(appliesTo);
         if (serviceName != null)
         {
            provider = this.configuration.getProviderForService(serviceName);
            if (provider != null)
            {
               request.setTokenType(URI.create(this.configuration.getTokenTypeForService(serviceName)));
               providerPublicKey = this.configuration.getServiceProviderPublicKey(serviceName);
            }
         }
      }
      // 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)
      {
         provider = this.configuration.getProviderForTokenType(request.getTokenType().toString());
      }
      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)
      {
         // 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.issueToken(requestContext);

         if (requestContext.getSecurityToken() == null)
            throw new WSTrustException("Token issued by provider " + provider.getClass().getName() + " is null");

         // sign the issued token if needed.
         /*if (this.configuration.signIssuedToken() && this.configuration.getSTSKeyPair() != null)
         {
            KeyPair keyPair = this.configuration.getSTSKeyPair();
            if (keyPair != null)
            {
               URI signatureURI = request.getSignatureAlgorithm();
               String signatureMethod = signatureURI != null ? signatureURI.toString() : SignatureMethod.RSA_SHA1;
               try
               {
                  Element tokenElement = (Element) requestContext.getSecurityToken().getTokenValue();
                  XMLSignatureUtil.sign(tokenElement.getOwnerDocument(), keyPair, DigestMethod.SHA1, signatureMethod,
                        "#" + requestContext.getSecurityToken().getTokenID());
                  if(trace)
                  {
                     try
                     {
                        log.trace("Signed Token:" + DocumentUtil.getNodeAsString(tokenElement));
                       
                        Document tokenDocument = DocumentUtil.createDocument();
                        tokenDocument.appendChild(tokenDocument.importNode(tokenElement, true));
                        log.trace("valid=" + XMLSignatureUtil.validate(tokenDocument, keyPair.getPublic()));
                       
                     }catch(Exception ignore){}
                  }
               }
               catch (Exception e)
               {
                  throw new WSTrustException("Failed to sign security token", e);
               }
            }
         }*/

         // construct the ws-trust security token response.
         RequestedSecurityTokenType requestedSecurityToken = new RequestedSecurityTokenType();
         requestedSecurityToken.setAny(requestContext.getSecurityToken().getTokenValue());

         // TODO: create proof token and encrypt the token if needed

         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");
   }

   /*
    * (non-Javadoc)
    * @see org.jboss.identity.federation.core.wstrust.WSTrustRequestHandler#renew(
    *   org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken, java.security.Principal)
    */
   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)
      {
         String serviceName = WSTrustUtil.parseAppliesTo(appliesTo);
         if (serviceName != null)
         {
            provider = this.configuration.getProviderForService(serviceName);
            request.setTokenType(URI.create(this.configuration.getTokenTypeForService(serviceName)));
            providerPublicKey = this.configuration.getServiceProviderPublicKey(serviceName);
         }
      }
      // 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)
      {
         provider = this.configuration.getProviderForTokenType(request.getTokenType().toString());
      }
      else if (appliesTo == null && request.getTokenType() == null)
         throw new WSTrustException("Either AppliesTo or TokenType must be present in a security token request");

      // TODO: get the provider using the token from the request.
      provider = this.configuration.getProviderForTokenType(SAMLUtil.SAML2_TOKEN_TYPE);

      if (provider != null)
      {
         // 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 (requestContext.getSecurityToken() == null)
            throw new WSTrustException("Token issued by provider " + provider.getClass().getName() + " is null");

         // construct the ws-trust security token response.
         RequestedSecurityTokenType requestedSecurityToken = new RequestedSecurityTokenType();
         requestedSecurityToken.setAny(requestContext.getSecurityToken().getTokenValue());

         // TODO: create proof token and encrypt the token if needed

         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");
   }

   /*
    * (non-Javadoc)
    * @see org.jboss.identity.federation.core.wstrust.WSTrustRequestHandler#validate(
    *   org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken, java.security.Principal)
    */
   public RequestSecurityTokenResponse validate(RequestSecurityToken request, Principal callerPrincipal)
         throws WSTrustException
   {
      Document rstDocument = request.getRSTDocument();
      if (rstDocument == null)
         throw new IllegalArgumentException("Request does not contain the DOM Document");

      if (request.getValidateTarget() == null)
         throw new WSTrustException("Unable to validate token: validate target is null");

      if (request.getTokenType() == null)
         request.setTokenType(URI.create(WSTrustConstants.STATUS_TYPE));

      Node securityToken = request.getValidateTargetElement().getFirstChild();
      SecurityTokenProvider provider = this.configuration.getProviderForTokenElementNS(
            securityToken.getLocalName(), securityToken.getNamespaceURI());
      if (provider == null)
         throw new WSTrustException("No SecurityTokenProvider configured for "
               + securityToken.getNamespaceURI() + ":" + securityToken.getLocalName());

      WSTrustRequestContext context = new WSTrustRequestContext(request, callerPrincipal);

      StatusType status = null;

      // validate the security token digital signature.
      if (this.configuration.signIssuedToken() && this.configuration.getSTSKeyPair() != null)
      {
         KeyPair keyPair = this.configuration.getSTSKeyPair();
         try
         {
            if (trace)
            {
               try
               {
                  log.trace("Going to validate:" + DocumentUtil.getNodeAsString(securityToken));
               }
               catch (Exception e)
               {
               }
            }
            Document tokenDocument = DocumentUtil.createDocument();
            Node importedNode = tokenDocument.importNode(securityToken, true);
            tokenDocument.appendChild(importedNode);
            if (!XMLSignatureUtil.validate(tokenDocument, keyPair.getPublic()))
            {
               status = new StatusType();
               status.setCode(WSTrustConstants.STATUS_CODE_INVALID);
               status.setReason("Validation failure: digital signature is invalid");
            }
         }
         catch (Exception e)
         {
            status = new StatusType();
            status.setCode(WSTrustConstants.STATUS_CODE_INVALID);
            status.setReason("Validation failure: unable to verify digital signature: " + e.getMessage());
         }
      }
      // TODO: add logging statements alerting that signature validation was not performed.

      // if the signature is valid, then let the provider handle perform any additional validation checks.
      if (status == null)
      {
         provider.validateToken(context);
         status = context.getStatus();
      }

      // construct and return the response.
      RequestSecurityTokenResponse response = new RequestSecurityTokenResponse();
      if (request.getContext() != null)
         response.setContext(request.getContext());
      response.setTokenType(request.getTokenType());
      response.setStatus(status);

      return response;
   }

   /*
    * (non-Javadoc)
    * @see org.jboss.identity.federation.core.wstrust.WSTrustRequestHandler#cancel(
    *   org.jboss.identity.federation.core.wstrust.wrappers.RequestSecurityToken, java.security.Principal)
    */
   public RequestSecurityTokenResponse cancel(RequestSecurityToken request, Principal callerPrincipal)
         throws WSTrustException
   {
      Document rstDocument = request.getRSTDocument();
      if (rstDocument == null)
         throw new IllegalArgumentException("Request does not contain the DOM Document");

      // TODO: implement cancel logic.
      throw new UnsupportedOperationException();
   }

   public Document postProcess(Document rstrDocument, RequestSecurityToken request) throws WSTrustException
   {
      if (WSTrustConstants.ISSUE_REQUEST.equals(request.getRequestType().toString())
            || WSTrustConstants.RENEW_REQUEST.equals(request.getRequestType().toString()))
      {
         rstrDocument = DocumentUtil.normalizeNamespaces(rstrDocument);

         //Sign and encrypt
         if (this.configuration.signIssuedToken() && this.configuration.getSTSKeyPair() != null)
         {
            KeyPair keyPair = this.configuration.getSTSKeyPair();
            if (keyPair != null)
            {
               URI signatureURI = request.getSignatureAlgorithm();
               String signatureMethod = signatureURI != null ? signatureURI.toString() : SignatureMethod.RSA_SHA1;
               try
               {
                  Node rst = rstrDocument.getElementsByTagNameNS(WSTrustConstants.BASE_NAMESPACE,
                        "RequestedSecurityToken").item(0);
                  Element tokenElement = (Element) rst.getFirstChild();
                  if (trace)
                  {
                     log.trace("NamespaceURI of element to be signed:" + tokenElement.getNamespaceURI());
                  }
                  /* XMLSignatureUtil.sign(tokenElement.getOwnerDocument(), keyPair, DigestMethod.SHA1, signatureMethod,
                         "#" + tokenElement.getAttribute("ID"));
                   */
                  rstrDocument = XMLSignatureUtil.sign(rstrDocument, tokenElement, keyPair, DigestMethod.SHA1,
                        signatureMethod, "#" + tokenElement.getAttribute("ID"));
                  if (trace)
                  {
                     try
                     {
                        log.trace("Signed Token:" + DocumentUtil.getNodeAsString(tokenElement));

                        Document tokenDocument = DocumentUtil.createDocument();
                        tokenDocument.appendChild(tokenDocument.importNode(tokenElement, true));
                        log.trace("valid=" + XMLSignatureUtil.validate(tokenDocument, keyPair.getPublic()));

                     }
                     catch (Exception ignore)
                     {
                     }
                  }
               }
               catch (Exception e)
               {
                  throw new WSTrustException("Failed to sign security token", e);
               }
            }
         }
      }

      return rstrDocument;
   }
}
TOP

Related Classes of org.jboss.identity.federation.core.wstrust.StandardRequestHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.