cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cohei...@apache.org
Subject svn commit: r1173182 [3/9] - in /cxf/trunk: ./ services/ services/sts/ services/sts/sts-core/ services/sts/sts-core/src/ services/sts/sts-core/src/main/ services/sts/sts-core/src/main/java/ services/sts/sts-core/src/main/java/org/ services/sts/sts-core...
Date Tue, 20 Sep 2011 15:12:11 GMT
Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/RequestParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/RequestParser.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/RequestParser.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/RequestParser.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,562 @@
+/**
+ * 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.request;
+
+import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Iterator;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.ws.WebServiceContext;
+import javax.xml.ws.handler.MessageContext;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.common.util.Base64Utility;
+import org.apache.cxf.helpers.CastUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.sts.QNameConstants;
+import org.apache.cxf.sts.STSConstants;
+import org.apache.cxf.sts.claims.RequestClaim;
+import org.apache.cxf.sts.claims.RequestClaimCollection;
+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.CancelTargetType;
+import org.apache.cxf.ws.security.sts.provider.model.ClaimsType;
+import org.apache.cxf.ws.security.sts.provider.model.EntropyType;
+import org.apache.cxf.ws.security.sts.provider.model.LifetimeType;
+import org.apache.cxf.ws.security.sts.provider.model.OnBehalfOfType;
+import org.apache.cxf.ws.security.sts.provider.model.RequestSecurityTokenType;
+import org.apache.cxf.ws.security.sts.provider.model.UseKeyType;
+import org.apache.cxf.ws.security.sts.provider.model.ValidateTargetType;
+import org.apache.cxf.ws.security.sts.provider.model.secext.ReferenceType;
+import org.apache.cxf.ws.security.sts.provider.model.secext.SecurityTokenReferenceType;
+import org.apache.cxf.ws.security.sts.provider.model.wstrust14.ActAsType;
+import org.apache.cxf.ws.security.sts.provider.model.xmldsig.KeyInfoType;
+import org.apache.cxf.ws.security.sts.provider.model.xmldsig.X509DataType;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.handler.WSHandlerResult;
+import org.apache.ws.security.message.token.SecurityContextToken;
+import org.apache.xml.security.utils.Constants;
+
+/**
+ * This class parses a RequestSecurityToken object. It stores the values that it finds into a KeyRequirements
+ * and TokenRequirements objects.
+ */
+public class RequestParser {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(RequestParser.class);
+    
+    private KeyRequirements keyRequirements = new KeyRequirements();
+    private TokenRequirements tokenRequirements = new TokenRequirements();
+
+    public void parseRequest(
+        RequestSecurityTokenType request, WebServiceContext wsContext
+    ) throws STSException {
+        LOG.fine("Parsing RequestSecurityToken");
+        keyRequirements = new KeyRequirements();
+        tokenRequirements = new TokenRequirements();
+        
+        for (Object requestObject : request.getAny()) {
+            // JAXB types
+            if (requestObject instanceof JAXBElement<?>) {
+                JAXBElement<?> jaxbElement = (JAXBElement<?>) requestObject;
+                boolean found = parseTokenRequirements(jaxbElement, tokenRequirements, wsContext);
+                if (!found) {
+                    found = parseKeyRequirements(jaxbElement, keyRequirements);
+                }
+                if (!found) {
+                    LOG.log(Level.WARNING, "Found a JAXB object of unknown type: " + jaxbElement.getName());
+                    throw new STSException(
+                        "An unknown element was received", STSException.BAD_REQUEST
+                    );
+                }
+            // SecondaryParameters/AppliesTo
+            } else if (requestObject instanceof Element) {
+                Element element = (Element)requestObject;
+                if (STSConstants.WST_NS_05_12.equals(element.getNamespaceURI())
+                    && "SecondaryParameters".equals(element.getLocalName())) {
+                    parseSecondaryParameters(element);
+                } else if ("AppliesTo".equals(element.getLocalName())
+                    && (STSConstants.WSP_NS.equals(element.getNamespaceURI())
+                        || STSConstants.WSP_NS_04.equals(element.getNamespaceURI()))) {
+                    tokenRequirements.setAppliesTo(element);
+                    LOG.fine("Found AppliesTo element");
+                } else {
+                    LOG.log(
+                        Level.WARNING, 
+                        "An unknown (DOM) element was received: " + element.getLocalName()
+                    );
+                    throw new STSException(
+                        "An unknown element was received", STSException.BAD_REQUEST
+                    );
+                }
+            } else {
+                LOG.log(Level.WARNING, "An unknown element was received");
+                throw new STSException(
+                    "An unknown element was received", STSException.BAD_REQUEST
+                );
+            }
+        }
+        String context = request.getContext();
+        tokenRequirements.setContext(context);
+        LOG.fine("Received Context attribute: " + context);
+    }
+    
+    public KeyRequirements getKeyRequirements() {
+        return keyRequirements;
+    }
+    
+    public TokenRequirements getTokenRequirements() {
+        return tokenRequirements;
+    }
+    
+    /**
+     * Parse the Key and Encryption requirements into the KeyRequirements argument.
+     */
+    private static boolean parseKeyRequirements(
+        JAXBElement<?> jaxbElement, KeyRequirements keyRequirements
+    ) {
+        if (QNameConstants.AUTHENTICATION_TYPE.equals(jaxbElement.getName())) {
+            String authenticationType = (String)jaxbElement.getValue();
+            keyRequirements.setAuthenticationType(authenticationType);
+            LOG.fine("Found AuthenticationType: " + authenticationType);
+        } else if (QNameConstants.KEY_TYPE.equals(jaxbElement.getName())) {
+            String keyType = (String)jaxbElement.getValue();
+            keyRequirements.setKeyType(keyType);
+            LOG.fine("Found KeyType: " + keyType);
+        } else if (QNameConstants.KEY_SIZE.equals(jaxbElement.getName())) {
+            long keySize = ((Long)jaxbElement.getValue()).longValue();
+            keyRequirements.setKeySize(keySize);
+            LOG.fine("Found KeySize: " + keySize);
+        } else if (QNameConstants.SIGNATURE_ALGORITHM.equals(jaxbElement.getName())) {
+            String signatureAlgorithm = (String)jaxbElement.getValue();
+            keyRequirements.setSignatureAlgorithm(signatureAlgorithm);
+            LOG.fine("Found Signature Algorithm: " + signatureAlgorithm);
+        } else if (QNameConstants.ENCRYPTION_ALGORITHM.equals(jaxbElement.getName())) {
+            String encryptionAlgorithm = (String)jaxbElement.getValue();
+            keyRequirements.setEncryptionAlgorithm(encryptionAlgorithm);
+            LOG.fine("Found Encryption Algorithm: " + encryptionAlgorithm);
+        } else if (QNameConstants.C14N_ALGORITHM.equals(jaxbElement.getName())) {
+            String c14nAlgorithm = (String)jaxbElement.getValue();
+            keyRequirements.setC14nAlgorithm(c14nAlgorithm);
+            LOG.fine("Found C14n Algorithm: " + c14nAlgorithm);
+        } else if (QNameConstants.COMPUTED_KEY_ALGORITHM.equals(jaxbElement.getName())) {
+            String computedKeyAlgorithm = (String)jaxbElement.getValue();
+            keyRequirements.setComputedKeyAlgorithm(computedKeyAlgorithm);
+            LOG.fine("Found ComputedKeyAlgorithm: " + computedKeyAlgorithm);
+        } else if (QNameConstants.KEYWRAP_ALGORITHM.equals(jaxbElement.getName())) {
+            String keywrapAlgorithm = (String)jaxbElement.getValue();
+            keyRequirements.setKeywrapAlgorithm(keywrapAlgorithm);
+            LOG.fine("Found KeyWrapAlgorithm: " + keywrapAlgorithm);
+        } else if (QNameConstants.USE_KEY.equals(jaxbElement.getName())) {
+            UseKeyType useKey = (UseKeyType)jaxbElement.getValue();
+            X509Certificate cert = parseUseKey(useKey);
+            keyRequirements.setCertificate(cert);
+        } else if (QNameConstants.ENTROPY.equals(jaxbElement.getName())) {
+            EntropyType entropyType = (EntropyType)jaxbElement.getValue();
+            Entropy entropy = parseEntropy(entropyType);
+            keyRequirements.setEntropy(entropy);
+        } else if (QNameConstants.REQUEST_TYPE.equals(jaxbElement.getName())) { //NOPMD
+            // Skip the request type.
+        } else {
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * Parse the Token requirements into the TokenRequirements argument.
+     */
+    private static boolean parseTokenRequirements(
+        JAXBElement<?> jaxbElement, 
+        TokenRequirements tokenRequirements,
+        WebServiceContext wsContext
+    ) {
+        if (QNameConstants.TOKEN_TYPE.equals(jaxbElement.getName())) {
+            String tokenType = (String)jaxbElement.getValue();
+            tokenRequirements.setTokenType(tokenType);
+            LOG.fine("Found TokenType: " + tokenType);
+        } else if (QNameConstants.ON_BEHALF_OF.equals(jaxbElement.getName())) {
+            OnBehalfOfType onBehalfOfType = (OnBehalfOfType)jaxbElement.getValue();
+            ReceivedToken onBehalfOf = new ReceivedToken(onBehalfOfType.getAny());
+            tokenRequirements.setOnBehalfOf(onBehalfOf);
+            LOG.fine("Found OnBehalfOf token");
+        } else if (QNameConstants.ACT_AS.equals(jaxbElement.getName())) {
+            ActAsType actAsType = (ActAsType)jaxbElement.getValue();
+            ReceivedToken actAs = new ReceivedToken(actAsType.getAny());
+            tokenRequirements.setActAs(actAs);
+            LOG.fine("Found ActAs token");
+        } else if (QNameConstants.LIFETIME.equals(jaxbElement.getName())) {
+            LifetimeType lifetimeType = (LifetimeType)jaxbElement.getValue();
+            Lifetime lifetime = new Lifetime();
+            if (lifetimeType.getCreated() != null) {
+                lifetime.setCreated(lifetimeType.getCreated().getValue());
+            }
+            if (lifetimeType.getExpires() != null) {
+                lifetime.setExpires(lifetimeType.getExpires().getValue());
+            }
+            tokenRequirements.setLifetime(lifetime);
+            LOG.fine("Found Lifetime element");
+        } else if (QNameConstants.VALIDATE_TARGET.equals(jaxbElement.getName())) {
+            ValidateTargetType validateTargetType = (ValidateTargetType)jaxbElement.getValue();
+            ReceivedToken validateTarget = new ReceivedToken(validateTargetType.getAny());
+            if (isTokenReferenced(validateTarget)) {
+                validateTarget = fetchTokenFromReference(validateTarget, wsContext);
+            }  
+            tokenRequirements.setValidateTarget(validateTarget);
+            LOG.fine("Found ValidateTarget token");
+        } else if (QNameConstants.CANCEL_TARGET.equals(jaxbElement.getName())) {
+            CancelTargetType cancelTargetType = (CancelTargetType)jaxbElement.getValue();
+            ReceivedToken cancelTarget = new ReceivedToken(cancelTargetType.getAny());
+            if (isTokenReferenced(cancelTarget)) {
+                cancelTarget = fetchTokenFromReference(cancelTarget, wsContext);
+            }          
+            tokenRequirements.setCancelTarget(cancelTarget);
+            LOG.fine("Found CancelTarget token");
+        } else if (QNameConstants.CLAIMS.equals(jaxbElement.getName())) {
+            ClaimsType claimsType = (ClaimsType)jaxbElement.getValue();
+            RequestClaimCollection requestedClaims = parseClaims(claimsType);
+            tokenRequirements.setClaims(requestedClaims);
+            LOG.fine("Found Claims token");
+        } else {
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * Parse the UseKey structure to get a certificate
+     * @param useKey The UseKey object
+     * @return the X509 certificate that has been parsed
+     * @throws STSException
+     */
+    private static X509Certificate parseUseKey(UseKeyType useKey) throws STSException {
+        byte[] x509 = null;
+        KeyInfoType keyInfoType = extractType(useKey.getAny(), KeyInfoType.class);
+        if (null != keyInfoType) {
+            LOG.fine("Found KeyInfo UseKey type");
+            for (Object keyInfoContent : keyInfoType.getContent()) {
+                X509DataType x509DataType = extractType(keyInfoContent, X509DataType.class);
+                if (null != x509DataType) {
+                    LOG.fine("Found X509Data KeyInfo type");
+                    for (Object x509Object 
+                        : x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName()) {
+                        x509 = extractType(x509Object, byte[].class);
+                        if (null != x509) {
+                            LOG.fine("Found X509Certificate UseKey type");
+                            break;
+                        }
+                    }
+                }
+            }
+        } else if (useKey.getAny() instanceof Element) {
+            Element elementNSImpl = (Element) useKey.getAny();
+            NodeList x509CertData = 
+                elementNSImpl.getElementsByTagNameNS(
+                    Constants.SignatureSpecNS, Constants._TAG_X509CERTIFICATE
+                );
+            if (x509CertData != null && x509CertData.getLength() > 0) {
+                try {
+                    x509 = Base64Utility.decode(x509CertData.item(0).getTextContent());
+                    LOG.fine("Found X509Certificate UseKey type");
+                } catch (Exception e) {
+                    LOG.log(Level.WARNING, "", e);
+                    throw new STSException(e.getMessage(), e, STSException.INVALID_REQUEST);
+                }
+            }
+        }
+        
+        if (x509 != null) {
+            try {
+                CertificateFactory cf = CertificateFactory.getInstance("X.509");
+                X509Certificate cert =
+                    (X509Certificate)cf.generateCertificate(new ByteArrayInputStream(x509));
+                LOG.fine("Successfully parsed X509 Certificate from UseKey");
+                return cert;
+            } catch (CertificateException ex) {
+                LOG.log(Level.WARNING, "", ex);
+                throw new STSException("Error in parsing certificate: ", ex, STSException.INVALID_REQUEST);
+            }
+        }
+        return null;
+    }
+    
+    private static <T> T extractType(Object param, Class<T> clazz) {
+        if (param instanceof JAXBElement<?>) {
+            JAXBElement<?> jaxbElement = (JAXBElement<?>) param;
+            if (clazz == jaxbElement.getDeclaredType()) {
+                return clazz.cast(jaxbElement.getValue());
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Parse an Entropy object
+     * @param entropy an Entropy object
+     */
+    private static Entropy parseEntropy(EntropyType entropyType) {
+        for (Object entropyObject : entropyType.getAny()) {
+            JAXBElement<?> entropyObjectJaxb = (JAXBElement<?>) entropyObject;
+            if (QNameConstants.BINARY_SECRET.equals(entropyObjectJaxb.getName())) {
+                BinarySecretType binarySecret = 
+                    (BinarySecretType)entropyObjectJaxb.getValue();
+                LOG.fine("Found BinarySecret Entropy type");
+                Entropy entropy = new Entropy();
+                entropy.setBinarySecretType(binarySecret.getType());
+                entropy.setBinarySecretValue(binarySecret.getValue());
+                return entropy;
+            } else {
+                LOG.fine("Unsupported Entropy type: " + entropyObjectJaxb.getName());
+            }
+            // TODO support EncryptedKey
+        }
+        return null;
+    }
+    
+    /**
+     * Parse the secondaryParameters element. Precedence goes to values that are specified as
+     * direct children of the RequestSecurityToken element. 
+     * @param secondaryParameters the secondaryParameters element to parse
+     */
+    private void parseSecondaryParameters(Element secondaryParameters) {
+        LOG.fine("Found SecondaryParameters element");
+        Element child = DOMUtils.getFirstElement(secondaryParameters);
+        while (child != null) {
+            String localName = child.getLocalName();
+            String namespace = child.getNamespaceURI();
+            if (keyRequirements.getKeySize() == 0 && "KeySize".equals(localName) 
+                && STSConstants.WST_NS_05_12.equals(namespace)) {
+                long keySize = Integer.parseInt(child.getTextContent());
+                keyRequirements.setKeySize(keySize);
+                LOG.fine("Found KeySize: " + keySize);
+            } else if (tokenRequirements.getTokenType() == null 
+                && "TokenType".equals(localName) && STSConstants.WST_NS_05_12.equals(namespace)) {
+                String tokenType = child.getTextContent();
+                tokenRequirements.setTokenType(tokenType);
+                LOG.fine("Found TokenType: " + tokenType);
+            } else if (keyRequirements.getKeyType() == null 
+                && "KeyType".equals(localName) && STSConstants.WST_NS_05_12.equals(namespace)) {
+                String keyType = child.getTextContent();
+                LOG.fine("Found KeyType: " + keyType);
+                keyRequirements.setKeyType(keyType);
+            } else if (tokenRequirements.getClaims() == null 
+                && "Claims".equals(localName) && STSConstants.WST_NS_05_12.equals(namespace)) {
+                LOG.fine("Found Claims element");
+                RequestClaimCollection requestedClaims = parseClaims(child);
+                tokenRequirements.setClaims(requestedClaims);
+            } else {
+                LOG.fine("Found unknown element: " + localName + " " + namespace);
+            }
+            child = DOMUtils.getNextElement(child);
+        }
+    }
+    
+    /**
+     * Create a RequestClaimCollection from a DOM Element
+     */
+    private RequestClaimCollection parseClaims(Element claimsElement) {
+        String dialectAttr = null;
+        RequestClaimCollection requestedClaims = new RequestClaimCollection();
+        try {
+            dialectAttr = claimsElement.getAttribute("Dialect");
+            if (dialectAttr != null && !"".equals(dialectAttr)) {
+                requestedClaims.setDialect(new URI(dialectAttr));
+            }
+        } catch (URISyntaxException e1) {
+            LOG.log(
+                Level.WARNING, 
+                "Cannot create URI from the given Dialect attribute value " + dialectAttr, 
+                e1
+            );
+        }
+        
+        Element childClaimType = DOMUtils.getFirstElement(claimsElement);
+        while (childClaimType != null) {
+            RequestClaim requestClaim = parseChildClaimType(childClaimType);
+            if (requestClaim != null) {
+                requestedClaims.add(requestClaim);
+            }
+            childClaimType = DOMUtils.getNextElement(childClaimType);
+        }
+        
+        return requestedClaims;
+    }
+    
+    /**
+     * Create a RequestClaimCollection from a JAXB ClaimsType object
+     */
+    private static RequestClaimCollection parseClaims(ClaimsType claimsType) {
+        String dialectAttr = null;
+        RequestClaimCollection requestedClaims = new RequestClaimCollection();
+        try {
+            dialectAttr = claimsType.getDialect();
+            if (dialectAttr != null && !"".equals(dialectAttr)) {
+                requestedClaims.setDialect(new URI(dialectAttr));
+            }
+        } catch (URISyntaxException e1) {
+            LOG.log(
+                Level.WARNING, 
+                "Cannot create URI from the given Dialect attribute value " + dialectAttr, 
+                e1
+            );
+        }
+        
+        for (Object claim : claimsType.getAny()) {
+            if (claim instanceof Element) {
+                RequestClaim requestClaim = parseChildClaimType((Element)claim);
+                if (requestClaim != null) {
+                    requestedClaims.add(requestClaim);
+                }
+            }
+        }
+        
+        return requestedClaims;
+    }
+    
+    /**
+     * Parse a child ClaimType into a RequestClaim object.
+     */
+    private static RequestClaim parseChildClaimType(Element childClaimType) {
+        String claimLocalName = childClaimType.getLocalName();
+        String claimNS = childClaimType.getNamespaceURI();
+        if ("ClaimType".equals(claimLocalName)) {
+            String claimTypeUri = childClaimType.getAttribute("Uri");
+            String claimTypeOptional = childClaimType.getAttribute("Optional");
+            RequestClaim requestClaim = new RequestClaim();
+            try {
+                requestClaim.setClaimType(new URI(claimTypeUri));
+            } catch (URISyntaxException e) {
+                LOG.log(
+                    Level.WARNING, 
+                    "Cannot create URI from the given ClaimType attribute value " + claimTypeUri,
+                    e
+                );
+            }
+            requestClaim.setOptional(Boolean.parseBoolean(claimTypeOptional));
+            return requestClaim;
+        }
+        
+        LOG.fine("Found unknown element: " + claimLocalName + " " + claimNS);
+        return null;
+    }
+    
+    
+    /**
+     * Method to check if the passed token is a SecurityTokenReference
+     */
+    private static boolean isTokenReferenced(ReceivedToken token) {
+        Object targetToken = token.getToken();
+        if (targetToken instanceof Element) {
+            Element tokenElement = (Element)targetToken;
+            String namespace = tokenElement.getNamespaceURI();
+            String localname = tokenElement.getLocalName();
+            if (STSConstants.WSSE_EXT_04_01.equals(namespace)
+                && "SecurityTokenReference".equals(localname)) {
+                return true;
+            }
+        } else if (targetToken instanceof SecurityTokenReferenceType) {
+            return true;
+        }
+        return false;
+    } 
+    
+    /**
+     * Method to fetch token from the SecurityTokenReference
+     */
+    private static ReceivedToken fetchTokenFromReference(
+        ReceivedToken tokenReference, WebServiceContext wsContext
+    ) {
+        // Get the reference URI
+        String referenceURI = null;
+        Object targetToken = tokenReference.getToken();
+        if (targetToken instanceof Element) {
+            Element tokenElement = (Element) targetToken;
+            NodeList refList = 
+                tokenElement.getElementsByTagNameNS(STSConstants.WSSE_EXT_04_01, "Reference");
+            if (refList.getLength() == 0) {
+                throw new STSException(
+                    "Cannot find Reference element in the SecurityTokenReference.", 
+                    STSException.REQUEST_FAILED
+                );
+            }
+            referenceURI = refList.item(0).getNodeValue();
+        } else if (targetToken instanceof SecurityTokenReferenceType) {
+            Iterator<?> iterator = ((SecurityTokenReferenceType) targetToken).getAny().iterator();
+            while (iterator.hasNext()) {
+                JAXBElement<?> jaxbElement = (JAXBElement<?>) iterator.next();
+                if (jaxbElement.getValue() instanceof ReferenceType) {
+                    referenceURI = ((ReferenceType) jaxbElement.getValue()).getURI();
+                }
+            }
+        }
+        LOG.fine("Reference URI found " + referenceURI);
+   
+        // Find processed token corresponding to the URI
+        if (referenceURI.charAt(0) == '#') {
+            referenceURI = referenceURI.substring(1);
+        }
+        MessageContext messageContext = wsContext.getMessageContext();
+        final List<WSHandlerResult> handlerResults = 
+            CastUtils.cast((List<?>) messageContext.get(WSHandlerConstants.RECV_RESULTS));
+        
+        if (handlerResults != null && handlerResults.size() > 0) {
+            WSHandlerResult handlerResult = handlerResults.get(0);
+            List<WSSecurityEngineResult> engineResults = handlerResult.getResults();
+            
+            for (WSSecurityEngineResult engineResult : engineResults) {
+                Integer actInt = (Integer)engineResult.get(WSSecurityEngineResult.TAG_ACTION);
+                String id = (String)engineResult.get(WSSecurityEngineResult.TAG_ID);
+                if (referenceURI.equals(id)) {
+                    Element tokenElement = 
+                        (Element)engineResult.get(WSSecurityEngineResult.TAG_TOKEN_ELEMENT);
+                    if (tokenElement == null) {
+                        throw new STSException(
+                            "Cannot retrieve token from reference", STSException.INVALID_REQUEST
+                        );
+                    }
+                    return new ReceivedToken(tokenElement);
+                } else if (actInt == WSConstants.SCT) {
+                    // Need to check special case of SecurityContextToken Identifier separately
+                    SecurityContextToken sct = 
+                        (SecurityContextToken)
+                            engineResult.get(WSSecurityEngineResult.TAG_SECURITY_CONTEXT_TOKEN);
+                    if (referenceURI.equals(sct.getIdentifier())) {
+                        return new ReceivedToken(sct.getElement());
+                    }
+                }
+            }
+        }
+        throw new STSException("Cannot retreive token from reference", STSException.REQUEST_FAILED);
+    }
+
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/TokenRequirements.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/TokenRequirements.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/TokenRequirements.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/request/TokenRequirements.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,112 @@
+/**
+ * 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.request;
+
+import org.w3c.dom.Element;
+import org.apache.cxf.sts.claims.RequestClaimCollection;
+
+/**
+ * This class contains values that have been extracted from a RequestSecurityToken corresponding to 
+ * various token requirements.
+ */
+public class TokenRequirements {
+    
+    private String tokenType;
+    private Element appliesTo;
+    private String context;
+    private ReceivedToken validateTarget;
+    private ReceivedToken onBehalfOf;
+    private ReceivedToken actAs;
+    private ReceivedToken cancelTarget;
+    private Lifetime lifetime;
+    private RequestClaimCollection claims;
+    
+    public String getTokenType() {
+        return tokenType;
+    }
+    
+    public ReceivedToken getCancelTarget() {
+        return cancelTarget;
+    }
+
+    public void setCancelTarget(ReceivedToken cancelTarget) {
+        this.cancelTarget = cancelTarget;
+    }
+
+    public void setTokenType(String tokenType) {
+        this.tokenType = tokenType;
+    }
+    
+    public Element getAppliesTo() {
+        return appliesTo;
+    }
+    
+    public void setAppliesTo(Element appliesTo) {
+        this.appliesTo = appliesTo;
+    }
+    
+    public String getContext() {
+        return context;
+    }
+    
+    public void setContext(String context) {
+        this.context = context;
+    }
+    
+    public ReceivedToken getValidateTarget() {
+        return validateTarget;
+    }
+    
+    public void setValidateTarget(ReceivedToken validateTarget) {
+        this.validateTarget = validateTarget;
+    }
+    
+    public ReceivedToken getOnBehalfOf() {
+        return onBehalfOf;
+    }
+    
+    public void setOnBehalfOf(ReceivedToken onBehalfOf) {
+        this.onBehalfOf = onBehalfOf;
+    }
+    
+    public ReceivedToken getActAs() {
+        return actAs;
+    }
+    
+    public void setActAs(ReceivedToken actAs) {
+        this.actAs = actAs;
+    }
+    
+    public Lifetime getLifetime() {
+        return lifetime;
+    }
+    
+    public void setLifetime(Lifetime lifetime) {
+        this.lifetime = lifetime;
+    }
+    
+    public RequestClaimCollection getClaims() {
+        return claims;
+    }
+    
+    public void setClaims(RequestClaimCollection claims) {
+        this.claims = claims;
+    }
+
+}
\ No newline at end of file

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/EncryptionProperties.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/EncryptionProperties.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/EncryptionProperties.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/EncryptionProperties.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,143 @@
+/**
+ * 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.service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.ws.security.WSConstants;
+
+/**
+ * This class contains various configuration properties that can be used to encrypt an issued token.
+ * The encryptionName property must be specified (corresponding to the alias to be used to select a
+ * certificate from a KeyStore) - everything else is optional.
+ */
+public class EncryptionProperties {
+    private String encryptionAlgorithm = WSConstants.AES_256;
+    private String keyWrapAlgorithm = WSConstants.KEYTRANSPORT_RSA15;
+    private int keyIdentifierType = WSConstants.ISSUER_SERIAL;
+    private List<String> acceptedEncryptionAlgorithms = new ArrayList<String>();
+    private List<String> acceptedKeyWrapAlgorithms = new ArrayList<String>();
+    private String encryptionName;
+    
+    public EncryptionProperties() {
+        // Default symmetric encryption algorithms
+        acceptedEncryptionAlgorithms.add(WSConstants.TRIPLE_DES);
+        acceptedEncryptionAlgorithms.add(WSConstants.AES_128);
+        acceptedEncryptionAlgorithms.add(WSConstants.AES_192);
+        acceptedEncryptionAlgorithms.add(WSConstants.AES_256);
+        
+        // Default key wrap algorithms
+        acceptedKeyWrapAlgorithms.add(WSConstants.KEYTRANSPORT_RSA15);
+        acceptedKeyWrapAlgorithms.add(WSConstants.KEYTRANSPORT_RSAOEP);
+    }
+    
+    /**
+     * Get the encryption algorithm to use
+     */
+    public String getEncryptionAlgorithm() {
+        return encryptionAlgorithm;
+    }
+    
+    /**
+     * Set the encryption algorithm to use
+     */
+    public void setEncryptionAlgorithm(String encryptionAlgorithm) {
+        this.encryptionAlgorithm = encryptionAlgorithm;
+    }
+    
+    /**
+     * Get the encryption key-wrap algorithm to use
+     */
+    public String getKeyWrapAlgorithm() {
+        return keyWrapAlgorithm;
+    }
+    
+    /**
+     * Set the encryption key-wrap algorithm to use
+     */
+    public void setKeyWrapAlgorithm(String keyWrapAlgorithm) {
+        this.keyWrapAlgorithm = keyWrapAlgorithm;
+    }
+    
+    /**
+     * Get the (WSS4J) key identifier type used to reference a certificate for encryption
+     */
+    public int getKeyIdentifierType() {
+        return keyIdentifierType;
+    }
+    
+    /**
+     * Set the (WSS4J) key identifier type used to reference a certificate for encryption
+     */
+    public void setKeyIdentifierType(int keyIdentifierType) {
+        this.keyIdentifierType = keyIdentifierType;
+    }
+    
+    /**
+     * Get the alias used to select a certificate for encryption
+     */
+    public String getEncryptionName() {
+        return encryptionName;
+    }
+    
+    /**
+     * Set the alias used to select a certificate for encryption
+     */
+    public void setEncryptionName(String encryptionName) {
+        this.encryptionName = encryptionName;
+    }
+    
+    /**
+     * Set the list of accepted encryption algorithms. A request can contain a wst:EncryptionAlgorithm
+     * uri to use to encrypt an issued token. The algorithm specified must be contained in this list.
+     * The default algorithms are 3-DES, AES-128, AES-192 and AES-256.
+     */
+    public void setAcceptedEncryptionAlgorithms(List<String> acceptedEncryptionAlgorithms) {
+        this.acceptedEncryptionAlgorithms = acceptedEncryptionAlgorithms;
+    }
+    
+    /**
+     * Get the list of accepted encryption algorithms. A request can contain a wst:EncryptionAlgorithm
+     * uri to use to encrypt an issued token. The algorithm specified must be contained in this list.
+     * The default algorithms are 3-DES, AES-128, AES-192 and AES-256.
+     */
+    public List<String> getAcceptedEncryptionAlgorithms() {
+        return acceptedEncryptionAlgorithms;
+    }
+
+    /**
+     * Set the list of accepted key-wrap algorithms. A request can contain a wst:KeyWrapAlgorithm
+     * uri for use in encrypting an issued token. The algorithm specified must be contained in this list.
+     * The default algorithms are RSA 1.5 and RSA OEP.
+     */
+    public void setAcceptedKeyWrapAlgorithms(List<String> acceptedKeyWrapAlgorithms) {
+        this.acceptedKeyWrapAlgorithms = acceptedKeyWrapAlgorithms;
+    }
+    
+    /**
+     * Get the list of accepted key-wrap algorithms. A request can contain a wst:KeyWrapAlgorithm
+     * uri for use in encrypting an issued token. The algorithm specified must be contained in this list.
+     * The default algorithms are RSA 1.5 and RSA OEP.
+     */
+    public List<String> getAcceptedKeyWrapAlgorithms() {
+        return acceptedKeyWrapAlgorithms;
+    }
+    
+}
\ No newline at end of file

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/ServiceMBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/ServiceMBean.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/ServiceMBean.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/ServiceMBean.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,72 @@
+/**
+ * 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.service;
+
+import java.util.List;
+
+/**
+ * This MBean represents a service. It defines a single operation
+ * "isAddressInEndpoints(String address)". This is called by the Issue binding, passing
+ * through the address URL that is supplied as part of "AppliesTo". The AppliesTo address
+ * must match with a "known" address of the implementation of this MBean.
+ */
+public interface ServiceMBean {
+    
+    /**
+     * Return true if the supplied address corresponds to a known address for this service
+     */
+    boolean isAddressInEndpoints(String address);
+    
+    /**
+     * Get the default Token Type to be issued for this Service
+     */
+    String getTokenType();
+    
+    /**
+     * Set the default Token Type to be issued for this Service
+     */
+    void setTokenType(String tokenType);
+    
+    /**
+     * Get the default Key Type to be issued for this Service
+     */
+    String getKeyType();
+    
+    /**
+     * Set the default Key Type to be issued for this Service
+     */
+    void setKeyType(String keyType);
+    
+    /**
+     * Set the list of endpoint addresses that correspond to this service
+     */
+    void setEndpoints(List<String> endpoints);
+    
+    /**
+     * Get the EncryptionProperties to be used to encrypt tokens issued for this service
+     */
+    EncryptionProperties getEncryptionProperties();
+    
+    /**
+     * Set the EncryptionProperties to be used to encrypt tokens issued for this service
+     */
+    void setEncryptionProperties(EncryptionProperties encryptionProperties);
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/StaticService.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/StaticService.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/StaticService.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/service/StaticService.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,130 @@
+/**
+ * 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.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.apache.cxf.common.logging.LogUtils;
+
+/**
+ * This class represents a (static) service. It can be spring-loaded with a set of Endpoint
+ * Strings, which are compiled into a collection of (reg-ex) Patterns.
+ */
+public class StaticService implements ServiceMBean {
+    private static final Logger LOG = LogUtils.getL7dLogger(StaticService.class);
+    
+    private String tokenType;
+    private String keyType;
+    private EncryptionProperties encryptionProperties;
+    
+    /**
+     * a collection of compiled regular expression patterns
+     */
+    private final Collection<Pattern> endpointPatterns = new ArrayList<Pattern>();
+    
+    /**
+     * Return true if the supplied address corresponds to a known address for this service
+     */
+    public boolean isAddressInEndpoints(String address) {
+        String addressToMatch = address;
+        if (addressToMatch == null) {
+            addressToMatch = "";
+        }
+        for (Pattern endpointPattern : endpointPatterns) {
+            final Matcher matcher = endpointPattern.matcher(addressToMatch);
+            if (matcher.matches()) {
+                LOG.fine("Address " + address + " matches with pattern " + endpointPattern);
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Get the default Token Type to be issued for this Service
+     */
+    public String getTokenType() {
+        return tokenType;
+    }
+    
+    /**
+     * Set the default Token Type to be issued for this Service
+     */
+    public void setTokenType(String tokenType) {
+        this.tokenType = tokenType;
+        LOG.fine("Setting Token Type: " + tokenType);
+    }
+    
+    /**
+     * Get the default Key Type to be issued for this Service
+     */
+    public String getKeyType() {
+        return keyType;
+    }
+    
+    /**
+     * Set the default Key Type to be issued for this Service
+     */
+    public void setKeyType(String keyType) {
+        this.keyType = keyType;
+        LOG.fine("Setting Key Type: " + keyType);
+    }
+    
+    /**
+     * Set the list of endpoint addresses that correspond to this service
+     */
+    public void setEndpoints(List<String> endpoints) {
+        if (endpoints != null) {
+            for (String endpoint : endpoints) {
+                try {
+                    endpointPatterns.add(Pattern.compile(endpoint.trim()));
+                } catch (PatternSyntaxException ex) {
+                    LOG.severe(ex.getMessage());
+                    throw ex;
+                }
+            }
+        }
+    }
+    
+    /**
+     * Get the EncryptionProperties to be used to encrypt tokens issued for this service
+     */
+    public EncryptionProperties getEncryptionProperties() {
+        if (encryptionProperties == null) {
+            return new EncryptionProperties();
+        }
+        return encryptionProperties;
+    }
+    
+    /**
+     * Set the EncryptionProperties to be used to encrypt tokens issued for this service
+     */
+    public void setEncryptionProperties(EncryptionProperties encryptionProperties) {
+        this.encryptionProperties = encryptionProperties;
+        LOG.fine("Setting encryption properties");
+    }
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/SCTCanceller.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/SCTCanceller.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/SCTCanceller.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/SCTCanceller.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.sts.token.canceller;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.ws.security.trust.STSUtils;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.message.token.SecurityContextToken;
+
+/**
+ * This class cancels a SecurityContextToken.
+ */
+public class SCTCanceller implements TokenCanceller {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(SCTCanceller.class);
+    
+    /**
+     * Return true if this TokenValidator implementation is capable of validating the
+     * ReceivedToken argument.
+     */
+    public boolean canHandleToken(ReceivedToken targetToken) {
+        Object token = targetToken.getToken();
+        if (token instanceof Element) {
+            Element tokenElement = (Element)token;
+            String namespace = tokenElement.getNamespaceURI();
+            String localname = tokenElement.getLocalName();
+            if ((STSUtils.SCT_NS_05_02.equals(namespace) 
+                || STSUtils.SCT_NS_05_12.equals(namespace))
+                && "SecurityContextToken".equals(localname)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Cancel a Token using the given TokenCancellerParameters.
+     */
+    public TokenCancellerResponse cancelToken(TokenCancellerParameters tokenParameters) {
+        LOG.fine("Trying to cancel a SecurityContextToken");
+        TokenRequirements tokenRequirements = tokenParameters.getTokenRequirements();
+        ReceivedToken cancelTarget = tokenRequirements.getCancelTarget();
+
+        TokenCancellerResponse response = new TokenCancellerResponse();
+        response.setTokenCancelled(false);
+        
+        if (tokenParameters.getCache() == null) {
+            LOG.log(Level.FINE, "A cache must be configured to use the SCTCanceller");
+            return response;
+        }
+        
+        if (cancelTarget != null && cancelTarget.isDOMElement()) {
+            try {
+                Element cancelTargetElement = (Element)cancelTarget.getToken();
+                SecurityContextToken sct = new SecurityContextToken(cancelTargetElement);
+                String identifier = sct.getIdentifier();
+                byte[] secret = (byte[])tokenParameters.getCache().get(identifier);
+                if (secret == null) {
+                    LOG.fine("Identifier: " + identifier + " is not found in the cache");
+                    return response;
+                }
+                tokenParameters.getCache().remove(identifier);
+                response.setTokenCancelled(true);
+            } catch (WSSecurityException ex) {
+                LOG.log(Level.WARNING, "", ex);
+            }
+        }
+        return response;
+    }
+
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCanceller.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCanceller.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCanceller.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCanceller.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.sts.token.canceller;
+
+import org.apache.cxf.sts.request.ReceivedToken;
+
+
+/**
+ * An interface that can cancel a security token.
+ */
+
+public interface TokenCanceller {
+
+    /**
+     * Return true if this TokenCanceller implementation is able to cancel a token
+     * that corresponds to the given token.
+     */
+    boolean canHandleToken(ReceivedToken cancelTarget);
+
+    /**
+     * Cancel a token given a TokenCancellerParameters
+     */
+    TokenCancellerResponse cancelToken(TokenCancellerParameters tokenParameters);
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerParameters.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerParameters.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerParameters.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerParameters.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.sts.token.canceller;
+
+import java.security.Principal;
+
+import javax.xml.ws.WebServiceContext;
+
+import org.apache.cxf.sts.STSPropertiesMBean;
+import org.apache.cxf.sts.cache.STSCache;
+import org.apache.cxf.sts.request.KeyRequirements;
+import org.apache.cxf.sts.request.TokenRequirements;
+
+/**
+ * This class encapsulates the parameters that will be passed to a TokenCanceller instance to
+ * cancel a token. It consists of both parameters that have been extracted from the request,
+ * as well as configuration specific to the Operation itself (STSPropertiesMBean etc.)
+ */
+public class TokenCancellerParameters {
+
+    private STSPropertiesMBean stsProperties;
+    private Principal principal;
+    private WebServiceContext webServiceContext;
+    private KeyRequirements keyRequirements;
+    private TokenRequirements tokenRequirements;
+    private STSCache cache;
+    
+    public STSCache getCache() {
+        return cache;
+    }
+
+    public void setCache(STSCache cache) {
+        this.cache = cache;
+    }
+    
+    public TokenRequirements getTokenRequirements() {
+        return tokenRequirements;
+    }
+
+    public void setTokenRequirements(TokenRequirements tokenRequirements) {
+        this.tokenRequirements = tokenRequirements;
+    }
+
+    public KeyRequirements getKeyRequirements() {
+        return keyRequirements;
+    }
+
+    public void setKeyRequirements(KeyRequirements keyRequirements) {
+        this.keyRequirements = keyRequirements;
+    }
+    
+    public STSPropertiesMBean getStsProperties() {
+        return stsProperties;
+    }
+
+    public void setStsProperties(STSPropertiesMBean stsProperties) {
+        this.stsProperties = stsProperties;
+    }
+    
+    public WebServiceContext getWebServiceContext() {
+        return webServiceContext;
+    }
+
+    public void setWebServiceContext(WebServiceContext webServiceContext) {
+        this.webServiceContext = webServiceContext;
+    }
+    
+    public void setPrincipal(Principal principal) {
+        this.principal = principal;
+    }
+    
+    public Principal getPrincipal() {
+        return principal;
+    }
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerResponse.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerResponse.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerResponse.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/canceller/TokenCancellerResponse.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.canceller;
+
+
+/**
+ * This class encapsulates the response from a TokenValidator instance after validating a token.
+ */
+public class TokenCancellerResponse {
+
+    private boolean tokenCancelled;
+    
+    public void setTokenCancelled(boolean tokenCancelled) {
+        this.tokenCancelled = tokenCancelled;
+    }
+    
+    public boolean isTokenCancelled() {
+        return tokenCancelled;
+    }
+    
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AttributeStatementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AttributeStatementProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AttributeStatementProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AttributeStatementProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import org.apache.ws.security.saml.ext.bean.AttributeStatementBean;
+
+/**
+ * An interface that allows a pluggable way of obtaining an AttributeStatementBean.
+ */
+public interface AttributeStatementProvider {
+
+    /**
+     * Get an AttributeStatementBean using the given parameters.
+     */
+    AttributeStatementBean getStatement(TokenProviderParameters providerParameters);
+        
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthDecisionStatementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthDecisionStatementProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthDecisionStatementProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthDecisionStatementProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import org.apache.ws.security.saml.ext.bean.AuthDecisionStatementBean;
+
+/**
+ * An interface that allows a pluggable way of obtaining an AuthDecisionStatementBean.
+ */
+public interface AuthDecisionStatementProvider {
+
+    /**
+     * Get an AuthDecisionStatementBean using the given parameters.
+     */
+    AuthDecisionStatementBean getStatement(TokenProviderParameters providerParameters);
+        
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthenticationStatementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthenticationStatementProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthenticationStatementProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/AuthenticationStatementProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import org.apache.ws.security.saml.ext.bean.AuthenticationStatementBean;
+
+/**
+ * An interface that allows a pluggable way of obtaining an AuthenticationStatementBean.
+ */
+public interface AuthenticationStatementProvider {
+
+    /**
+     * Get an AuthenticationStatementBean using the given parameters.
+     */
+    AuthenticationStatementBean getStatement(TokenProviderParameters providerParameters);
+        
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/ConditionsProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/ConditionsProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/ConditionsProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/ConditionsProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import org.apache.ws.security.saml.ext.bean.ConditionsBean;
+
+/**
+ * An interface that allows a pluggable way of obtaining a SAML ConditionsBean used to populate the
+ * Conditions of a SAML Assertion.
+ */
+public interface ConditionsProvider {
+
+    /**
+     * Get a ConditionsBean object.
+     */
+    ConditionsBean getConditions(TokenProviderParameters providerParameters);
+    
+    /**
+     * Get the lifetime to use (in seconds)
+     */
+    long getLifetime();
+    
+        
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultAttributeStatementProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultAttributeStatementProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultAttributeStatementProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultAttributeStatementProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,135 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.w3c.dom.Element;
+
+import org.apache.cxf.sts.request.ReceivedToken;
+import org.apache.cxf.sts.request.TokenRequirements;
+import org.apache.cxf.ws.security.sts.provider.STSException;
+import org.apache.cxf.ws.security.sts.provider.model.secext.UsernameTokenType;
+import org.apache.ws.security.SAMLTokenPrincipal;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.saml.ext.AssertionWrapper;
+import org.apache.ws.security.saml.ext.bean.AttributeBean;
+import org.apache.ws.security.saml.ext.bean.AttributeStatementBean;
+
+/**
+ * A default AttributeStatementProvider implementation. It creates a default attribute with
+ * value "authenticated". It also shows how to handle OnBehalfOf or ActAs elements by adding an
+ * Attribute for them.
+ */
+public class DefaultAttributeStatementProvider implements AttributeStatementProvider {
+
+    /**
+     * Get an AttributeStatementBean using the given parameters.
+     */
+    public AttributeStatementBean getStatement(TokenProviderParameters providerParameters) {
+        AttributeStatementBean attrBean = new AttributeStatementBean();
+        List<AttributeBean> attributeList = new ArrayList<AttributeBean>();
+
+        TokenRequirements tokenRequirements = providerParameters.getTokenRequirements();
+        String tokenType = tokenRequirements.getTokenType();
+        AttributeBean attributeBean = createDefaultAttribute(tokenType);
+        attributeList.add(attributeBean);
+        
+        ReceivedToken onBehalfOf = tokenRequirements.getOnBehalfOf();
+        ReceivedToken actAs = tokenRequirements.getActAs();
+        try {
+            if (onBehalfOf != null) {
+                AttributeBean parameterBean = 
+                    handleAdditionalParameters(false, onBehalfOf.getToken(), tokenType);
+                if (!parameterBean.getAttributeValues().isEmpty()) {
+                    attributeList.add(parameterBean);
+                }
+            }
+            if (actAs != null) {
+                AttributeBean parameterBean = 
+                    handleAdditionalParameters(true, actAs.getToken(), tokenType);
+                if (!parameterBean.getAttributeValues().isEmpty()) {
+                    attributeList.add(parameterBean);
+                }
+            }
+        } catch (WSSecurityException ex) {
+            throw new STSException(ex.getMessage(), ex);
+        }
+        
+        attrBean.setSamlAttributes(attributeList);
+        
+        return attrBean;
+    }
+    
+    /**
+     * Create a default attribute
+     */
+    private AttributeBean createDefaultAttribute(String tokenType) {
+        AttributeBean attributeBean = new AttributeBean();
+
+        if (WSConstants.WSS_SAML2_TOKEN_TYPE.equals(tokenType)
+            || WSConstants.SAML2_NS.equals(tokenType)) {
+            attributeBean.setQualifiedName("token-requestor");
+            attributeBean.setNameFormat("http://cxf.apache.org/sts");
+        } else {
+            attributeBean.setSimpleName("token-requestor");
+            attributeBean.setQualifiedName("http://cxf.apache.org/sts");
+        }
+        
+        attributeBean.setAttributeValues(Collections.singletonList("authenticated"));
+        
+        return attributeBean;
+    }
+
+    /**
+     * Handle ActAs or OnBehalfOf elements.
+     */
+    private AttributeBean handleAdditionalParameters(
+        boolean actAs, 
+        Object parameter, 
+        String tokenType
+    ) throws WSSecurityException {
+        AttributeBean parameterBean = new AttributeBean();
+
+        String claimType = actAs ? "ActAs" : "OnBehalfOf";
+        if (WSConstants.WSS_SAML2_TOKEN_TYPE.equals(tokenType) || WSConstants.SAML2_NS.equals(tokenType)) {
+            parameterBean.setQualifiedName(claimType);
+            parameterBean.setNameFormat("http://cxf.apache.org/sts");
+        } else {
+            parameterBean.setSimpleName(claimType);
+            parameterBean.setQualifiedName("http://cxf.apache.org/sts");
+        }
+        if (parameter instanceof UsernameTokenType) {
+            parameterBean.setAttributeValues(
+                Collections.singletonList(((UsernameTokenType)parameter).getUsername().getValue())
+            );
+        } else if (parameter instanceof Element) {
+            AssertionWrapper wrapper = new AssertionWrapper((Element)parameter);
+            SAMLTokenPrincipal principal = new SAMLTokenPrincipal(wrapper);
+            parameterBean.setAttributeValues(Collections.singletonList(principal.getName()));
+        }
+
+        return parameterBean;
+    }
+
+
+}

Added: cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultConditionsProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultConditionsProvider.java?rev=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultConditionsProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultConditionsProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import org.apache.ws.security.saml.ext.bean.ConditionsBean;
+
+/**
+ * A default implementation of the ConditionsProvider interface.
+ */
+public class DefaultConditionsProvider implements ConditionsProvider {
+    
+    private long lifetime = 300L;
+    
+    public void setLifetime(long lifetime) {
+        this.lifetime = lifetime;
+    }
+    
+    public long getLifetime() {
+        return lifetime;
+    }
+
+    /**
+     * Get a ConditionsBean object.
+     */
+    public ConditionsBean getConditions(TokenProviderParameters providerParameters) {
+        ConditionsBean conditions = new ConditionsBean();
+        if (lifetime > 0) {
+            conditions.setTokenPeriodMinutes((int)(lifetime / 60L));
+        } else {
+            conditions.setTokenPeriodMinutes(5);
+        }
+        conditions.setAudienceURI(providerParameters.getAppliesToAddress());
+        
+        return conditions;
+    }
+        
+}

Added: 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=1173182&view=auto
==============================================================================
--- cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java (added)
+++ cxf/trunk/services/sts/sts-core/src/main/java/org/apache/cxf/sts/token/provider/DefaultSubjectProvider.java Tue Sep 20 15:12:07 2011
@@ -0,0 +1,186 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.sts.token.provider;
+
+import java.security.Principal;
+import java.security.cert.X509Certificate;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.cxf.common.logging.LogUtils;
+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.TokenRequirements;
+import org.apache.cxf.sts.service.EncryptionProperties;
+import org.apache.cxf.ws.security.sts.provider.STSException;
+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.bean.KeyInfoBean;
+import org.apache.ws.security.saml.ext.bean.KeyInfoBean.CERT_IDENTIFIER;
+import org.apache.ws.security.saml.ext.bean.SubjectBean;
+import org.apache.ws.security.saml.ext.builder.SAML1Constants;
+import org.apache.ws.security.saml.ext.builder.SAML2Constants;
+
+/**
+ * A default implementation of SubjectProvider to create a SAML Assertion. The Subject name is the name
+ * of the current principal, the subject name qualifier is a default URL that can be configured, and the
+ * subject confirmation method is created according to the token type and key type. If the Subject
+ * Confirmation Method is SymmetricKey or PublicKey, the appropriate KeyInfoBean object is created and
+ * attached to the Subject.
+ */
+public class DefaultSubjectProvider implements SubjectProvider {
+    
+    private static final Logger LOG = LogUtils.getL7dLogger(DefaultSubjectProvider.class);
+    private String subjectNameQualifier = "http://cxf.apache.org/sts";
+    
+    /**
+     * Set the SubjectNameQualifier.
+     */
+    public void setSubjectNameQualifier(String subjectNameQualifier) {
+        this.subjectNameQualifier = subjectNameQualifier;
+        LOG.fine("Setting Subject Name Qualifier: " + subjectNameQualifier);
+    }
+
+    /**
+     * Get a SubjectBean object.
+     */
+    public SubjectBean getSubject(
+        TokenProviderParameters providerParameters, Document doc, byte[] secret
+    ) {
+        TokenRequirements tokenRequirements = providerParameters.getTokenRequirements();
+        KeyRequirements keyRequirements = providerParameters.getKeyRequirements();
+        STSPropertiesMBean stsProperties = providerParameters.getStsProperties();
+
+        String tokenType = tokenRequirements.getTokenType();
+        String keyType = keyRequirements.getKeyType();
+        String confirmationMethod = getSubjectConfirmationMethod(tokenType, keyType);
+        
+        Principal principal = providerParameters.getPrincipal();
+        SubjectBean subjectBean = 
+            new SubjectBean(principal.getName(), subjectNameQualifier, confirmationMethod);
+        LOG.fine("Creating new subject with principal name: " + principal.getName());
+
+        if (STSConstants.SYMMETRIC_KEY_KEYTYPE.equals(keyType)) {
+            Crypto crypto = stsProperties.getEncryptionCrypto();
+            CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+            EncryptionProperties encryptionProperties = providerParameters.getEncryptionProperties();
+            String encryptionName = encryptionProperties.getEncryptionName();
+            if (encryptionName == null) {
+                // Fall back on the STS encryption name
+                encryptionName = stsProperties.getEncryptionUsername();
+            }
+            if (encryptionName == null) {
+                LOG.fine("No encryption Name is configured for Symmetric KeyType");
+                throw new STSException("No Encryption Name is configured", STSException.REQUEST_FAILED);
+            }
+            cryptoType.setAlias(encryptionName);
+            try {
+                X509Certificate certificate = crypto.getX509Certificates(cryptoType)[0];
+                KeyInfoBean keyInfo = 
+                    createKeyInfo(certificate, secret, doc, encryptionProperties, crypto);
+                subjectBean.setKeyInfo(keyInfo);
+            } catch (WSSecurityException ex) {
+                LOG.log(Level.WARNING, "", ex);
+                throw new STSException(ex.getMessage(), ex);
+            }
+        } else if (STSConstants.PUBLIC_KEY_KEYTYPE.equals(keyType)) {
+            KeyInfoBean keyInfo = createKeyInfo(keyRequirements.getCertificate());
+            subjectBean.setKeyInfo(keyInfo);
+        }
+        
+        return subjectBean;
+    }
+        
+    /**
+     * Get the SubjectConfirmation method given a tokenType and keyType
+     */
+    private String getSubjectConfirmationMethod(String tokenType, String keyType) {
+        if (WSConstants.WSS_SAML2_TOKEN_TYPE.equals(tokenType)
+            || WSConstants.SAML2_NS.equals(tokenType)) {
+            if (STSConstants.SYMMETRIC_KEY_KEYTYPE.equals(keyType) 
+                || STSConstants.PUBLIC_KEY_KEYTYPE.equals(keyType)) {
+                return SAML2Constants.CONF_HOLDER_KEY;
+            } else {
+                return SAML2Constants.CONF_BEARER;
+            }
+        } else {
+            if (STSConstants.SYMMETRIC_KEY_KEYTYPE.equals(keyType) 
+                || STSConstants.PUBLIC_KEY_KEYTYPE.equals(keyType)) {
+                return SAML1Constants.CONF_HOLDER_KEY;
+            } else {
+                return SAML1Constants.CONF_BEARER;
+            }
+        }
+    }
+
+    /**
+     * Create a KeyInfoBean that contains an X.509 certificate.
+     */
+    private static KeyInfoBean createKeyInfo(X509Certificate certificate) {
+        KeyInfoBean keyInfo = new KeyInfoBean();
+
+        keyInfo.setCertificate(certificate);
+        keyInfo.setCertIdentifer(CERT_IDENTIFIER.X509_CERT);
+
+        return keyInfo;
+    }
+
+    /**
+     * Create an EncryptedKey KeyInfo.
+     */
+    private static KeyInfoBean createKeyInfo(
+        X509Certificate certificate, 
+        byte[] secret,
+        Document doc,
+        EncryptionProperties encryptionProperties,
+        Crypto encryptionCrypto
+    ) throws WSSecurityException {
+        KeyInfoBean keyInfo = new KeyInfoBean();
+
+        // Create an EncryptedKey
+        WSSecEncryptedKey encrKey = new WSSecEncryptedKey();
+        encrKey.setKeyIdentifierType(encryptionProperties.getKeyIdentifierType());
+        encrKey.setEphemeralKey(secret);
+        encrKey.setUseThisCert(certificate);
+        encrKey.prepare(doc, encryptionCrypto);
+        Element encryptedKeyElement = encrKey.getEncryptedKeyElement();
+
+        // Append the EncryptedKey to a KeyInfo element
+        Element keyInfoElement = 
+            doc.createElementNS(
+                WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.KEYINFO_LN
+            );
+        keyInfoElement.setAttributeNS(
+            WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
+        );
+        keyInfoElement.appendChild(encryptedKeyElement);
+
+        keyInfo.setElement(keyInfoElement);
+
+        return keyInfo;
+    }
+
+}



Mime
View raw message