Merge latest changes from trunk.
diff --git a/modules/rampart-core/pom.xml b/modules/rampart-core/pom.xml
index 295480e..e1158f5 100644
--- a/modules/rampart-core/pom.xml
+++ b/modules/rampart-core/pom.xml
@@ -85,5 +85,10 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java
index dda31b0..b445d52 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java
@@ -31,12 +31,22 @@
 import org.apache.rampart.saml.SAMLAssertionHandlerFactory;
 import org.apache.rampart.util.Axis2Util;
 import org.apache.rampart.util.RampartUtil;
+import org.apache.rampart.policy.model.KerberosConfig;
+import org.apache.rampart.policy.model.RampartConfig;
 import org.apache.ws.secpolicy.WSSPolicyException;
 import org.apache.ws.secpolicy.model.UsernameToken;
+import org.apache.ws.secpolicy.model.KerberosToken;
+import org.apache.ws.secpolicy.model.SupportingToken;
 import org.apache.ws.security.*;
 import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.validate.KerberosTokenDecoder;
+import org.apache.ws.security.validate.KerberosTokenValidator;
 
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.xml.namespace.QName;
+
+import java.io.IOException;
 import java.security.cert.X509Certificate;
 import java.util.*;
 
@@ -88,6 +98,89 @@
 		//Set rampart's configuration of WSS4J
 		engine.setWssConfig(rmd.getConfig());
 
+		RampartConfig rampartConfig = rpd.getRampartConfig();
+		if (rampartConfig != null) {
+			WSSConfig config = engine.getWssConfig();
+
+            // Inbound Kerberos authentication for web services
+            // Check the service policy for Kerberos token and add KerberosTokenValidator for BINARY_TOKEN validation
+            SupportingToken endSupptokens = rpd.getEndorsingSupportingTokens();
+            if (endSupptokens != null && endSupptokens.getTokens() != null &&
+                endSupptokens.getTokens().size() > 0) {
+                
+            	log.debug("Processing endorsing supporting tokens");
+                List tokens = endSupptokens.getTokens();
+                
+                for (Object objectToken : tokens) {                    
+                    if (objectToken instanceof KerberosToken) {
+                        log.debug("KerberosToken is found as part of the endorsing supporting tokens.Check for KerberosConfig.");
+                        KerberosConfig kerberosConfig = rampartConfig.getKerberosConfig();
+                        
+                        if (null != kerberosConfig){
+                            log.debug("KerberosConfig is found.");
+                            log.debug("Creating KerberosTokenValidor with the available KerberosConfig.");
+                            KerberosTokenValidator kerberosValidator = new KerberosTokenValidator();
+                            
+                            KerberosTokenDecoder kerberosTokenDecoder = RampartUtil.getKerberosTokenDecoder(msgCtx, kerberosConfig);
+                            if (kerberosTokenDecoder != null) {
+                                kerberosValidator.setKerberosTokenDecoder(kerberosTokenDecoder);
+                            }
+                            kerberosValidator.setContextName(kerberosConfig.getJaasContext());
+                            kerberosValidator.setServiceName(kerberosConfig.getServicePrincipalName());
+                            String serviceNameForm = kerberosConfig.getServicePrincipalNameForm();
+                            
+                            if (KerberosConfig.USERNAME_NAME_FORM.equals(serviceNameForm)) {
+                                kerberosValidator.setUsernameServiceNameForm(true);    
+                            }
+                            
+                            String principalName = kerberosConfig.getPrincipalName();
+                            if (null == principalName){
+                                log.debug("Principal name is not available in the KerberosConfig.Using the Rampart configuration's user.");
+                                principalName = rampartConfig.getUser();
+                            }
+                            
+                            String password = kerberosConfig.getPrincipalPassword();
+                            if (password == null) {
+                                log.debug("Principal password is not available in the KerberosConfig.Trying with the configured Rampart password callback.");
+                                CallbackHandler handler = RampartUtil.getPasswordCB(rmd);
+
+                                if (handler != null) {
+                                    WSPasswordCallback[] cb = { 
+                                    		new WSPasswordCallback(principalName, WSPasswordCallback.CUSTOM_TOKEN) 
+                                    };
+                                    
+                                    try {
+                                        handler.handle(cb);
+                                        if (cb[0].getPassword() != null && !"".equals(cb[0].getPassword())) {
+                                            password = cb[0].getPassword();
+                                        }
+                                    } catch (IOException e) {
+                                        throw new RampartException("errorInGettingPasswordForUser", new String[] { principalName }, e);
+                                    } catch (UnsupportedCallbackException e) {
+                                        throw new RampartException("errorInGettingPasswordForUser", new String[] { principalName }, e);
+                                    }
+                                } else{
+                                    log.debug("No Rampart password handler is configured.");
+                                }
+                            }
+                            
+                            if (principalName != null && password != null) {
+                                NamePasswordCallbackHandler cb = new NamePasswordCallbackHandler(principalName, password);                            
+                                kerberosValidator.setCallbackHandler(cb);
+                            }
+                            
+                            config.setValidator(WSSecurityEngine.BINARY_TOKEN, kerberosValidator);
+                            log.debug("KerberosTokenValidator is configured and set for BINARY_TOKEN.");
+                        } else {
+                            log.debug("KerberosConfig is not found.Skipping configurating and setting of a Kerberos validator.");
+                        }
+                    }
+                }
+            }            
+            
+            engine.setWssConfig(config);
+		}
+		
 		ValidatorData data = new ValidatorData(rmd);
 
 		SOAPHeader header = rmd.getMsgContext().getEnvelope().getHeader();
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/builder/BindingBuilder.java b/modules/rampart-core/src/main/java/org/apache/rampart/builder/BindingBuilder.java
index dd36d21..6dc753c 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/builder/BindingBuilder.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/builder/BindingBuilder.java
@@ -17,7 +17,10 @@
 package org.apache.rampart.builder;
 
 import org.apache.axiom.om.OMElement;
+import org.apache.axis2.addressing.AddressingConstants;
+import org.apache.axis2.addressing.AddressingHelper;
 import org.apache.axis2.client.Options;
+import org.apache.axis2.description.AxisEndpoint;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.rahas.EncryptedKeyToken;
@@ -28,6 +31,7 @@
 import org.apache.rampart.policy.RampartPolicyData;
 import org.apache.rampart.policy.SupportingPolicyData;
 import org.apache.rampart.policy.model.RampartConfig;
+import org.apache.rampart.policy.model.KerberosConfig;
 import org.apache.rampart.util.RampartUtil;
 import org.apache.ws.secpolicy.Constants;
 import org.apache.ws.secpolicy.SPConstants;
@@ -38,6 +42,7 @@
 import org.apache.ws.secpolicy.model.Token;
 import org.apache.ws.secpolicy.model.UsernameToken;
 import org.apache.ws.secpolicy.model.X509Token;
+import org.apache.ws.security.NamePasswordCallbackHandler;
 import org.apache.ws.security.WSConstants;
 import org.apache.ws.security.WSEncryptionPart;
 import org.apache.ws.security.WSPasswordCallback;
@@ -53,6 +58,7 @@
 import org.apache.ws.security.message.WSSecSignatureConfirmation;
 import org.apache.ws.security.message.WSSecTimestamp;
 import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.token.KerberosSecurity;
 import org.apache.ws.security.message.token.SecurityTokenReference;
 import org.apache.ws.security.util.WSSecurityUtil;
 import org.w3c.dom.Document;
@@ -846,5 +852,95 @@
         }
     }
 
-    
+    protected KerberosSecurity addKerberosToken(RampartMessageData rmd, Token token)
+            throws RampartException {
+        RampartPolicyData rpd = rmd.getPolicyData();
+        KerberosConfig krbConfig = rpd.getRampartConfig().getKerberosConfig();
+
+        if (krbConfig == null) {
+            throw new RampartException("noKerberosConfigDefined");
+        }
+
+        log.debug("Token inclusion: " + token.getInclusion());
+
+        String user = krbConfig.getPrincipalName();
+        if (user == null) {
+            user = rpd.getRampartConfig().getUser();
+        }
+        
+        String password = krbConfig.getPrincipalPassword();
+        if (password == null) {
+            CallbackHandler handler = RampartUtil.getPasswordCB(rmd);
+
+            if (handler != null) {
+                if (user == null) {
+                    log.debug("Password callback is configured but no user value is specified in the configuration");
+                    throw new RampartException("userMissing");
+                }
+                
+                //TODO We do not have a separate usage type for Kerberos token, let's use custom token
+                WSPasswordCallback[] cb = { new WSPasswordCallback(user, WSPasswordCallback.CUSTOM_TOKEN) };
+                try {
+                    handler.handle(cb);
+                    if (cb[0].getPassword() != null && !"".equals(cb[0].getPassword())) {
+                        password = cb[0].getPassword();
+                    }
+                } catch (IOException e) {
+                    throw new RampartException("errorInGettingPasswordForUser", new String[] { user }, e);
+                } catch (UnsupportedCallbackException e) {
+                    throw new RampartException("errorInGettingPasswordForUser", new String[] { user }, e);
+                }
+            }
+        }
+        
+        String principalName = null;
+        boolean isUsernameServiceNameForm = KerberosConfig.USERNAME_NAME_FORM.equals(krbConfig.getServicePrincipalNameForm());
+        
+        AxisEndpoint endpoint = rmd.getMsgContext().findEndpoint();
+        if (endpoint != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("Identified endpoint: " + endpoint.getName() + ". Looking for SPN identity claim.");
+            }
+            
+            OMElement addressingIdentity = AddressingHelper.getAddressingIdentityParameterValue(endpoint);
+            if (addressingIdentity != null) {
+                OMElement spnClaim = addressingIdentity.getFirstChildWithName(AddressingConstants.QNAME_IDENTITY_SPN);
+                if (spnClaim != null) {
+                    principalName = spnClaim.getText();
+                    isUsernameServiceNameForm = false;
+                    if (log.isDebugEnabled()) {
+                        log.debug("Found SPN identity claim: " + principalName);
+                    }
+                }
+                else {
+                    OMElement upnClaim = addressingIdentity.getFirstChildWithName(AddressingConstants.QNAME_IDENTITY_UPN);
+                    if (upnClaim != null) {
+                        principalName = upnClaim.getText();
+                        isUsernameServiceNameForm = true;
+                        if (log.isDebugEnabled()) {
+                            log.debug("Found UPN identity claim: " + principalName);
+                        }
+                    } else if (log.isDebugEnabled()) {
+                        log.debug(String.format("Neither SPN nor UPN identity claim found in %s EPR element for endpoint %s.", addressingIdentity.getQName().toString(), endpoint.getName()));
+                    }
+                }
+            }
+        }
+        
+        if (principalName == null) {
+        	principalName = krbConfig.getServicePrincipalName();
+        }
+        
+        try {
+            KerberosSecurity bst = new KerberosSecurity(rmd.getDocument());
+            
+            NamePasswordCallbackHandler cb = new NamePasswordCallbackHandler(user, password);
+            bst.retrieveServiceTicket(krbConfig.getJaasContext(), cb, principalName, isUsernameServiceNameForm,
+                krbConfig.isRequstCredentialDelegation(), krbConfig.getDelegationCredential());
+            
+            return bst;
+        } catch (WSSecurityException e) {
+            throw new RampartException("errorInBuildingKereberosToken", e);
+        }
+    }
 }
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/builder/TransportBindingBuilder.java b/modules/rampart-core/src/main/java/org/apache/rampart/builder/TransportBindingBuilder.java
index 2bee572..de05429 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/builder/TransportBindingBuilder.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/builder/TransportBindingBuilder.java
@@ -32,6 +32,7 @@
 import org.apache.ws.secpolicy.model.AlgorithmSuite;
 import org.apache.ws.secpolicy.model.Header;
 import org.apache.ws.secpolicy.model.IssuedToken;
+import org.apache.ws.secpolicy.model.KerberosToken;
 import org.apache.ws.secpolicy.model.SecureConversationToken;
 import org.apache.ws.secpolicy.model.SignedEncryptedParts;
 import org.apache.ws.secpolicy.model.SupportingToken;
@@ -44,10 +45,16 @@
 import org.apache.ws.security.conversation.ConversationException;
 import org.apache.ws.security.handler.WSHandlerConstants;
 import org.apache.ws.security.message.*;
+import org.apache.ws.security.message.token.KerberosSecurity;
+import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.util.WSSecurityUtil;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import javax.crypto.SecretKey;
 import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.SignatureMethod;
+
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -138,6 +145,8 @@
                     } else if (token instanceof SecureConversationToken) {
                         handleSecureConversationTokens(rmd, (SecureConversationToken) token);
                         signatureValues.add(doSecureConversationSignature(rmd, token, signdParts));
+                    } else if (token instanceof KerberosToken) {
+                        signatureValues.add(doKerberosTokenSignature(rmd, (KerberosToken)token, signdParts));
                     }
                 }
             }
@@ -292,6 +301,77 @@
         
     }
 
+    /**
+     * Generates a signature over the timestamp element (if any) using the Kerberos client/server session key.
+     * 
+     * @param rmd
+     * @param token
+     * @param signdParts 
+     */
+    private byte[] doKerberosTokenSignature(RampartMessageData rmd, KerberosToken token, SignedEncryptedParts signdParts) throws RampartException {
+        
+        Document doc = rmd.getDocument();
+        
+        List<WSEncryptionPart> sigParts = new ArrayList<WSEncryptionPart>();
+        
+        //TODO Shall we always include a timestamp?
+        if (this.timestampElement != null) {
+            sigParts.add(new WSEncryptionPart(rmd.getTimestampId()));
+        }
+        
+        if (signdParts != null) {
+            if (signdParts.isBody()) {
+                SOAPEnvelope env = rmd.getMsgContext().getEnvelope();
+                sigParts.add(new WSEncryptionPart(RampartUtil.addWsuIdToElement(env.getBody())));
+            }
+    
+            ArrayList headers = signdParts.getHeaders();
+            for (Iterator iterator = headers.iterator(); iterator.hasNext();) {
+                Header header = (Header) iterator.next();
+                WSEncryptionPart wep = new WSEncryptionPart(header.getName(), 
+                        header.getNamespace(),
+                        "Content");
+                sigParts.add(wep);
+            }
+        }
+
+        try {
+            KerberosSecurity kerberosBst = addKerberosToken(rmd, token);
+            kerberosBst.setID("Id-" + kerberosBst.hashCode());
+            
+            WSSecSignature sign = new WSSecSignature();
+            sign.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
+            
+            if (token.isRequiresKeyIdentifierReference()) {
+                sign.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
+               
+                byte[] digestBytes = WSSecurityUtil.generateDigest(kerberosBst.getToken());
+                sign.setCustomTokenId(Base64.encode(digestBytes));
+                sign.setCustomTokenValueType(WSConstants.WSS_KRB_KI_VALUE_TYPE);
+            } else {
+                sign.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
+                
+                sign.setCustomTokenId(kerberosBst.getID());
+                sign.setCustomTokenValueType(kerberosBst.getValueType());
+            }
+            
+            SecretKey secretKey = kerberosBst.getSecretKey();
+            sign.setSecretKey(secretKey.getEncoded());
+            
+            sign.prepare(doc, null, rmd.getSecHeader());
+            
+            WSSecurityUtil.prependChildElement(rmd.getSecHeader().getSecurityHeader(), kerberosBst.getElement());
+            
+            List<Reference> referenceList = sign.addReferencesToSign(sigParts, rmd.getSecHeader());
+
+            sign.computeSignature(referenceList, false, null);
+
+            return sign.getSignatureValue();
+        } catch (WSSecurityException e) {
+            throw new RampartException("errorInSignatureWithKerberosToken", e);
+        }
+    }
+    
     private void appendToHeader(WSSecHeader secHeader, Element appendingChild) {
 
         // TODO this is bit dubious, before migration code was like "dkSig.appendSigToHeader(rmd.getSecHeader())"
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/KerberosConfigBuilder.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/KerberosConfigBuilder.java
new file mode 100644
index 0000000..0c214b3
--- /dev/null
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/KerberosConfigBuilder.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2001-2014 The Apache Software Foundation.
+ * 
+ * Licensed 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.rampart.policy.builders;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.neethi.Assertion;
+import org.apache.neethi.AssertionBuilderFactory;
+import org.apache.neethi.builders.AssertionBuilder;
+import org.apache.rampart.policy.model.KerberosConfig;
+import org.apache.rampart.policy.model.RampartConfig;
+
+/**
+ * Builder for {@link KerberosConfig} assertion.
+ */
+public class KerberosConfigBuilder implements AssertionBuilder<OMElement> {
+
+    /* (non-Javadoc)
+     * @see org.apache.neethi.builders.AssertionBuilder#build(java.lang.Object, 
+     * org.apache.neethi.AssertionBuilderFactory)
+     */
+    public Assertion build(OMElement element, AssertionBuilderFactory factory) 
+        throws IllegalArgumentException {
+
+        KerberosConfig kerberosConfig = new KerberosConfig();
+
+        OMElement childElement;
+
+        childElement = element.getFirstChildWithName(
+              new QName(RampartConfig.NS, KerberosConfig.JAAS_CONTEXT_LN));
+        if (childElement != null) {
+            if (null == kerberosConfig.getJaasContext()) {
+                kerberosConfig.setJaasContext(childElement.getText().trim());
+            }
+        }
+
+        childElement = element.getFirstChildWithName(
+              new QName(RampartConfig.NS, KerberosConfig.PRINCIPAL_NAME_LN));
+        if (childElement != null) {
+            if (null == kerberosConfig.getPrincipalName()) {
+                kerberosConfig.setPrincipalName(childElement.getText().trim());
+            }
+        }
+
+        childElement = element.getFirstChildWithName(
+            new QName(RampartConfig.NS, KerberosConfig.PRINCIPAL_PASSWORD_LN));
+        if (childElement != null) {
+            if (null == kerberosConfig.getPrincipalPassword()) {
+                kerberosConfig.setPrincipalPassword(childElement.getText().trim());
+            }
+        }
+
+        childElement = element.getFirstChildWithName(new QName(RampartConfig.NS,
+            KerberosConfig.SERVICE_PRINCIPAL_NAME_LN));
+        if (childElement != null) {
+            kerberosConfig.setServicePrincipalName(childElement.getText().trim());
+        }
+
+        childElement = element.getFirstChildWithName(new QName(RampartConfig.NS,
+            KerberosConfig.SERVICE_PRINCIPAL_NAME_FORM_LN));
+        if (childElement != null) {
+            kerberosConfig.setServicePrincipalNameForm(
+                 childElement.getText().trim());
+        }
+        
+        childElement = element.getFirstChildWithName(new QName(RampartConfig.NS,
+            KerberosConfig.KERBEROS_TOKEN_DECODER_CLASS_LN));
+        if (childElement != null) {
+            kerberosConfig.setKerberosTokenDecoderClass(
+                 childElement.getText().trim());
+        }
+        
+        childElement = element.getFirstChildWithName(new QName(
+            RampartConfig.NS, KerberosConfig.REQUEST_CREDENTIAL_DELEGATION_LN));
+        if (childElement != null) {
+            kerberosConfig.setRequstCredentialDelegation(Boolean.valueOf(childElement.getText().trim()));
+        }    
+
+        return kerberosConfig;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.neethi.builders.AssertionBuilder#getKnownElements()
+     */
+    public QName[] getKnownElements() {
+        return new QName[] {
+            new QName(RampartConfig.NS, KerberosConfig.KERBEROS_LN) 
+        };
+    }
+}
+
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java
index d111fbd..edce4cd 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java
@@ -22,6 +22,7 @@
 import org.apache.neethi.AssertionBuilderFactory;
 import org.apache.neethi.builders.AssertionBuilder;
 import org.apache.rampart.policy.model.CryptoConfig;
+import org.apache.rampart.policy.model.KerberosConfig;
 import org.apache.rampart.policy.model.OptimizePartsConfig;
 import org.apache.rampart.policy.model.RampartConfig;
 import org.apache.rampart.policy.model.SSLConfig;
@@ -89,6 +90,16 @@
         }
         
         childElement = element.getFirstChildWithName(new QName(
+                RampartConfig.NS, RampartConfig.KERBEROS_CONFIG));
+        if (childElement != null) {                             
+            KerberosConfig kerberosConfig = (KerberosConfig)new KerberosConfigBuilder().
+                                      build(childElement, 
+                                      factory);
+            rampartConfig.setKerberosConfig(kerberosConfig);
+            
+        }
+        
+        childElement = element.getFirstChildWithName(new QName(
                 RampartConfig.NS, RampartConfig.SIG_CRYPTO_LN));
         if (childElement != null) {
             rampartConfig.setSigCryptoConfig((CryptoConfig) factory
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/KerberosConfig.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/KerberosConfig.java
new file mode 100644
index 0000000..73a5b96
--- /dev/null
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/KerberosConfig.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2001-2014 The Apache Software Foundation.
+ * 
+ * Licensed 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.rampart.policy.model;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.neethi.Assertion;
+import org.apache.neethi.Constants;
+import org.apache.neethi.PolicyComponent;
+import org.apache.rampart.RampartException;
+import org.ietf.jgss.GSSCredential;
+
+/**
+ * Container for Kerberos configuration options.
+ */
+public class KerberosConfig implements Assertion {
+
+    public final static String KERBEROS_LN = RampartConfig.KERBEROS_CONFIG;
+
+    public final static String JAAS_CONTEXT_LN = "jaasContext";
+
+    public final static String PRINCIPAL_NAME_LN = "principalName";
+
+    public final static String PRINCIPAL_PASSWORD_LN = "principalPassword";
+
+    public final static String SERVICE_PRINCIPAL_NAME_LN = "servicePrincipalName";
+
+    public final static String SERVICE_PRINCIPAL_NAME_FORM_LN = "servicePrincipalNameForm";
+
+    public final static String KERBEROS_TOKEN_DECODER_CLASS_LN = "kerberosTokenDecoderClass";
+    
+    public final static String REQUEST_CREDENTIAL_DELEGATION_LN  = "requestCredentialDelegation";
+    
+    public final static String DELEGATION_CREDENTIAL_LN = "delegationCredential";
+    /**
+     * Specifies that the service principal name should be interpreted as a 
+     * "host-based" name as specified in GSS API RFC, 
+     * section "4.1: Host-Based Service Name Form". 
+     * See <a href="http://www.ietf.org/rfc/rfc2743.txt">rfc2743 - GSS
+     * API, Version 2</a>.
+     */
+    public final static String HOST_BASED_NAME_FORM = "hostbased";
+
+    /**
+     * Specifies that the service principal name should be interpreted as a   
+     * "username" name as specified in GSS API RFC,
+     * section "4.2: User Name Form". 
+     * See <a href="http://www.ietf.org/rfc/rfc2743.txt">rfc2743 - GSS API, Version
+     * 2</a>.
+     */
+    public final static String USERNAME_NAME_FORM = "username";
+
+    private String jaasContext;
+
+    private String principalName;
+
+    private String principalPassword;
+
+    private String servicePrincipalName;
+
+    private String servicePrincipalNameForm;
+
+    private String kerberosTokenDecoderClass;
+    
+    private boolean requstCredentialDelegation;
+    
+    private GSSCredential delegationCredential;
+    
+    /**
+     * @return The JAAS context name to use to obtain a TGT (Ticket granting ticket).
+     */
+    public String getJaasContext() {
+        return jaasContext;
+    }
+    /**
+     * Sets the JAAS context name to use to obtain a TGT (Ticket granting ticket).
+     * @param jaasContext the jaasContext to set
+     */
+    public void setJaasContext(String jaasContext) {
+        this.jaasContext = jaasContext;
+    }
+
+    /**
+     * @return The principal name to use to obtain a TGT (Ticket granting ticket).
+     * This is usually the domain username.
+     * If not specified, Rampart will fall back to the Rampart configuration's 
+     * {@link RampartConfig#getUser() user}.
+     * Note that the principal name specified in JAAS configuration takes precedence
+     * over any principal name configured here.
+     */
+    public String getPrincipalName() {
+        return principalName;
+    }
+
+    /**
+     * Sets the principal name to use to obtain a TGT (Ticket granting ticket). 
+     * This is usually the domain username. If* not specified, Rampart will fall back 
+     * to the Rampart configuration's {@link RampartConfig#getUser() user}. 
+     * Note that the principal name specified in JAAS configuration takes precedence 
+     * over any principal name configured via this method.
+     * @param principalName the principalName to set
+     */
+    public void setPrincipalName(String principalName) {
+        this.principalName = principalName;
+    }
+
+    /**
+     * @return Returns the principal's clear-text password. If the password is not
+     * configured (null), Rampart will try to obtain it from any configured 
+     * {@link RampartConfig#getPwCbClass() password callback}. Note that any 
+     * principal password configured here will be ignored if the JAAS configuration 
+     * configures usage of a keytab file.
+     */
+    public String getPrincipalPassword() {
+        return principalPassword;
+    }
+
+    /**
+     * Sets the principal's clear-text password. If the password is not configured
+     * (null), Rampart will try to obtain it from any configured 
+     * {@link RampartConfig#getPwCbClass() password callback}. Note that any 
+     * principal password configured here will be ignored if the JAAS configuration 
+     * configures usage of a keytab file.
+     */
+    public void setPrincipalPassword(String principalPassword) {
+        this.principalPassword = principalPassword;
+    }
+
+    /**
+     * @return The service principal name to use to obtain a service ticket on the 
+     * client-side. Note that by default,
+     * this name is assumed to be in a {@link #HOST_BASED_NAME_FORM} unless the
+     * {@link #setServicePrincipalNameForm(String) service principal name form} is 
+     * explicitly configured.
+     */
+    public String getServicePrincipalName() {
+        return servicePrincipalName;
+    }
+
+    /**
+     * Sets service principal name to use to obtain a service ticket on the 
+     * client-side. Note that by default, this name is assumed to be in a 
+     * {@link #HOST_BASED_NAME_FORM} unless the 
+     * {@link #setServicePrincipalNameForm(String)
+     * service principal name form} is explicitly configured.
+     */
+    public void setServicePrincipalName(String servicePrincipalName) {
+        this.servicePrincipalName = servicePrincipalName;
+    }
+
+    /**
+     * Returns the service principal name form.
+     * @return Either {@value #HOST_BASED_NAME_FORM} or {@value #USERNAME_NAME_FORM}.   
+     * Default is: {@value #HOST_BASED_NAME_FORM}.
+     */
+    public String getServicePrincipalNameForm() {
+        if (servicePrincipalNameForm == null) {
+            return HOST_BASED_NAME_FORM;
+        }
+        return servicePrincipalNameForm;
+    }
+    
+    /**
+     * Configures a Kerberos token decoder implementation for decoding Kerberos v5 tokens on server side.
+     * The decoder will be used only if the Kerberos client/server session key cannot be obtained using Java's {@link com.sun.security.jgss.ExtendedGSSContext} API,
+     * which is normally the case when using Java version older than 1.7.0_b07, 
+     * see <a href="http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6710360"> JDK-6710360 : export Kerberos session key to applications</a>.
+     * <p>
+     * The class will be loaded using current service's {@link org.apache.axis2.description.AxisService#getClassLoader() classloader}.
+     * </p>
+     * 
+     * @param kerberosTokenValidatorClass A fully qualifier class name that implements {@link org.apache.ws.security.validate.KerberosTokenValidator}.
+     */
+    public void setKerberosTokenDecoderClass(String kerberosTokenDecoderClass) {
+        this.kerberosTokenDecoderClass = kerberosTokenDecoderClass;
+    }
+    
+    /**
+     * Returns the Kerberos token decoder implementation for decoding Kerberos v5 tokens on server side.
+     * The decoder will be used only if the Kerberos client/server session key cannot be obtained using Java's {@link com.sun.security.jgss.ExtendedGSSContext} API,
+     * which is normally the case when using Java version older than 1.7.0_b07, 
+     * see <a href="http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6710360"> JDK-6710360 : export Kerberos session key to applications</a>
+     * 
+     * @return A fully qualifier class name that implements {@link org.apache.ws.security.validate.KerberosTokenValidator} or <code>null</code> if no Kerberos token decoder is configured.
+     */
+    public String getKerberosTokenDecoderClass() {
+        return this.kerberosTokenDecoderClass;
+    }
+
+    /**
+     * Sets the service principal name form.
+     * @param servicePrincipalNameForm The service principal name form to set. 
+     * The given literal must be either {@value #HOST_BASED_NAME_FORM} or 
+     * {@value #USERNAME_NAME_FORM}.
+     * @throws IllegalArgumentException If the given 
+     * <code>servicePrincipalNameForm</code> is not one of:
+     * {@value #HOST_BASED_NAME_FORM} or {@value #USERNAME_NAME_FORM}.
+     */
+    public void setServicePrincipalNameForm(String servicePrincipalNameForm) 
+        throws IllegalArgumentException {
+
+        if (!HOST_BASED_NAME_FORM.equals(servicePrincipalNameForm) &&
+            !USERNAME_NAME_FORM.equals(servicePrincipalNameForm)) {
+            throw new IllegalArgumentException(
+               new RampartException("invalidServicePrincipalNameForm", 
+                                    new String[] {
+                                        servicePrincipalNameForm, 
+                                        HOST_BASED_NAME_FORM, 
+                                        USERNAME_NAME_FORM }));
+        }
+        this.servicePrincipalNameForm = servicePrincipalNameForm;
+    }
+    
+    /**
+     * If Kerberos credential delegation is requested, the initiator's TGT (Ticket granting ticket) is propagated to the receiver
+     * along with the TGS(Ticket granting service).
+     * 
+     * @return true if credential delegation is requested.
+     */
+    public boolean isRequstCredentialDelegation() {
+        return requstCredentialDelegation;
+    }
+
+    /**
+     * Enables Kerberos credential delegation. If credential delegation is requested, the initiator's TGT (Ticket
+     * granting ticket) is propagated to the receiver along with the TGS(Ticket granting service). <br/>
+     * <br/>
+     * 
+     * Enabling delegation requires <b>forwardable=true</b> property to be added to the <b>[libdefaults]</b> section in
+     * the Kerberos setup configuration.KDC should also be explicitly configured to allow delegation as it is considered
+     * a security issue and is disabled by default.
+     * 
+     * @param requstCredentialDelegation if true, credential delegation is requested.
+     */
+    public void setRequstCredentialDelegation(boolean requstCredentialDelegation) {
+        this.requstCredentialDelegation = requstCredentialDelegation;
+    }
+
+    /**
+     * The delegation credential is available when the initiator has explicitly requested delegation through
+     * {@link KerberosConfig#setRequstCredentialDelegation(boolean)} and the receiver has retrieved it and set it
+     * through {@link KerberosConfig#setDelegationCredential(GSSCredential)}.
+     * 
+     * If available, the delegation credential is used by the receiver to obtain a service ticket for another
+     * Kerberos protected WS on behalf of the initiator. The receiver's principal must have explicit privileges to use
+     * the delegated credential(TGT) for retrieval of the service ticket.
+     * 
+     * @return the client's TGT wrapped in {@link GSSCredential}
+     */
+    public GSSCredential getDelegationCredential() {
+        return delegationCredential;
+    }
+
+    /**
+     * Sets the delegation credential to be used by the receiver to obtain a service ticket for another
+     * Kerberos protected WS on behalf of the initiator. The receiver's principal must have explicit privileges to use
+     * the delegated credential(TGT) for retrieval of the service ticket.
+     * 
+     * @param delegationCredential the {@link GSSCredential} to use for obtaining a TGS
+     */
+    public void setDelegationCredential(GSSCredential delegationCredential) {
+        this.delegationCredential = delegationCredential;
+    }
+
+    public PolicyComponent normalize() {
+        throw new UnsupportedOperationException();
+    }
+
+    public QName getName() {
+        return new QName(RampartConfig.NS, KERBEROS_LN);
+    }
+
+    public boolean isOptional() {
+        return true;
+    }
+
+    public boolean isIgnorable() {
+        throw new UnsupportedOperationException();
+    }
+
+    public short getType() {
+        return Constants.TYPE_ASSERTION;
+    }
+
+    public boolean equal(PolicyComponent policyComponent) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void serialize(XMLStreamWriter writer) throws XMLStreamException {
+        String prefix = writer.getPrefix(RampartConfig.NS);
+
+        if (prefix == null) {
+            prefix = RampartConfig.NS;
+            writer.setPrefix(prefix, RampartConfig.NS);
+        }
+
+        if (getJaasContext() != null) {
+            writer.writeStartElement(RampartConfig.NS, JAAS_CONTEXT_LN);
+            writer.writeCharacters(getJaasContext());
+            writer.writeEndElement();
+        }
+
+        if (getPrincipalName() != null) {
+            writer.writeStartElement(RampartConfig.NS, PRINCIPAL_NAME_LN);
+            writer.writeCharacters(getPrincipalName());
+            writer.writeEndElement();
+        }
+
+        if (getPrincipalPassword() != null) {
+            writer.writeStartElement(RampartConfig.NS, PRINCIPAL_PASSWORD_LN);
+            writer.writeCharacters(getPrincipalPassword());
+            writer.writeEndElement();
+        }
+
+        if (getServicePrincipalName() != null) {
+            writer.writeStartElement(RampartConfig.NS, SERVICE_PRINCIPAL_NAME_LN);
+            writer.writeCharacters(getServicePrincipalName());
+            writer.writeEndElement();
+        }
+
+        if (this.servicePrincipalNameForm != null) {
+            writer.writeStartElement(RampartConfig.NS,
+                                     SERVICE_PRINCIPAL_NAME_FORM_LN);
+            writer.writeCharacters(this.servicePrincipalNameForm);
+            writer.writeEndElement();
+        }
+        
+        if (this.kerberosTokenDecoderClass != null) {
+            writer.writeStartElement(RampartConfig.NS,
+                                     KERBEROS_TOKEN_DECODER_CLASS_LN);
+            writer.writeCharacters(this.kerberosTokenDecoderClass);
+            writer.writeEndElement();
+        }
+        
+        if (this.requstCredentialDelegation) {
+            writer.writeStartElement(RampartConfig.NS, REQUEST_CREDENTIAL_DELEGATION_LN);
+            writer.writeCharacters(Boolean.toString(this.requstCredentialDelegation));
+            writer.writeEndElement();
+        }
+    }
+}
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java
index 5bfba4f..bdad069 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java
@@ -114,6 +114,8 @@
 
     public final static String SSL_CONFIG = "sslConfig";
     
+    public final static String KERBEROS_CONFIG = "kerberosConfig";
+    
     private String user;
     
     private String userCertAlias;
@@ -150,7 +152,17 @@
     private String nonceLifeTime = Integer.toString(DEFAULT_NONCE_LIFE_TIME);
     
     private SSLConfig sslConfig;
+    
+    private KerberosConfig kerberosConfig;
+    
+    public KerberosConfig getKerberosConfig() {
+        return kerberosConfig;
+    }
 
+    public void setKerberosConfig(KerberosConfig kerberosConfig) {
+        this.kerberosConfig = kerberosConfig;
+    }
+    
     /*To set timeStampStrict in WSSConfig through rampartConfig - default value is false*/
     private boolean timeStampStrict = false;
     
@@ -392,6 +404,12 @@
             writer.writeEndElement();
         }
         
+        if (kerberosConfig != null) {
+            writer.writeStartElement(NS, KERBEROS_CONFIG);
+            kerberosConfig.serialize(writer);
+            writer.writeEndElement();
+        }
+        
         writer.writeEndElement();
 
     }
diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/util/RampartUtil.java b/modules/rampart-core/src/main/java/org/apache/rampart/util/RampartUtil.java
index d8d6275..6035981 100644
--- a/modules/rampart-core/src/main/java/org/apache/rampart/util/RampartUtil.java
+++ b/modules/rampart-core/src/main/java/org/apache/rampart/util/RampartUtil.java
@@ -29,6 +29,7 @@
 import org.apache.axis2.context.MessageContext;
 import org.apache.axis2.dataretrieval.DRConstants;
 import org.apache.axis2.dataretrieval.client.MexClient;
+import org.apache.axis2.description.AxisService;
 import org.apache.axis2.description.Parameter;
 import org.apache.axis2.mex.MexConstants;
 import org.apache.axis2.mex.MexException;
@@ -55,6 +56,7 @@
 import org.apache.rampart.policy.RampartPolicyData;
 import org.apache.rampart.policy.SupportingPolicyData;
 import org.apache.rampart.policy.model.CryptoConfig;
+import org.apache.rampart.policy.model.KerberosConfig;
 import org.apache.rampart.policy.model.RampartConfig;
 import org.apache.ws.secpolicy.SPConstants;
 import org.apache.ws.secpolicy.model.*;
@@ -75,6 +77,7 @@
 import org.apache.ws.security.message.WSSecEncryptedKey;
 import org.apache.ws.security.util.Loader;
 import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.validate.KerberosTokenDecoder;
 import org.apache.xml.security.utils.Constants;
 import org.jaxen.JaxenException;
 import org.jaxen.XPath;
@@ -165,6 +168,64 @@
         return cbHandler;
     }
     
+    /**
+     * Instantiates any Kerberos token decoder implementation configured via {@link KerberosConfig#setKerberosTokenDecoderClass(String)}
+     * using the {@link AxisService#getClassLoader() class loader} of the specified message context's {@link MessageContext#getAxisService() service}.
+     * 
+     * @param msgContext The current message context. Must not be null and must contain a valid service instance.
+     * @param kerberosConfig Rampart's Kerberos configuration.
+     * 
+     * @return A new instance of {@link KerberosTokenDecoder} implementation configured via {@link KerberosConfig#setKerberosTokenDecoderClass(String)} or <code>null</code>
+     * if no Kerberos token decoder is configured.
+     * @throws RampartException If the class cannot be loaded or instantiated.
+     */
+    public static KerberosTokenDecoder getKerberosTokenDecoder(MessageContext msgContext, KerberosConfig kerberosConfig) throws RampartException {
+        if (kerberosConfig == null) {
+            throw new IllegalArgumentException("Kerberos config must not be null");
+        }
+        else if (msgContext == null) {
+            throw new IllegalArgumentException("Message context must not be null");
+        }
+        
+        AxisService service = msgContext.getAxisService();
+        if (service == null) {
+            throw new IllegalArgumentException("No service available in message context: " + msgContext.getLogIDString());
+        }
+        
+        KerberosTokenDecoder kerberosTokenDecoder;
+        
+        String kerberosTokenDecoderClass = kerberosConfig.getKerberosTokenDecoderClass();
+        if (kerberosTokenDecoderClass == null) {
+            if (log.isDebugEnabled()) {
+                log.debug("No Kerberos token decoder class configured for service: " + service.getName());
+            }
+            return null;
+        }
+
+        if (log.isDebugEnabled()) {
+            log.debug(String.format("Loading Kerberos token decoder class '%s' using class loader of service '%s'", kerberosTokenDecoderClass, service.getName()));
+        }
+        
+        ClassLoader classLoader = service.getClassLoader();
+        Class krbTokenDecoderClass;
+        try {
+            krbTokenDecoderClass = Loader.loadClass(classLoader, kerberosTokenDecoderClass);
+        } 
+        catch (ClassNotFoundException e) {
+            throw new RampartException("cannotLoadKrbTokenDecoderClass", 
+                    new String[] { kerberosTokenDecoderClass }, e);
+        }
+        
+        try {
+            kerberosTokenDecoder = (KerberosTokenDecoder) krbTokenDecoderClass.newInstance();
+        } catch (java.lang.Exception e) {
+            throw new RampartException("cannotCreateKrbTokenDecoderInstance",
+                    new String[] { kerberosTokenDecoderClass }, e);
+        }
+
+        return kerberosTokenDecoder;
+    }
+    
    /**
     * Returns an instance of PolicyValidatorCallbackHandler to be used to validate ws-security results.
     * 
diff --git a/modules/rampart-core/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder b/modules/rampart-core/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
index 34900b9..a641f80 100644
--- a/modules/rampart-core/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
+++ b/modules/rampart-core/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
@@ -1,3 +1,4 @@
 org.apache.rampart.policy.builders.CryptoConfigBuilder
 org.apache.rampart.policy.builders.RampartConfigBuilder
-org.apache.rampart.policy.builders.SSLConfigBuilder
\ No newline at end of file
+org.apache.rampart.policy.builders.SSLConfigBuilder
+org.apache.rampart.policy.builders.KerberosConfigBuilder
\ No newline at end of file
diff --git a/modules/rampart-core/src/main/resources/org/apache/rampart/errors.properties b/modules/rampart-core/src/main/resources/org/apache/rampart/errors.properties
index 3250cd3..034b91d 100644
--- a/modules/rampart-core/src/main/resources/org/apache/rampart/errors.properties
+++ b/modules/rampart-core/src/main/resources/org/apache/rampart/errors.properties
@@ -47,6 +47,7 @@
 errorInDerivedKeyTokenSignature = Error in DerivedKeyToken signature
 errorInSignatureWithX509Token = Error in signature with X509Token
 errorInSignatureWithACustomToken = Error in signature with a custom token
+errorInSignatureWithKerberosToken = Error in signature with KerberosToken
 errorCreatingEncryptedKey = Error in creating an encrypted key
 errorGettingSignatureValuesForSigconf = Error in getting signature values for signature confirmation
 cannotLoadPWCBClass = Cannot load password callback class: {0}
@@ -105,3 +106,10 @@
 invalidIssuerAddress = Invalid value for Issuer
 invalidSignatureAlgo=Invalid signature algorithm for Asymmetric binding
 invalidUsernameTokenType = Invalid UsernameToken Type.
+
+#Rampart Kerberos-specific errors
+invalidServicePrincipalNameForm = Invalid servicePrincipalNameForm found in Rampart configuration ({0}). The supported service principal name forms are: \"{1}\", \"{2}\".
+noKerberosConfigDefined = No kerberosConfig policy assertion defined in rampart config.
+errorInBuildingKereberosToken = Error in building kereberos token.
+cannotLoadKrbTokenDecoderClass = Cannot load Kerberos token decoder class: {0}
+cannotCreateKrbTokenDecoderInstance = Cannot create instance of Kerberos token decoder : {0}
\ No newline at end of file
diff --git a/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java b/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java
new file mode 100644
index 0000000..3857ee7
--- /dev/null
+++ b/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java
@@ -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.rampart.policy.builders;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.neethi.Assertion;
+import org.apache.neethi.Policy;
+import org.apache.neethi.PolicyBuilder;
+import org.apache.rampart.policy.RampartPolicyBuilder;
+import org.apache.rampart.policy.RampartPolicyData;
+import org.apache.rampart.policy.model.KerberosConfig;
+import org.apache.rampart.policy.model.RampartConfig;
+import org.apache.ws.secpolicy.WSSPolicyException;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class KerberosConfigBuilderTest extends TestCase {
+
+    public static final String KERBEROS_CONFIG_POLICY_FILE = "kerberosConfig.policy";
+    
+    private static Log log = LogFactory.getLog(KerberosConfigBuilderTest.class);
+    
+    public void testBuildKerberosConfig() throws WSSPolicyException {
+        Policy kerberosConfigPolicy = loadKerberosConfigPolicy();
+        assertNotNull(String.format("Failed to parse policy file: %s", KERBEROS_CONFIG_POLICY_FILE), kerberosConfigPolicy);
+        
+        Iterator<List<Assertion>> iter = kerberosConfigPolicy.getAlternatives();
+         
+        assertTrue(String.format("No policy alternatives found in policy file: %s", KERBEROS_CONFIG_POLICY_FILE), iter.hasNext());
+         
+         //Process policy and build policy data
+        RampartPolicyData policyData = RampartPolicyBuilder.build(iter.next());
+
+        RampartConfig rampartConfig = policyData.getRampartConfig();
+        assertNotNull(String.format("No rampartConfig found in policy file: %s", KERBEROS_CONFIG_POLICY_FILE), rampartConfig);
+        KerberosConfig kerberosConfig = rampartConfig.getKerberosConfig();
+        assertNotNull(String.format("No kerberosConfig found in policy file: %s", KERBEROS_CONFIG_POLICY_FILE), kerberosConfig);
+        
+        assertEquals("Kerberos jaas context name not configured as expected.", "alice", kerberosConfig.getJaasContext());
+        assertEquals("Kerberos principal name not configured as expected.", "alice", kerberosConfig.getPrincipalName());
+        assertEquals("Kerberos principal password not configured as expected.", "changeit", kerberosConfig.getPrincipalPassword());
+        assertEquals("Kerberos service principal name not configured as expected.", "bob/example.com", kerberosConfig.getServicePrincipalName());
+        assertEquals("Kerberos token decoder class not configured as expected.", "org.foo.KerberosTokenDecoderImpl", kerberosConfig.getKerberosTokenDecoderClass());
+        assertTrue("Request for Kerberos credential delegation is expected to be enabled.", kerberosConfig.isRequstCredentialDelegation());
+    }
+
+    public void testSerializeKerberosConfig() throws XMLStreamException, SAXException, IOException, XpathException {
+        Policy kerberosConfigPolicy = loadKerberosConfigPolicy();
+        assertNotNull(String.format("Failed to parse policy file: %s", KERBEROS_CONFIG_POLICY_FILE), kerberosConfigPolicy);
+        
+        //serialize the kerberos config policy
+        StringWriter writer = new StringWriter();
+        XMLStreamWriter streamWriter = null;
+        try {
+            streamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+            kerberosConfigPolicy.serialize(streamWriter);
+        }
+        finally {
+            if (streamWriter != null) {
+                streamWriter.close();
+            }
+        }
+        
+        InputStream kerberosConfigStream = null;
+        try {
+            kerberosConfigStream = this.getClass().getResourceAsStream(KERBEROS_CONFIG_POLICY_FILE);
+            XMLUnit.setIgnoreWhitespace(true);
+            XMLAssert.assertXMLEqual("Serialized rampart:kerberosConfig element does not match the initial one.", new InputSource(kerberosConfigStream), new InputSource(new StringReader(writer.toString())));
+        }
+        finally {
+            closeStream(kerberosConfigStream);
+        }
+    }
+
+    private Policy loadKerberosConfigPolicy() {
+        InputStream kerberosConfigStream = null;
+        try {
+            kerberosConfigStream = this.getClass().getResourceAsStream(KERBEROS_CONFIG_POLICY_FILE);
+            PolicyBuilder builder = new PolicyBuilder();
+            return builder.getPolicy(kerberosConfigStream);
+        }
+        finally {
+            closeStream(kerberosConfigStream);
+        }
+    }
+    
+    private void closeStream(InputStream in) {
+        if (in != null) {
+            try {
+                in.close();
+            }
+            catch (IOException e) {
+                log.error("Failed to close input stream.", e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy b/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy
new file mode 100644
index 0000000..f727eb6
--- /dev/null
+++ b/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy
@@ -0,0 +1,22 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
+                <rampart:timestampPrecisionInMilliseconds>true</rampart:timestampPrecisionInMilliseconds>
+                <rampart:timestampTTL>300</rampart:timestampTTL>
+                <rampart:timestampMaxSkew>300</rampart:timestampMaxSkew>
+                <rampart:timestampStrict>false</rampart:timestampStrict>
+                <rampart:nonceLifeTime>300</rampart:nonceLifeTime>
+                <rampart:kerberosConfig>
+                    <rampart:jaasContext>alice</rampart:jaasContext>
+                    <rampart:principalName>alice</rampart:principalName>
+                    <rampart:principalPassword>changeit</rampart:principalPassword>
+                    <rampart:servicePrincipalName>bob/example.com</rampart:servicePrincipalName>
+                    <rampart:servicePrincipalNameForm>username</rampart:servicePrincipalNameForm>
+                    <rampart:kerberosTokenDecoderClass>org.foo.KerberosTokenDecoderImpl</rampart:kerberosTokenDecoderClass>
+                    <rampart:requestCredentialDelegation>true</rampart:requestCredentialDelegation>
+                </rampart:kerberosConfig>
+            </rampart:RampartConfig>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-integration/pom.xml b/modules/rampart-integration/pom.xml
index 8be65a1..3871110 100644
--- a/modules/rampart-integration/pom.xml
+++ b/modules/rampart-integration/pom.xml
@@ -163,6 +163,8 @@
 
                                 <copy overwrite="yes" file="target/classes/org/apache/rampart/Service.class" tofile="target/temp-ramp/org/apache/rampart/Service.class" />
                                 <copy overwrite="yes" file="target/classes/org/apache/rampart/PWCallback.class" tofile="target/temp-ramp/org/apache/rampart/PWCallback.class" />
+                                <copy overwrite="yes" file="target/classes/org/apache/rampart/KerberosDelegationService.class" tofile="target/temp-ramp/org/apache/rampart/KerberosDelegationService.class" />
+                                <copy overwrite="yes" file="target/classes/org/apache/rampart/KerberosDelegationServiceValidator.class" tofile="target/temp-ramp/org/apache/rampart/KerberosDelegationServiceValidator.class" />
                                 <copy overwrite="yes" file="src/test/resources/rampart/store.jks" tofile="target/temp-ramp/store.jks" />
                                 <!--path id="ramp.client.props" location="test-resources/rampart"/-->
                                 <!--maven:addPath id="maven.dependency.classpath" refid="ramp.client.props" -->
@@ -313,6 +315,17 @@
                                 <copy overwrite="yes" file="src/test/resources/rampart/issuer.properties" tofile="target/temp-ramp/issuer.properties" />
                                 <copy overwrite="yes" file="src/test/resources/rampart/services-sc-6.xml" tofile="target/temp-ramp/META-INF/services.xml" />
                                 <jar jarfile="target/test-resources/rampart_service_repo/services/SecureServiceSC6.aar" basedir="target/temp-ramp" />
+                                
+                                <!--  Kerberos Services -->
+                                <copy overwrite="yes" file="src/test/resources/rampart/kerberos/KerberosOverTransportKeytab.xml" tofile="target/temp-ramp/META-INF/services.xml" />
+                                <jar jarfile="target/test-resources/rampart_service_repo/services/KerberosOverTransportKeytab.aar" basedir="target/temp-ramp" />
+                                
+                                <copy overwrite="yes" file="src/test/resources/rampart/kerberos/KerberosOverTransportPWCB.xml" tofile="target/temp-ramp/META-INF/services.xml" />
+                                <jar jarfile="target/test-resources/rampart_service_repo/services/KerberosOverTransportPWCB.aar" basedir="target/temp-ramp" />
+                                
+                                <copy overwrite="yes" file="src/test/resources/rampart/kerberos/KerberosDelegation.xml" tofile="target/temp-ramp/META-INF/services.xml" />
+                                <jar jarfile="target/test-resources/rampart_service_repo/services/KerberosDelegation.aar" basedir="target/temp-ramp" />
+                                
 
                                 <!--
                                  Set up the infra for rahas tests and the rahas client repo
@@ -403,7 +416,7 @@
             </plugin>
         </plugins>
     </build>
-
+    
     <dependencies>
         <dependency>
             <groupId>org.apache.rampart</groupId>
@@ -483,6 +496,153 @@
             <artifactId>addressing</artifactId>
             <type>mar</type>
         </dependency>
+        <!--dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-kerberos-shared</artifactId>
+            <version>2.0.0-M21</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.server</groupId>
+                    <artifactId>apacheds-i18n</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.server</groupId>
+                    <artifactId>apacheds-core-jndi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.server</groupId>
+                    <artifactId>apacheds-protocol-shared</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-schema</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-schema-loader</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-schema-manager</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-cursor</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-jndi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-asn1-codec</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-constants</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-converter</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldap-schema-dao</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-ldif</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.directory.shared</groupId>
+                    <artifactId>shared-dsml-parser</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency-->
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-core-annotations</artifactId>
+            <version>2.0.0-M21</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-protocol-shared</artifactId>
+            <version>2.0.0-M21</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-protocol-kerberos</artifactId>
+            <version>2.0.0-M21</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.server</groupId>
+            <artifactId>apacheds-interceptor-kerberos</artifactId>
+            <version>2.0.0-M21</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>bouncycastle</groupId>
+                    <artifactId>bcprov-jdk15</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-codec-standalone</artifactId>
+            <version>1.0.0-M33</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.directory.api</groupId>
+            <artifactId>api-ldap-extras-codec-api</artifactId>
+            <version>1.0.0-M33</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-collections</groupId>
+            <artifactId>commons-collections</artifactId>
+            <version>3.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
diff --git a/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationService.java b/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationService.java
new file mode 100644
index 0000000..ee010b0
--- /dev/null
+++ b/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationService.java
@@ -0,0 +1,88 @@
+package org.apache.rampart;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.neethi.Policy;
+import org.apache.rampart.policy.model.KerberosConfig;
+import org.apache.rampart.policy.model.RampartConfig;
+
+/**
+ * 
+ */
+public class KerberosDelegationService extends PolicyBasedResultsValidator{
+    
+    
+    public OMElement echo(OMElement elem) throws MalformedURLException, IllegalStateException, AxisFault {
+        int port = ((HttpServletRequest)MessageContext.getCurrentMessageContext().getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST)).getLocalPort();
+        
+        final String serviceName = "KerberosOverTransportKeytab";
+        URL wsdlUrl = new URL(String.format("https://localhost:%s/axis2/services/%s?wsdl", port, serviceName));
+        
+        ConfigurationContext configContext = ConfigurationContextFactory.
+                        createConfigurationContextFromFileSystem("target/test-resources/rampart_client_repo", null);
+
+        ServiceClient serviceClient = new ServiceClient(configContext, wsdlUrl, null, null);
+
+        serviceClient.getOptions().setTimeOutInMilliSeconds(200000);
+        serviceClient.getOptions().setProperty(HTTPConstants.SO_TIMEOUT, 200000);
+        serviceClient.getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT, 200000);
+
+        serviceClient.engageModule("addressing");
+        serviceClient.engageModule("rampart");     
+        
+        RampartConfig rampartConfig = new RampartConfig();  
+        
+        KerberosConfig kerberosConfig = new KerberosConfig();
+        rampartConfig.setKerberosConfig(kerberosConfig);
+        kerberosConfig.setJaasContext("KerberosDelegation");
+        kerberosConfig.setDelegationCredential(KerberosDelegationServiceValidator.getDelegationCredential());
+
+        Policy policy = new Policy();
+        policy.addAssertion(rampartConfig);
+                
+        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
+        
+        //Blocking invocation
+        QName operation = new QName("http://rampart.apache.org", "echo");
+        OMElement echoElement = getEchoElement();
+        OMElement result = serviceClient.sendReceive(operation, echoElement);
+        return result;
+    }
+    
+    protected OMElement getEchoElement() {
+        OMFactory fac = OMAbstractFactory.getOMFactory();
+        OMNamespace omNs = fac.createOMNamespace(
+                "http://example1.org/example1", "example1");
+        OMElement method = fac.createOMElement("echo", omNs);
+        OMElement value = fac.createOMElement("Text", omNs);
+        value.addChild(fac.createOMText(value, "Testing Rampart with WS-SecPolicy"));
+        method.addChild(value);
+
+        return method;
+    }
+
+    /**
+     * New service method for testing negative scenario where service throws an exception
+     * @param element
+     * @return
+     * @throws Exception
+     */
+    public OMElement returnError(OMElement element) throws Exception {
+        throw new Exception("Testing negative scenarios with Apache Rampart. Intentional Exception");
+    }    
+    
+}
diff --git a/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationServiceValidator.java b/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationServiceValidator.java
new file mode 100644
index 0000000..b9df9cf
--- /dev/null
+++ b/modules/rampart-integration/src/main/java/org/apache/rampart/KerberosDelegationServiceValidator.java
@@ -0,0 +1,36 @@
+package org.apache.rampart;
+
+import java.util.List;
+
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSecurityEngineResult;
+import org.ietf.jgss.GSSCredential;
+
+/**
+ * 
+ */
+public class KerberosDelegationServiceValidator extends PolicyBasedResultsValidator {
+    
+    private static GSSCredential delegationCredential = null;
+
+    @Override
+    public void validate(ValidatorData data, List<WSSecurityEngineResult> results) throws RampartException {
+
+        super.validate(data, results);
+        
+
+        for (WSSecurityEngineResult wsSecEngineResult : results) {
+            Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
+            if (actInt == WSConstants.BST) {                
+                delegationCredential = (GSSCredential) wsSecEngineResult.
+                                get(WSSecurityEngineResult.TAG_DELEGATION_CREDENTIAL);
+                break;
+            }
+        }
+    }
+    
+    static GSSCredential getDelegationCredential(){
+        return delegationCredential;
+    }
+
+}
diff --git a/modules/rampart-integration/src/test/java/org/apache/rampart/AbstractRampartTest.java b/modules/rampart-integration/src/test/java/org/apache/rampart/AbstractRampartTest.java
new file mode 100644
index 0000000..dbcdbad
--- /dev/null
+++ b/modules/rampart-integration/src/test/java/org/apache/rampart/AbstractRampartTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2004 - 2014 The Apache Software Foundation.
+ *
+ * Licensed 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.rampart;
+
+import java.net.URL;
+
+import org.apache.axiom.om.OMAbstractFactory;
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMFactory;
+import org.apache.axiom.om.OMNamespace;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.axis2.context.ConfigurationContextFactory;
+import org.apache.axis2.transport.http.HTTPConstants;
+import org.apache.neethi.Policy;
+import org.apache.neethi.PolicyEngine;
+
+/**
+ * Base test class for integration tests that require Axis2 web application running in a web container.
+ * The class uses Axis2 web application deployed via {@link JettyServer}.
+ */
+public abstract class AbstractRampartTest {
+    
+    /**
+     * Default client connection timeout in milliseconds: {@value}
+     */
+    public static final int DEFAULT_CLIENT_CONNECTION_TIMEOUT_MILLIS = 200000;
+    
+    protected static final String RAMPART_CLIENT_REPO_PATH = "target/test-resources/rampart_client_repo";
+    
+    protected ServiceClient getServiceClientInstance() throws AxisFault {
+        return getServiceClientInstance(null);
+    }
+    
+    /**
+     * Creates an Axis2 service client using the specified <code>wsdlUrl</code> and {@link #DEFAULT_CLIENT_CONNECTION_TIMEOUT_MILLIS}.
+     * The service client will use Axis2 repository at {@link #RAMPART_CLIENT_REPO_PATH}.
+     * @param wsdlUrl The wsdl url to initialize the service client with. Can be null in which case the client must be configured additionally (with policy, action etc.).
+     * @return
+     * @throws AxisFault
+     */
+    protected ServiceClient getServiceClientInstance(URL wsdlUrl) throws AxisFault {
+        return getServiceClientInstance(wsdlUrl, DEFAULT_CLIENT_CONNECTION_TIMEOUT_MILLIS);
+    }
+    
+    /**
+     * Creates an Axis2 service client using the specified <code>wsdlUrl</code> and specified <code>connectionTimeoutMillis</code>.
+     * The service client will use Axis2 repository at {@link #RAMPART_CLIENT_REPO_PATH}.
+     * @param wsdlUrl The wsdl url to initialize the service client with. Can be null in which case the client must be configured additionally (with policy, action etc.).
+     * @return
+     * @throws AxisFault
+     */
+    protected ServiceClient getServiceClientInstance(URL wsdlUrl, int connectionTimeoutMillis) throws AxisFault {
+
+        ConfigurationContext configContext = ConfigurationContextFactory.
+                createConfigurationContextFromFileSystem(RAMPART_CLIENT_REPO_PATH, null);
+        
+        ServiceClient serviceClient;
+        if (wsdlUrl == null) {
+            serviceClient = new ServiceClient(configContext, null);
+        }
+        else {
+            serviceClient = new ServiceClient(configContext, wsdlUrl, null, null);
+        }
+        
+        serviceClient.getOptions().setTimeOutInMilliSeconds(connectionTimeoutMillis);
+        serviceClient.getOptions().setProperty(HTTPConstants.SO_TIMEOUT, connectionTimeoutMillis);
+        serviceClient.getOptions().setProperty(HTTPConstants.CONNECTION_TIMEOUT, connectionTimeoutMillis);
+
+        serviceClient.engageModule("addressing");
+        serviceClient.engageModule("rampart");
+
+        return serviceClient;
+
+    }
+    
+    protected OMElement getEchoElement() {
+        OMFactory fac = OMAbstractFactory.getOMFactory();
+        OMNamespace omNs = fac.createOMNamespace(
+                "http://example1.org/example1", "example1");
+        OMElement method = fac.createOMElement("echo", omNs);
+        OMElement value = fac.createOMElement("Text", omNs);
+        value.addChild(fac.createOMText(value, "Testing Rampart with WS-SecPolicy"));
+        method.addChild(value);
+
+        return method;
+    }
+
+    protected OMElement getOMElement() {
+        OMFactory fac = OMAbstractFactory.getOMFactory();
+        OMNamespace omNs = fac.createOMNamespace(
+                "http://example1.org/example1", "example1");
+        OMElement method = fac.createOMElement("returnError", omNs);
+        OMElement value = fac.createOMElement("Text", omNs);
+        value.addChild(fac.createOMText(value, "Testing Rampart with WS-SecPolicy"));
+        method.addChild(value);
+
+        return method;
+    }
+
+    protected Policy loadPolicy(String xmlPath) {
+        return PolicyEngine.getPolicy(this.getClass().getResourceAsStream(xmlPath));
+    }
+}
diff --git a/modules/rampart-integration/src/test/java/org/apache/rampart/RampartKerberosTest.java b/modules/rampart-integration/src/test/java/org/apache/rampart/RampartKerberosTest.java
new file mode 100644
index 0000000..c489900
--- /dev/null
+++ b/modules/rampart-integration/src/test/java/org/apache/rampart/RampartKerberosTest.java
@@ -0,0 +1,252 @@
+package org.apache.rampart;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.testutils.JettyServer;
+import org.apache.commons.io.IOUtils;
+import org.apache.neethi.Policy;
+import org.apache.rampart.policy.model.KerberosConfig;
+import org.apache.rampart.policy.model.RampartConfig;
+import org.apache.rampart.util.KerberosServer;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests Kerberos authentication over transport binding using a Kerberos token as supporting endorsing token.
+ * The test will use Apache DS Kerberos server, see {@link KerberosServer}.
+ * 
+ * The test is tailored for Oracle Java execution since it uses <code>com.sun.security.auth.module.Krb5LoginModule</code> JAAS login module for Kerberos authentication.
+ */
+public class RampartKerberosTest extends AbstractRampartTest {
+
+    /**
+     * Java system property for setting JAAS configuration file: {@value}
+     */
+    public static final String JAAS_CONF_SYS_PROP = "java.security.auth.login.config";
+    
+    /**
+     * Java system property for setting Kerberos 5 configuration file: {@value}
+     */
+    public static final String KRB5_CONF_SYS_PROP = "java.security.krb5.conf";
+    
+    /**
+     * JAAS configuration file to use: {@value}
+     * <p>
+     * Contains Kerberos login module entries for authenticating client and server principals:
+     * </p>
+     */
+    public static final String KERBEROS_JAAS_CONF = "src/test/resources/kerberos/jaas.conf";
+    
+    /**
+     * Kerberos configuration file <b>template</b> to use: {@value}
+     * <p>
+     * Specifies the Kerberos realm and KDC server to use, the configuration must contain a <code>KDC_PORT</code> literal
+     * which will be replaced with actual KDC server port.
+     * </p>
+     */
+    public static final String KERBEROS_CONF_TEMPLATE = "src/test/resources/kerberos/krb5.conf.template";
+    
+    /**
+     * A token literal in kerberos5 configuration file template that must be replaced with actual KDC port value: {@value}
+     */
+    public static final String KERBEROS_CONF_KDC_PORT_TOKEN = "KDC_PORT";
+    
+    @Rule
+    public final JettyServer server = new JettyServer("target/test-resources/rampart_service_repo", true);
+    
+    /**
+     * Stores any original JAAS configuration set via {@link #JAAS_CONF_SYS_PROP} property to restore it after test execution.
+     */
+    protected String jaasConf;
+    
+    /**
+     * Stores any original Kerberos 5 configuration set via {@link #KRB5_CONF_SYS_PROP} property to restore it after test execution.
+     */
+    protected String krb5Conf;
+    
+    @Test
+    public void testKerberosOverTransportKeytab() throws XMLStreamException, SAXException, IOException {
+        final String serviceName = "KerberosOverTransportKeytab";
+        URL serviceUrl = new URL(server.getEndpoint(serviceName) + "?wsdl");
+        
+        ServiceClient serviceClient = getServiceClientInstance(serviceUrl);
+
+        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);
+                
+        
+        RampartConfig rampartConfig = new RampartConfig();
+        KerberosConfig kerberosConfig = new KerberosConfig();
+        rampartConfig.setKerberosConfig(kerberosConfig);
+
+        kerberosConfig.setJaasContext(serviceName + "Client");        
+
+        Policy policy = new Policy();
+        policy.addAssertion(rampartConfig);                
+        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
+        
+        //Blocking invocation
+        QName operation = new QName("http://rampart.apache.org", "echo");
+        OMElement echoElement = getEchoElement();
+        OMElement result = serviceClient.sendReceive(operation, echoElement);
+        XMLAssert.assertXMLEqual(echoElement.toStringWithConsume(), result.toStringWithConsume());
+    }
+    
+    @Test
+    public void testKerberosOverTransportPWCB() throws XMLStreamException, SAXException, IOException {
+        final String serviceName = "KerberosOverTransportPWCB";
+        URL serviceUrl = new URL(server.getEndpoint(serviceName) + "?wsdl");
+        
+        ServiceClient serviceClient = getServiceClientInstance(serviceUrl);
+
+        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);
+
+        RampartConfig rampartConfig = new RampartConfig();
+        rampartConfig.setUser("alice");        
+        rampartConfig.setPwCbClass(org.apache.rahas.PWCallback.class.getName());
+        
+        KerberosConfig kerberosConfig = new KerberosConfig();
+        rampartConfig.setKerberosConfig(kerberosConfig);
+
+        kerberosConfig.setJaasContext(serviceName + "Client");
+
+        Policy policy = new Policy();
+        policy.addAssertion(rampartConfig);        
+        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
+        
+        //Blocking invocation
+        QName operation = new QName("http://rampart.apache.org", "echo");
+        OMElement echoElement = getEchoElement();
+        OMElement result = serviceClient.sendReceive(operation, echoElement);
+        XMLAssert.assertXMLEqual(echoElement.toStringWithConsume(), result.toStringWithConsume());
+    }
+    
+    @Test
+    public void testKerberosDelegation() throws XMLStreamException, SAXException, IOException {
+        final String serviceName = "KerberosDelegation";
+        URL serviceUrl = new URL(server.getEndpoint(serviceName) + "?wsdl");
+
+        ServiceClient serviceClient = getServiceClientInstance(serviceUrl);
+
+        System.out.println("Testing WS-Sec: Kerberos scenario: " + serviceName);
+                
+        
+        RampartConfig rampartConfig = new RampartConfig();
+        KerberosConfig kerberosConfig = new KerberosConfig();
+        rampartConfig.setKerberosConfig(kerberosConfig);
+
+        kerberosConfig.setJaasContext(serviceName + "Client");  
+        kerberosConfig.setRequstCredentialDelegation(true);
+
+        Policy policy = new Policy();
+        policy.addAssertion(rampartConfig);                
+        serviceClient.getAxisService().getPolicySubject().attachPolicyComponent(policy);
+        
+        //Blocking invocation
+        QName operation = new QName("http://rampart.apache.org", "echo");
+        OMElement echoElement = getEchoElement();
+        OMElement result = serviceClient.sendReceive(operation, echoElement);
+        XMLAssert.assertXMLEqual(echoElement.toStringWithConsume(), result.toStringWithConsume());
+    }
+    
+    @Before
+    public void setUpKerberos() throws Exception {
+        System.setProperty("sun.security.krb5.debug", "true");
+        System.setProperty("sun.security.jgss.debug", "true");
+        
+        KerberosServer.startKerberosServer();
+                        
+        //configure JGSS
+        krb5Conf = System.getProperty(KRB5_CONF_SYS_PROP);
+        
+        File krb5ConfFile = generateKerberosConf();
+        System.out.println("Using Kerberos configuration file: " + krb5ConfFile.getAbsolutePath());
+        System.setProperty(KRB5_CONF_SYS_PROP, krb5ConfFile.getAbsolutePath());
+        
+        //configure JAAS
+        jaasConf = System.getProperty(JAAS_CONF_SYS_PROP);
+        System.out.println("Using Kerberos JAAS configuration file: " + new File(KERBEROS_JAAS_CONF).getAbsolutePath());
+        System.setProperty(JAAS_CONF_SYS_PROP, KERBEROS_JAAS_CONF);
+    }
+
+    @After
+    public void tearDownKerberos() throws Exception {
+        KerberosServer.stopKerberosServer();
+        
+        if (jaasConf != null) {
+            System.setProperty(JAAS_CONF_SYS_PROP, jaasConf);
+        }
+        else {
+            System.clearProperty(JAAS_CONF_SYS_PROP);
+        }
+        
+        if (krb5Conf != null) {
+            System.setProperty(KRB5_CONF_SYS_PROP, krb5Conf);
+        }
+        else {
+            System.clearProperty(KRB5_CONF_SYS_PROP);
+        }
+    }
+    
+    /**
+     * Generates a Kerberos configuration file (krb5.conf) out of the {@link #KERBEROS_CONF_TEMPLATE} file,
+     * replacing the {@link #KERBEROS_CONF_KDC_PORT_TOKEN} with actual KDC port.
+     * 
+     * @return The generated Kerberos configuration file. It will be generated under the following path:
+     * <code>target/tmp/{thisClassSimpleName}_krb5.conf</code>
+     * 
+     * @throws IOException 
+     */
+    protected File generateKerberosConf() throws IOException {
+        File tmpDir = new File("target" + File.separator + "tmp");
+        if (!tmpDir.exists() && !tmpDir.mkdirs()) {
+            throw new RuntimeException("Failed to create temp directory: " + tmpDir.getAbsolutePath());
+        }
+        
+        File krb5ConfTemplate = new File(KERBEROS_CONF_TEMPLATE);
+        if (!krb5ConfTemplate.exists()) {
+            throw new IllegalArgumentException("Cannot find kerberos configuration file template: " + krb5ConfTemplate.getAbsolutePath());
+        }
+        
+        FileInputStream krb5ConfTemplateIn = null;
+        String krb5ConfContent;
+        try {
+            krb5ConfTemplateIn = new FileInputStream(krb5ConfTemplate);
+            krb5ConfContent = IOUtils.toString(krb5ConfTemplateIn);
+        }
+        finally {
+            IOUtils.closeQuietly(krb5ConfTemplateIn);
+        }
+        
+        if (krb5ConfContent.indexOf(KERBEROS_CONF_KDC_PORT_TOKEN) == -1) {
+            throw new IllegalArgumentException(String.format("Cannot find any %s token in kerberos configuration file template: %s",
+                    KERBEROS_CONF_KDC_PORT_TOKEN, krb5ConfTemplate.getAbsolutePath()));
+        }
+            
+        krb5ConfContent = krb5ConfContent.replace(KERBEROS_CONF_KDC_PORT_TOKEN, String.valueOf(KerberosServer.getPort()));
+        
+        File krb5Conf = new File(tmpDir, this.getClass().getSimpleName() + "_krb5.conf");
+        FileOutputStream krb5ConfOut = null;
+        try {
+            krb5ConfOut = new FileOutputStream(krb5Conf);
+            IOUtils.write(krb5ConfContent, krb5ConfOut);
+        }
+        finally {
+            IOUtils.closeQuietly(krb5ConfOut);
+        }
+        
+        return krb5Conf;
+    }
+}
diff --git a/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosServer.java b/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosServer.java
new file mode 100644
index 0000000..efefb4f
--- /dev/null
+++ b/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosServer.java
@@ -0,0 +1,214 @@
+/**
+ * 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.rampart.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.DatagramSocket;
+import java.nio.file.Files;
+import java.security.Provider;
+import java.security.Security;
+import java.util.List;
+
+import org.apache.axis2.testutils.PortAllocator;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.directory.api.ldap.model.entry.DefaultEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifEntry;
+import org.apache.directory.api.ldap.model.ldif.LdifReader;
+import org.apache.directory.server.core.api.DirectoryService;
+import org.apache.directory.server.core.api.interceptor.Interceptor;
+import org.apache.directory.server.core.api.partition.Partition;
+import org.apache.directory.server.core.factory.DefaultDirectoryServiceFactory;
+import org.apache.directory.server.core.factory.DirectoryServiceFactory;
+import org.apache.directory.server.core.factory.PartitionFactory;
+import org.apache.directory.server.core.kerberos.KeyDerivationInterceptor;
+import org.apache.directory.server.kerberos.KerberosConfig;
+import org.apache.directory.server.kerberos.kdc.KdcServer;
+import org.apache.directory.server.protocol.shared.transport.Transport;
+import org.apache.directory.server.protocol.shared.transport.UdpTransport;
+import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
+
+/**
+ * Runs an Apache DS Kerberos server.
+ * @see org.apache.wss4j.integration.test.common.KerberosServiceStarter
+ */
+public class KerberosServer {
+
+    private static final Log log = LogFactory.getLog(KerberosServer.class);
+    
+    /**
+     * The used DirectoryService instance
+     */
+    private static DirectoryService directoryService;
+
+    /**
+     * The used KdcServer instance
+     */
+    private static KdcServer kdcServer;
+
+    private static Provider provider = null;
+    private static int providerPos = 2;
+    
+    private static File workDir = null;
+    
+    /**
+     * Starts an Apache DS Kerberos server with dynamically allocated port.
+     * 
+     * @return
+     * @throws Exception
+     */
+    public static synchronized void startKerberosServer() throws Exception {
+        int kdcPort = PortAllocator.allocatePort();
+        
+        DatagramSocket datagramSocket = new DatagramSocket(kdcPort);
+        datagramSocket.setReuseAddress(true);
+        datagramSocket.close();
+
+        //Ok, apache ds doesn't like the bouncy castle provider at position 2
+        //Caused by: KrbException: Integrity check on decrypted field failed (31) - Integrity check on decrypted field failed
+        Provider[] installedProviders = Security.getProviders();
+        for (int i = 0; i < installedProviders.length; i++) {
+            Provider installedProvider = installedProviders[i];
+            if ("BC".equals(installedProvider.getName())) {
+                provider = installedProvider;
+                providerPos = i;
+                Security.removeProvider("BC");
+                break;
+            }
+        }
+        if (provider != null) {
+            Security.addProvider(provider);
+        }
+        
+        workDir = Files.createTempDirectory("server-work").toFile();
+        
+        DirectoryServiceFactory directoryServiceFactory = new DefaultDirectoryServiceFactory();
+        directoryService = directoryServiceFactory.getDirectoryService();
+        directoryService.setAccessControlEnabled(false);
+        directoryService.setAllowAnonymousAccess(false);
+        directoryService.getChangeLog().setEnabled(true);
+        
+        List<Interceptor> interceptors = directoryService.getInterceptors();
+        interceptors.add(new KeyDerivationInterceptor());
+        directoryService.setInterceptors(interceptors);
+        directoryServiceFactory.init("defaultDS");
+
+        PartitionFactory partitionFactory = directoryServiceFactory.getPartitionFactory();
+        Partition partition = partitionFactory.createPartition(directoryService.getSchemaManager(),
+            directoryService.getDnFactory(), "example", "dc=example,dc=com", 1000, workDir);
+
+        partitionFactory.addIndex(partition, "objectClass", 1000);
+        partitionFactory.addIndex(partition, "dc", 1000);
+        partitionFactory.addIndex(partition, "ou", 1000);
+
+        partition.setSchemaManager(directoryService.getSchemaManager());
+        // Inject the partition into the DirectoryService
+        directoryService.addPartition(partition);
+
+        InputStream is = KerberosServer.class.getClassLoader().getResourceAsStream("kerberos/users.ldif");
+        LdifReader ldifReader = new LdifReader(is);
+        for (LdifEntry entry : ldifReader) {
+            directoryService.getAdminSession().add(new DefaultEntry(directoryService.getSchemaManager(), entry.getEntry()));
+        }
+        ldifReader.close();
+
+        KerberosConfig kerberosConfig = new KerberosConfig();
+        kerberosConfig.setServicePrincipal("krbtgt/EXAMPLE.COM@EXAMPLE.COM");
+        kerberosConfig.setPrimaryRealm("EXAMPLE.COM");
+        kerberosConfig.setSearchBaseDn("dc=example,dc=com");
+        kerberosConfig.setMaximumTicketLifetime(60000 * 1440);
+        kerberosConfig.setMaximumRenewableLifetime(60000 * 10080);
+        kerberosConfig.setEncryptionTypes(new EncryptionType[]{EncryptionType.AES128_CTS_HMAC_SHA1_96});
+        
+        kdcServer = new KdcServer(kerberosConfig);
+        kdcServer.setServiceName("DefaultKrbServer");        
+        
+        final String kdcHostname = "localhost";
+        log.info(String.format("Starting service on %s:%s", kdcHostname, kdcPort));
+        
+        UdpTransport udp = new UdpTransport(kdcHostname, kdcPort);
+        kdcServer.addTransports(udp);
+        kdcServer.setDirectoryService(directoryService);
+        kdcServer.start();
+    }
+
+    /**
+     * @return The Apache DS Kerberos server port.
+     * @throws IllegalArgumentException If server or respective transport are not initialized
+     */
+    public static synchronized int getPort() throws IllegalArgumentException {
+        if (kdcServer == null) {
+            throw new IllegalStateException("Kerberos server is not initialized");
+        }
+
+        Transport[] transports =  kdcServer.getTransports();
+        if (transports == null || transports.length == 0) {
+            throw new IllegalStateException("Kerberos server does not configure any transports");
+        }
+        
+        for (Transport transport : transports) {
+            if (transport instanceof UdpTransport) {
+                return transport.getPort();
+            }
+        }
+        
+        throw new IllegalStateException(
+                String.format("Cannot identify Kerberos server port. List of transports does not contain an %s instance",
+                        UdpTransport.class.getName()));
+    } 
+    
+    /**
+     * Stops the Apache DS Kerberos server.
+     * @throws Exception
+     */
+    public static synchronized void stopKerberosServer() throws Exception {
+        log.info("Stop called");
+        try {        
+            if (directoryService != null) {
+                try {
+                    directoryService.shutdown();
+                }
+                finally {                    
+                    try {
+                        FileUtils.deleteDirectory(workDir);
+                    }
+                    catch (IOException e) {
+                        log.error("Failed to delete Apache DS working directory: " + workDir.getAbsolutePath() , e);
+                    }
+                }
+                directoryService = null;
+            }
+        }
+        finally {
+            if (kdcServer != null) {
+                kdcServer.stop();
+                kdcServer = null;
+            }
+            
+            if (provider != null) {
+                //restore BC position
+                Security.removeProvider("BC");
+                Security.insertProviderAt(provider, providerPos);
+            }
+        }
+    }
+}
diff --git a/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosTokenDecoderImpl.java b/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosTokenDecoderImpl.java
new file mode 100644
index 0000000..8779ff1
--- /dev/null
+++ b/modules/rampart-integration/src/test/java/org/apache/rampart/util/KerberosTokenDecoderImpl.java
@@ -0,0 +1,156 @@
+/**
+ * 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.rampart.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.security.auth.Subject;
+
+import org.apache.directory.shared.kerberos.codec.KerberosDecoder;
+import org.apache.directory.shared.kerberos.components.EncTicketPart;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.validate.KerberosTokenDecoder;
+
+/**
+ * A copy of wss4j 2.0 Kerberos token decoder implementation.
+ * 
+ * @see org.apache.wss4j.common.kerberos.KerberosTokenDecoderImpl
+ * 
+ * TODO Once Rampart adopts wss4j 2.0, this class must be removed in favor of wss4j's
+ */
+public class KerberosTokenDecoderImpl implements KerberosTokenDecoder {
+    
+    private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
+
+    private byte[] serviceTicket;
+    private Subject subject;
+
+    private boolean decoded = false;
+    private EncTicketPart encTicketPart;
+
+    /**
+     * Clear all internal information
+     */
+    public void clear() {
+        serviceTicket = null;
+        subject = null;
+        decoded = false;
+        encTicketPart = null;
+    }
+
+    /**
+     * Set the AP-REQ Kerberos Token
+     *
+     * @param token the AP-REQ Kerberos Token
+     */
+    public void setToken(byte[] token) {
+        serviceTicket = token;
+    }
+
+    /**
+     * Set the Subject
+     *
+     * @param subject the Subject
+     */
+    public void setSubject(Subject subject) {
+        this.subject = subject;
+    }
+
+    /**
+     * Get the session key from the token
+     *
+     * @return the session key from the token
+     */
+    public byte[] getSessionKey() {
+        if (!decoded) {
+            decodeServiceTicket();
+        }
+        if (encTicketPart != null && encTicketPart.getKey() != null) {
+            return encTicketPart.getKey().getKeyValue();
+        }
+        return null;
+    }
+
+    /**
+     * Get the client principal name from the decoded service ticket.
+     *
+     * @return the client principal name
+     */
+    public String getClientPrincipalName() {
+        if (!decoded) {
+            decodeServiceTicket();
+        }
+        return encTicketPart.getCName().toString();
+    }
+
+    // Decode the service ticket.
+    private synchronized void decodeServiceTicket() {
+        parseServiceTicket(serviceTicket);
+        decoded = true;
+    }
+
+    // Parses the service ticket (GSS AP-REQ token)
+    private void parseServiceTicket(byte[] ticket) {
+        try {
+            // I didn't find a better way how to parse this Kerberos Message...
+            org.bouncycastle.asn1.ASN1InputStream asn1InputStream =
+                    new org.bouncycastle.asn1.ASN1InputStream(new ByteArrayInputStream(ticket));
+            org.bouncycastle.asn1.DERApplicationSpecific derToken =
+                    (org.bouncycastle.asn1.DERApplicationSpecific) asn1InputStream.readObject();
+            if (derToken == null || !derToken.isConstructed()) {
+                asn1InputStream.close();
+                throw new WSSecurityException("invalid kerberos token");
+            }
+            asn1InputStream.close();
+
+            asn1InputStream = new org.bouncycastle.asn1.ASN1InputStream(new ByteArrayInputStream(derToken.getContents()));
+            org.bouncycastle.asn1.DERObjectIdentifier kerberosOid =
+                    (org.bouncycastle.asn1.DERObjectIdentifier) asn1InputStream.readObject();
+            if (!kerberosOid.getId().equals(KERBEROS_OID)) {
+                asn1InputStream.close();
+                throw new WSSecurityException("invalid kerberos token");
+            }
+
+            int readLowByte = asn1InputStream.read() & 0xff;
+            int readHighByte = asn1InputStream.read() & 0xff;
+            int read = (readHighByte << 8) + readLowByte; //NOPMD
+            if (read != 0x01) {
+                throw new WSSecurityException("invalid kerberos token");
+            }
+            
+            this.encTicketPart = KerberosDecoder.decodeEncTicketPart(toByteArray(asn1InputStream));
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static byte[] toByteArray(InputStream inputStream) throws IOException {
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        int read;
+        byte[] buf = new byte[1024];
+        while ((read = inputStream.read(buf)) != -1) {
+            byteArrayOutputStream.write(buf, 0, read);
+        }
+        return byteArrayOutputStream.toByteArray();
+    }
+}
diff --git a/modules/rampart-integration/src/test/resources/kerberos/alice.keytab b/modules/rampart-integration/src/test/resources/kerberos/alice.keytab
new file mode 100644
index 0000000..053b248
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/alice.keytab
Binary files differ
diff --git a/modules/rampart-integration/src/test/resources/kerberos/bob.keytab b/modules/rampart-integration/src/test/resources/kerberos/bob.keytab
new file mode 100644
index 0000000..5be6b13
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/bob.keytab
Binary files differ
diff --git a/modules/rampart-integration/src/test/resources/kerberos/jaas.conf b/modules/rampart-integration/src/test/resources/kerberos/jaas.conf
new file mode 100644
index 0000000..b236d4a
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/jaas.conf
@@ -0,0 +1,49 @@
+KerberosOverTransportKeytab {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useKeyTab=true
+        keyTab="target/test-classes/kerberos/bob.keytab"
+        principal=bob
+        storeKey=true
+        isInitiator=false
+        refreshKrb5Config=true;
+};
+
+KerberosOverTransportKeytabClient {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useKeyTab=true
+        keyTab="target/test-classes/kerberos/alice.keytab"
+        principal=alice
+        refreshKrb5Config=true;
+};
+
+KerberosOverTransportPWCB {
+    com.sun.security.auth.module.Krb5LoginModule required
+        principal=bob
+        storeKey=true
+        isInitiator=false
+        refreshKrb5Config=true;
+};
+
+KerberosOverTransportPWCBClient {
+    com.sun.security.auth.module.Krb5LoginModule required
+        principal=alice
+        refreshKrb5Config=true;
+};
+
+KerberosDelegation {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useKeyTab=true
+        keyTab="target/test-classes/kerberos/bob.keytab"
+        principal=bob
+        storeKey=true
+        isInitiator=true
+        refreshKrb5Config=true;
+};
+
+KerberosDelegationClient {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useKeyTab=true
+        keyTab="target/test-classes/kerberos/alice.keytab"
+        principal=alice
+        refreshKrb5Config=true;
+};
\ No newline at end of file
diff --git a/modules/rampart-integration/src/test/resources/kerberos/krb5.conf.template b/modules/rampart-integration/src/test/resources/kerberos/krb5.conf.template
new file mode 100644
index 0000000..30a9ebf
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/krb5.conf.template
@@ -0,0 +1,8 @@
+[libdefaults]
+	default_realm = EXAMPLE.COM
+	forwardable = true	
+
+[realms]
+	EXAMPLE.COM = {
+		kdc = localhost:KDC_PORT
+	}
\ No newline at end of file
diff --git a/modules/rampart-integration/src/test/resources/kerberos/readme b/modules/rampart-integration/src/test/resources/kerberos/readme
new file mode 100644
index 0000000..9c04c80
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/readme
@@ -0,0 +1,9 @@
+In order to create alice.keytab and bob.keytab, in src/test/resources/kerberos directory, execute the following commands depending on the underlying OS:
+
+Windows:
+<java_home>/bin/ktab.exe -a alice@EXAMPLE.COM password -k alice.keytab
+<java_home>/bin/ktab.exe -a bob@EXAMPLE.COM password -k bob.keytab
+
+Unix (requires ktutil)
+ktutil add_entry -password -p alice@EXAMPLE.COM -k 1 -e aes128-cts-hmac-sha1-96\npassword\n write_kt alice.keytab\n quit
+ktutil add_entry -password -p bob@EXAMPLE.COM -k 1 -e aes128-cts-hmac-sha1-96\npassword\n write_kt bob.keytab\n quit 
\ No newline at end of file
diff --git a/modules/rampart-integration/src/test/resources/kerberos/users.ldif b/modules/rampart-integration/src/test/resources/kerberos/users.ldif
new file mode 100644
index 0000000..f0557ec
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/kerberos/users.ldif
@@ -0,0 +1,60 @@
+version: 1
+
+dn: dc=example,dc=com
+objectClass: top
+objectClass: domain
+objectClass: extensibleObject
+dc: example
+
+dn: ou=users,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: users
+
+dn: ou=services,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+ou: services
+
+dn: krb5PrincipalName=bob@EXAMPLE.COM+uid=bob+sn=bob+cn=bob,ou=services,dc=example,dc=com
+objectClass: top
+objectClass: inetOrgPerson
+objectClass: krb5KDCEntry
+objectClass: uidObject
+objectClass: person
+objectClass: krb5Principal
+objectClass: organizationalPerson
+cn: bob
+krb5KeyVersionNumber: 0
+krb5PrincipalName: bob@EXAMPLE.COM
+sn: bob
+uid: bob
+userPassword: password
+
+dn: uid=krbtgt+krb5PrincipalName=krbtgt/EXAMPLE.COM@EXAMPLE.COM+ou=TGT,ou=se
+ rvices,dc=example,dc=com
+objectClass: top
+objectClass: organizationalUnit
+objectClass: krb5KDCEntry
+objectClass: uidObject
+objectClass: krb5Principal
+krb5KeyVersionNumber: 0
+krb5PrincipalName: krbtgt/EXAMPLE.COM@EXAMPLE.COM
+ou: TGT
+uid: krbtgt
+userPassword: randomKey
+
+dn: cn=alice+krb5PrincipalName=alice@EXAMPLE.COM+uid=alice,ou=users,dc=example,dc=com
+objectClass: top
+objectClass: krb5KDCEntry
+objectClass: inetOrgPerson
+objectClass: uidObject
+objectClass: krb5Principal
+objectClass: person
+objectClass: organizationalPerson
+cn: alice
+krb5KeyVersionNumber: 0
+krb5PrincipalName: alice@EXAMPLE.COM
+sn: alice
+uid: alice
+userPassword: password
diff --git a/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosDelegation.xml b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosDelegation.xml
new file mode 100644
index 0000000..5ba8922
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosDelegation.xml
@@ -0,0 +1,86 @@
+<service name="KerberosDelegation">
+
+    <module ref="addressing" />
+    <module ref="rampart" />
+
+    <parameter locked="false" name="ServiceClass">org.apache.rampart.KerberosDelegationService</parameter>
+
+    <transports>
+        <transport>https</transport>
+    </transports>
+    
+    <operation name="echo">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:echo</actionMapping>
+    </operation>
+
+    <operation name="returnError">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:returnError</actionMapping>
+    </operation>
+
+    <wsp:PolicyAttachment xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
+
+        <wsp:AppliesTo>
+            <policy-subject identifier="binding:soap" />
+            <policy-subject identifier="binding:soap12" />
+        </wsp:AppliesTo>
+        
+        <wsp:Policy wsu:Id="KerberosOverTransport"
+            xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
+            xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
+            xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+        
+            <wsp:ExactlyOne>
+                <wsp:All>
+                    <sp:TransportBinding>
+                        <wsp:Policy>
+                            <sp:TransportToken>
+                                <wsp:Policy>
+                                    <sp:HttpsToken />
+                                </wsp:Policy>
+                            </sp:TransportToken>
+                            <sp:AlgorithmSuite>
+                                <wsp:Policy>
+                                    <sp:Basic128 />
+                                </wsp:Policy>
+                            </sp:AlgorithmSuite>
+                            <sp:IncludeTimestamp />
+                        </wsp:Policy>
+                    </sp:TransportBinding>
+                    <sp:EndorsingSupportingTokens>
+                        <wsp:Policy>
+                            <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                                <wsp:Policy>
+                                    <sp:WssGssKerberosV5ApReqToken11 />
+                                </wsp:Policy>
+                            </sp:KerberosToken>
+                        </wsp:Policy>
+                    </sp:EndorsingSupportingTokens>
+                    <sp:Wss11>
+                        <wsp:Policy />
+                    </sp:Wss11>
+                    <wsaw:UsingAddressing />
+                    
+                   <rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
+                        <rampart:kerberosConfig>
+                            <rampart:jaasContext>KerberosDelegation</rampart:jaasContext>
+                            <rampart:servicePrincipalNameForm>username</rampart:servicePrincipalNameForm>
+                            <rampart:kerberosTokenDecoderClass>org.apache.rampart.util.KerberosTokenDecoderImpl</rampart:kerberosTokenDecoderClass>
+                        </rampart:kerberosConfig>
+                        <rampart:policyValidatorCbClass>org.apache.rampart.KerberosDelegationServiceValidator</rampart:policyValidatorCbClass>                        
+                    </rampart:RampartConfig>
+                </wsp:All>
+            </wsp:ExactlyOne>
+        </wsp:Policy>
+
+    </wsp:PolicyAttachment>
+
+    <!-- Configure SPN using addressingIdentity extensibility element -->
+    <parameter name="addressingIdentity">
+        <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
+            <Upn>bob@EXAMPLE.COM</Upn>
+        </Identity>
+    </parameter>
+
+</service>
diff --git a/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportKeytab.xml b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportKeytab.xml
new file mode 100644
index 0000000..27c4dc9
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportKeytab.xml
@@ -0,0 +1,85 @@
+<service name="KerberosOverTransportKeytab">
+
+    <module ref="addressing" />
+    <module ref="rampart" />
+
+    <parameter locked="false" name="ServiceClass">org.apache.rampart.Service</parameter>
+
+    <transports>
+        <transport>https</transport>
+    </transports>
+    
+    <operation name="echo">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:echo</actionMapping>
+    </operation>
+
+    <operation name="returnError">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:returnError</actionMapping>
+    </operation>
+
+    <wsp:PolicyAttachment xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
+
+        <wsp:AppliesTo>
+            <policy-subject identifier="binding:soap" />
+            <policy-subject identifier="binding:soap12" />
+        </wsp:AppliesTo>
+        
+        <wsp:Policy wsu:Id="KerberosOverTransport"
+            xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
+            xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
+            xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+        
+            <wsp:ExactlyOne>
+                <wsp:All>
+                    <sp:TransportBinding>
+                        <wsp:Policy>
+                            <sp:TransportToken>
+                                <wsp:Policy>
+                                    <sp:HttpsToken />
+                                </wsp:Policy>
+                            </sp:TransportToken>
+                            <sp:AlgorithmSuite>
+                                <wsp:Policy>
+                                    <sp:Basic128 />
+                                </wsp:Policy>
+                            </sp:AlgorithmSuite>
+                            <sp:IncludeTimestamp />
+                        </wsp:Policy>
+                    </sp:TransportBinding>
+                    <sp:EndorsingSupportingTokens>
+                        <wsp:Policy>
+                            <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                                <wsp:Policy>
+                                    <sp:WssGssKerberosV5ApReqToken11 />
+                                </wsp:Policy>
+                            </sp:KerberosToken>
+                        </wsp:Policy>
+                    </sp:EndorsingSupportingTokens>
+                    <sp:Wss11>
+                        <wsp:Policy />
+                    </sp:Wss11>
+                    <wsaw:UsingAddressing />
+                    
+                    <rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
+                        <rampart:kerberosConfig>
+                            <rampart:jaasContext>KerberosOverTransportKeytab</rampart:jaasContext>
+                            <rampart:servicePrincipalNameForm>username</rampart:servicePrincipalNameForm>
+                            <rampart:kerberosTokenDecoderClass>org.apache.rampart.util.KerberosTokenDecoderImpl</rampart:kerberosTokenDecoderClass>
+                        </rampart:kerberosConfig>
+                    </rampart:RampartConfig>
+                </wsp:All>
+            </wsp:ExactlyOne>
+        </wsp:Policy>
+
+    </wsp:PolicyAttachment>
+
+    <!-- Configure SPN using addressingIdentity extensibility element -->
+    <parameter name="addressingIdentity">
+        <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
+            <Upn>bob@EXAMPLE.COM</Upn>
+        </Identity>
+    </parameter>
+
+</service>
diff --git a/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportPWCB.xml b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportPWCB.xml
new file mode 100644
index 0000000..fc3a3a3
--- /dev/null
+++ b/modules/rampart-integration/src/test/resources/rampart/kerberos/KerberosOverTransportPWCB.xml
@@ -0,0 +1,88 @@
+<service name="KerberosOverTransportPWCB">
+
+    <module ref="addressing" />
+    <module ref="rampart" />
+
+    <parameter locked="false" name="ServiceClass">org.apache.rampart.Service</parameter>
+
+    <transports>
+        <transport>https</transport>
+    </transports>
+    
+    <operation name="echo">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:echo</actionMapping>
+    </operation>
+
+    <operation name="returnError">
+        <messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver" />
+        <actionMapping>urn:returnError</actionMapping>
+    </operation>
+
+    <wsp:PolicyAttachment xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
+
+        <wsp:AppliesTo>
+            <policy-subject identifier="binding:soap" />
+            <policy-subject identifier="binding:soap12" />
+        </wsp:AppliesTo>
+        
+        <wsp:Policy wsu:Id="KerberosOverTransport"
+            xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
+            xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
+            xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+        
+            <wsp:ExactlyOne>
+                <wsp:All>
+                    <sp:TransportBinding>
+                        <wsp:Policy>
+                            <sp:TransportToken>
+                                <wsp:Policy>
+                                    <sp:HttpsToken />
+                                </wsp:Policy>
+                            </sp:TransportToken>
+                            <sp:AlgorithmSuite>
+                                <wsp:Policy>
+                                    <sp:Basic128 />
+                                </wsp:Policy>
+                            </sp:AlgorithmSuite>
+                            <sp:IncludeTimestamp />
+                        </wsp:Policy>
+                    </sp:TransportBinding>
+                    <sp:EndorsingSupportingTokens>
+                        <wsp:Policy>
+                            <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                                <wsp:Policy>
+                                    <sp:WssGssKerberosV5ApReqToken11 />
+                                </wsp:Policy>
+                            </sp:KerberosToken>
+                        </wsp:Policy>
+                    </sp:EndorsingSupportingTokens>
+                    <sp:Wss11>
+                        <wsp:Policy />
+                    </sp:Wss11>
+                    <wsaw:UsingAddressing />
+                    
+                    <rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
+                        <rampart:user>alice</rampart:user>
+                        <rampart:passwordCallbackClass>org.apache.rampart.PWCallback</rampart:passwordCallbackClass>
+                        
+                        <rampart:kerberosConfig>
+                            <rampart:jaasContext>KerberosOverTransportPWCB</rampart:jaasContext>
+                            <rampart:servicePrincipalNameForm>username</rampart:servicePrincipalNameForm>
+                            <rampart:kerberosTokenDecoderClass>org.apache.rampart.util.KerberosTokenDecoderImpl</rampart:kerberosTokenDecoderClass>
+                        </rampart:kerberosConfig>
+                    </rampart:RampartConfig>
+                </wsp:All>
+            </wsp:ExactlyOne>
+        </wsp:Policy>
+
+    </wsp:PolicyAttachment>
+
+    <!-- Configure SPN using addressingIdentity extensibility element -->
+    <parameter name="addressingIdentity">
+        <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
+            <Upn>bob@EXAMPLE.COM</Upn>
+        </Identity>
+    </parameter>
+
+</service>
diff --git a/modules/rampart-policy/pom.xml b/modules/rampart-policy/pom.xml
index 06dcc53..4655d26 100644
--- a/modules/rampart-policy/pom.xml
+++ b/modules/rampart-policy/pom.xml
@@ -43,5 +43,15 @@
             <groupId>org.apache.ws.commons.axiom</groupId>
             <artifactId>axiom-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>xmlunit</groupId>
+            <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/Constants.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/Constants.java
index 60f28f8..d2b15f2 100644
--- a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/Constants.java
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/Constants.java
@@ -201,6 +201,10 @@
     public static final String XPATH_FILTER20 = "XPathFilter20";
 
     // /////////////////////////////////////////////////////////////////////
+    
+    public final static String WSS_KERBEROS_TOKEN11 = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
+    
+    // /////////////////////////////////////////////////////////////////////
 
     public static final QName ATTR_XPATH_VERSION = new QName(SP_NS, "XPathVersion", Constants.SP_PREFIX);
     
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP11Constants.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP11Constants.java
index 24bc380..99f4f77 100644
--- a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP11Constants.java
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP11Constants.java
@@ -258,6 +258,15 @@
 
     public static final QName BODY = new QName(SP11Constants.SP_NS, "Body");
     
+    public static final QName KERBEROS_TOKEN = new QName(SP11Constants.SP_NS,
+            SPConstants.KERBEROS_TOKEN, SP11Constants.SP_PREFIX);
+
+    public static final QName REQUIRE_KERBEROS_GSS_V5_TOKEN_11 = new QName(SP11Constants.SP_NS,
+            SPConstants.REQUIRE_KERBEROS_GSS_V5_TOKEN_11, SP11Constants.SP_PREFIX);
+
+    public static final QName REQUIRE_KERBEROS_V5_TOKEN_11 = new QName(SP11Constants.SP_NS,
+            SPConstants.REQUIRE_KERBEROS_V5_TOKEN_11, SP11Constants.SP_PREFIX);
+    
     public static int getInclusionFromAttributeValue(String value ) {
         
         if (INCLUDE_ALWAYS.equals(value)) {
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP12Constants.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP12Constants.java
index 9cc040d..ff7e0d9 100644
--- a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP12Constants.java
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SP12Constants.java
@@ -317,6 +317,15 @@
     
     ////////////////////////////////////////////////////////////////////////////////////////////////
     
+    public static final QName KERBEROS_TOKEN = new QName(SP12Constants.SP_NS,
+            SPConstants.KERBEROS_TOKEN, SP12Constants.SP_PREFIX);
+
+    public static final QName REQUIRE_KERBEROS_GSS_V5_TOKEN_11 = new QName(SP12Constants.SP_NS,
+            SPConstants.REQUIRE_KERBEROS_GSS_V5_TOKEN_11, SP12Constants.SP_PREFIX);
+
+    public static final QName REQUIRE_KERBEROS_V5_TOKEN_11 = new QName(SP12Constants.SP_NS,
+            SPConstants.REQUIRE_KERBEROS_V5_TOKEN_11, SP12Constants.SP_PREFIX);
+    
     public static int getInclusionFromAttributeValue(String value ) {
         
         if (INCLUDE_ALWAYS.equals(value)) {
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SPConstants.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SPConstants.java
index dd834e7..1ca64db 100755
--- a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SPConstants.java
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/SPConstants.java
@@ -131,6 +131,7 @@
     
     public final static String USERNAME_TOKEN11 = "WssUsernameToken11";
 
+    public final static String KERBEROS_TOKEN = "KerberosToken";
     
     public final static String TRANSPORT_TOKEN = "TransportToken";
     
@@ -429,7 +430,7 @@
     
     public static final String HASH_PASSWORD = "HashPassword";
     
-
+    public static final String REQUIRE_KERBEROS_V5_TOKEN_11 = "WssKerberosV5ApReqToken11";
     
-
+    public static final String REQUIRE_KERBEROS_GSS_V5_TOKEN_11 = "WssGssKerberosV5ApReqToken11";
 }
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/model/KerberosToken.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/model/KerberosToken.java
new file mode 100644
index 0000000..b0e9c93
--- /dev/null
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy/model/KerberosToken.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2001-2014 The Apache Software Foundation.
+ * 
+ * Licensed 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.ws.secpolicy.model;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.ws.secpolicy.Constants;
+import org.apache.ws.secpolicy.SP11Constants;
+import org.apache.ws.secpolicy.SP12Constants;
+import org.apache.ws.secpolicy.SPConstants;
+
+public class KerberosToken extends Token {
+
+    private boolean requiresKerberosV5Token;
+
+    private boolean requiresGssKerberosV5Token;
+
+    private boolean requiresKeyIdentifierReference;
+
+    private String tokenVersionAndType = Constants.WSS_KERBEROS_TOKEN11;
+
+    public String getTokenVersionAndType() {
+        return tokenVersionAndType;
+    }
+
+    public void setTokenVersionAndType(String tokenVersionAndType) {
+        this.tokenVersionAndType = tokenVersionAndType;
+    }
+
+    public boolean isRequiresKerberosV5Token() {
+        return requiresKerberosV5Token;
+    }
+
+    public void setRequiresKerberosV5Token(boolean requiresKerberosV5Token) {
+        this.requiresKerberosV5Token = requiresKerberosV5Token;
+    }
+
+    public boolean isRequiresGssKerberosV5Token() {
+        return requiresGssKerberosV5Token;
+    }
+
+    public void setRequiresGssKerberosV5Token(boolean requiresGssKerberosV5Token) {
+        this.requiresGssKerberosV5Token = requiresGssKerberosV5Token;
+    }
+
+    public boolean isRequiresKeyIdentifierReference() {
+        return requiresKeyIdentifierReference;
+    }
+
+    public void setRequiresKeyIdentifierReference(boolean
+        requiresKeyIdentifierReference) {
+        this.requiresKeyIdentifierReference = requiresKeyIdentifierReference;
+    }
+
+    public KerberosToken(int version) {
+        setVersion(version);
+    }
+
+    public QName getName() {
+        if (version == SPConstants.SP_V12) {
+            return SP12Constants.KERBEROS_TOKEN;
+        } 
+        else {
+            return SP11Constants.KERBEROS_TOKEN;
+        }
+    }
+
+    public void serialize(XMLStreamWriter writer) throws XMLStreamException {
+        String localName = getName().getLocalPart();
+        String namespaceURI = getName().getNamespaceURI();
+
+        String prefix = writer.getPrefix(namespaceURI);
+
+        if (prefix == null) {
+            prefix = getName().getPrefix();
+            writer.setPrefix(prefix, namespaceURI);
+        }
+
+        // <sp:KerberosToken>
+        writer.writeStartElement(prefix, localName, namespaceURI);
+
+        String inclusion;
+
+        if (version == SPConstants.SP_V12) {
+            inclusion = SP12Constants.getAttributeValueFromInclusion(getInclusion());
+        } else {
+            inclusion = SP11Constants.getAttributeValueFromInclusion(getInclusion());
+        }
+
+        if (inclusion != null) {
+            writer.writeAttribute(prefix, namespaceURI,
+                                  SPConstants.ATTR_INCLUDE_TOKEN, inclusion);
+        }
+
+        String pPrefix = writer.getPrefix(SPConstants.POLICY.getNamespaceURI());
+        if (pPrefix == null) {
+            pPrefix = SPConstants.POLICY.getPrefix();
+            writer.setPrefix(pPrefix, SPConstants.POLICY.getNamespaceURI());
+        }
+
+        // <wsp:Policy>
+        writer.writeStartElement(pPrefix, SPConstants.POLICY.getLocalPart(),
+                                 SPConstants.POLICY.getNamespaceURI());
+
+        if (isRequiresKerberosV5Token()) {
+            // <sp:WssKerberosV5ApReqToken11 />
+            writer.writeStartElement(prefix,SPConstants.REQUIRE_KERBEROS_V5_TOKEN_11,
+                                     namespaceURI);
+            writer.writeEndElement();
+        }
+
+        if (isRequiresGssKerberosV5Token()) {
+            // <sp:WssGssKerberosV5ApReqToken11 ... />
+            writer.writeStartElement(prefix,
+                                     SPConstants.REQUIRE_KERBEROS_GSS_V5_TOKEN_11,
+                                     namespaceURI);
+            writer.writeEndElement();
+        }
+
+        if (isRequiresKeyIdentifierReference()) {
+            // <sp:RequireKeyIdentifierReference />
+            writer.writeStartElement(prefix,
+                                     SPConstants.REQUIRE_KEY_IDENTIFIRE_REFERENCE,
+                                     namespaceURI);
+            writer.writeEndElement();
+        }
+
+        // </wsp:Policy>
+        writer.writeEndElement();
+
+        // </sp:KerberosToken>
+        writer.writeEndElement();
+    }
+}
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy11/builders/KerberosTokenBuilder.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy11/builders/KerberosTokenBuilder.java
new file mode 100644
index 0000000..837fce5
--- /dev/null
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy11/builders/KerberosTokenBuilder.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2001-2014 The Apache Software Foundation.
+ * 
+ * Licensed 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.ws.secpolicy11.builders;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMElement;
+import org.apache.neethi.Assertion;
+import org.apache.neethi.AssertionBuilderFactory;
+import org.apache.neethi.Policy;
+import org.apache.neethi.PolicyEngine;
+import org.apache.neethi.builders.AssertionBuilder;
+import org.apache.ws.secpolicy.SP11Constants;
+import org.apache.ws.secpolicy.SPConstants;
+import org.apache.ws.secpolicy.model.KerberosToken;
+
+/**
+ * Builder for {@link KerberosToken} assertion (WS Security Policy version 1.1)
+ */
+public class KerberosTokenBuilder implements AssertionBuilder<OMElement> {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.neethi.builders.AssertionBuilder#build(java.lang.Object,
+     * org.apache.neethi.AssertionBuilderFactory)
+     */
+    public Assertion build(OMElement element, AssertionBuilderFactory arg1) 
+            throws IllegalArgumentException {
+        KerberosToken kerberosToken = new KerberosToken(SPConstants.SP_V11);
+
+        OMElement policyElement = element.getFirstElement();
+
+        // Process token inclusion
+        OMAttribute includeAttr = element.getAttribute(SP11Constants.INCLUDE_TOKEN);
+
+        if (includeAttr != null) {
+            int inclusion = SP11Constants.getInclusionFromAttributeValue(
+                                  includeAttr.getAttributeValue());
+            kerberosToken.setInclusion(inclusion);
+        }
+
+        if (policyElement != null) {
+            Policy policy = PolicyEngine.getPolicy(element.getFirstElement());
+            policy = (Policy) policy.normalize(false);
+            for (Iterator iterator = policy.getAlternatives(); iterator.hasNext();) {
+                processAlternative((List) iterator.next(), kerberosToken);
+                 // there should be only one alternative
+                break;
+            }
+        }
+        return kerberosToken;
+    }
+
+    private void processAlternative(List assertions, KerberosToken parent) {
+        Assertion assertion;
+        QName name;
+
+        for (Iterator iterator = assertions.iterator(); iterator.hasNext();) {
+            assertion = (Assertion) iterator.next();
+            name = assertion.getName();
+            if (SP11Constants.REQUIRE_KERBEROS_V5_TOKEN_11.equals(name)) {
+                parent.setRequiresKerberosV5Token(true);
+            } else if (SP11Constants.REQUIRE_KERBEROS_GSS_V5_TOKEN_11.equals(name)) {
+                parent.setRequiresGssKerberosV5Token(true);
+            } else if (SP11Constants.REQUIRE_KEY_IDENTIFIRE_REFERENCE.equals(name)) {
+                parent.setRequiresKeyIdentifierReference(true);
+            }
+        }
+    }
+
+    public QName[] getKnownElements() {
+        return new QName[] { SP11Constants.KERBEROS_TOKEN };
+    }
+}
diff --git a/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy12/builders/KerberosTokenBuilder.java b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy12/builders/KerberosTokenBuilder.java
new file mode 100644
index 0000000..7b285e4
--- /dev/null
+++ b/modules/rampart-policy/src/main/java/org/apache/ws/secpolicy12/builders/KerberosTokenBuilder.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2001-2014 The Apache Software Foundation.
+ * 
+ * Licensed 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.ws.secpolicy12.builders;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.axiom.om.OMAttribute;
+import org.apache.axiom.om.OMElement;
+import org.apache.neethi.Assertion;
+import org.apache.neethi.AssertionBuilderFactory;
+import org.apache.neethi.Policy;
+import org.apache.neethi.PolicyEngine;
+import org.apache.neethi.builders.AssertionBuilder;
+import org.apache.ws.secpolicy.SP12Constants;
+import org.apache.ws.secpolicy.SPConstants;
+import org.apache.ws.secpolicy.model.KerberosToken;
+
+/**
+ * Builder for {@link KerberosToken} assertion (WS Security Policy version 1.2)
+ */
+public class KerberosTokenBuilder implements AssertionBuilder<OMElement> {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.neethi.builders.AssertionBuilder#build(java.lang.Object,
+     * org.apache.neethi.AssertionBuilderFactory)
+     */
+    public Assertion build(OMElement element, AssertionBuilderFactory arg1) 
+            throws IllegalArgumentException {
+        KerberosToken kerberosToken = new KerberosToken(SPConstants.SP_V12);
+
+        OMElement policyElement = element.getFirstElement();
+
+        // Process token inclusion
+        OMAttribute includeAttr = element.getAttribute(SP12Constants.INCLUDE_TOKEN);
+
+        if (includeAttr != null) {
+            int inclusion = SP12Constants.getInclusionFromAttributeValue(
+                                  includeAttr.getAttributeValue());
+            kerberosToken.setInclusion(inclusion);
+        }
+
+        if (policyElement != null) {
+            Policy policy = PolicyEngine.getPolicy(element.getFirstElement());
+            policy = (Policy) policy.normalize(false);
+            for (Iterator iterator = policy.getAlternatives(); iterator.hasNext();) {
+                processAlternative((List) iterator.next(), kerberosToken);
+                 // there should be only one alternative
+                break;
+            }
+        }
+        return kerberosToken;
+    }
+
+    private void processAlternative(List assertions, KerberosToken parent) {
+        Assertion assertion;
+        QName name;
+
+        for (Iterator iterator = assertions.iterator(); iterator.hasNext();) {
+            assertion = (Assertion) iterator.next();
+            name = assertion.getName();
+            if (SP12Constants.REQUIRE_KERBEROS_V5_TOKEN_11.equals(name)) {
+                parent.setRequiresKerberosV5Token(true);
+            } else if (SP12Constants.REQUIRE_KERBEROS_GSS_V5_TOKEN_11.equals(name)) {
+                parent.setRequiresGssKerberosV5Token(true);
+            } else if (SP12Constants.REQUIRE_KEY_IDENTIFIRE_REFERENCE.equals(name)) {
+                parent.setRequiresKeyIdentifierReference(true);
+            }
+        }
+    }
+
+    public QName[] getKnownElements() {
+        return new QName[] { SP12Constants.KERBEROS_TOKEN };
+    }
+}
diff --git a/modules/rampart-policy/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder b/modules/rampart-policy/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
index ecd3c9a..4201a92 100644
--- a/modules/rampart-policy/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
+++ b/modules/rampart-policy/src/main/resources/META-INF/services/org.apache.neethi.builders.AssertionBuilder
@@ -23,6 +23,7 @@
 org.apache.ws.secpolicy11.builders.RequiredElementsBuilder
 org.apache.ws.secpolicy11.builders.SignatureTokenBuilder
 org.apache.ws.secpolicy11.builders.EncryptionTokenBuilder
+org.apache.ws.secpolicy11.builders.KerberosTokenBuilder
 org.apache.ws.secpolicy12.builders.AlgorithmSuiteBuilder
 org.apache.ws.secpolicy12.builders.AsymmetricBindingBuilder
 org.apache.ws.secpolicy12.builders.EncryptedElementsBuilder
@@ -49,4 +50,5 @@
 org.apache.ws.secpolicy12.builders.ContentEncryptedElementsBuilder
 org.apache.ws.secpolicy12.builders.HttpsTokenBuilder
 org.apache.ws.secpolicy12.builders.SignatureTokenBuilder
-org.apache.ws.secpolicy12.builders.EncryptionTokenBuilder
\ No newline at end of file
+org.apache.ws.secpolicy12.builders.EncryptionTokenBuilder
+org.apache.ws.secpolicy12.builders.KerberosTokenBuilder
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/java/org/apache/ws/secpolicy/KerberosPolicyTest.java b/modules/rampart-policy/src/test/java/org/apache/ws/secpolicy/KerberosPolicyTest.java
new file mode 100644
index 0000000..74da398
--- /dev/null
+++ b/modules/rampart-policy/src/test/java/org/apache/ws/secpolicy/KerberosPolicyTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.ws.secpolicy;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import junit.framework.TestCase;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.OMXMLBuilderFactory;
+import org.apache.axiom.om.OMXMLParserWrapper;
+import org.apache.neethi.All;
+import org.apache.neethi.Assertion;
+import org.apache.neethi.ExactlyOne;
+import org.apache.neethi.Policy;
+import org.apache.neethi.PolicyComponent;
+import org.apache.neethi.PolicyEngine;
+import org.apache.ws.secpolicy.model.KerberosToken;
+import org.apache.ws.secpolicy.model.SupportingToken;
+import org.apache.ws.secpolicy.model.Token;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.xml.sax.SAXException;
+
+/**
+ * Tests building and serialization of {@link KerberosToken} assertion.
+ */
+public class KerberosPolicyTest extends TestCase {
+    private boolean isXmlUnitIgnoreWhitespace;
+
+    @Override
+    protected void setUp() throws Exception {
+        isXmlUnitIgnoreWhitespace = XMLUnit.getIgnoreWhitespace();
+        XMLUnit.setIgnoreWhitespace(true);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        XMLUnit.setIgnoreWhitespace(isXmlUnitIgnoreWhitespace);
+    }
+    
+    public void testKerberosGssKeyRefPolicy11() throws Exception {
+        System.out.println(getName());
+        File policyFile = new File("src/test/resources/policy/kerberos-gss-keyref-11.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP11Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP11Constants.KERBEROS_TOKEN, true, true, false);
+        assertPolicyEquals(policyFile, policy);
+    }
+
+    public void testKerberosGssPolicy11() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-gss-11.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP11Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP11Constants.KERBEROS_TOKEN, false, true, false);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    public void testKerberosKeyRefPolicy11() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-keyref-11.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP11Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP11Constants.KERBEROS_TOKEN, true, false, true);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    public void testKerberosPolicy11() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-11.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP11Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP11Constants.KERBEROS_TOKEN, false, false, true);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    public void testKerberosGssKeyRefPolicy12() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-gss-keyref-12.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP12Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP12Constants.KERBEROS_TOKEN, true, true, false);
+        assertPolicyEquals(policyFile, policy);
+    }
+
+    public void testKerberosGssPolicy12() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-gss-12.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP12Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP12Constants.KERBEROS_TOKEN, false, true, false);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    public void testKerberosKeyRefPolicy12() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-keyref-12.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP12Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP12Constants.KERBEROS_TOKEN, true, false, true);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    public void testKerberosPolicy12() throws Exception {
+        File policyFile = new File("src/test/resources/policy/kerberos-12.xml");
+        Policy policy = loadPolicy(policyFile);
+        KerberosToken kerberosToken = getKerberosEndorsingSupportingToken(policyFile, policy, SP12Constants.SP_NS);
+        assertKerberosTokenMatches(kerberosToken, SP12Constants.KERBEROS_TOKEN, false, false, true);
+        assertPolicyEquals(policyFile, policy);
+    }
+    
+    private KerberosToken getKerberosEndorsingSupportingToken(File policyFile, Policy policy, String namespace) throws XMLStreamException {
+        ExactlyOne exactlyOne = (ExactlyOne) policy.getAssertions().get(0);
+        All all = (All) exactlyOne.getFirstPolicyComponent();
+        List<PolicyComponent> assertions = all.getAssertions();
+        
+        QName endSuppTokens = new QName(namespace, SPConstants.ENDORSING_SUPPORTING_TOKENS);
+        SupportingToken endorsingSupportingTokens = (SupportingToken) findAssertion(assertions, endSuppTokens);
+        assertNotNull(String.format("Cannot find any '%s' assertion in policy: %s", endSuppTokens, printPolicy(policy)), endorsingSupportingTokens);
+        
+        ArrayList<Token> supportingTokens = endorsingSupportingTokens.getTokens();
+        assertTrue(String.format("Cannot find any supporting tokens in policy: %s", printPolicy(policy)), supportingTokens.size() > 0);
+
+        KerberosToken kerberosToken = findKerberosToken(supportingTokens);
+        assertNotNull(String.format("Cannot find any Kerberos token in policy: %s", printPolicy(policy)), kerberosToken);
+        
+        return kerberosToken;
+    }
+    
+    private void assertKerberosTokenMatches(KerberosToken kerberosToken, QName expectedName, boolean requiresKeyIdentifierRef,
+        boolean requiresGssKerberosV5, boolean requiresKerberosV5) {
+        assertTrue(String.format("Expected KerberosToken '%s' but got: %s", expectedName, kerberosToken.getName()),
+            expectedName.equals(kerberosToken.getName()));
+        assertEquals("Expected Kerberos token that must be included once.", SPConstants.INCLUDE_TOKEN_ONCE, kerberosToken.getInclusion());
+        assertEquals("Expected KerberosToken that " + (requiresKeyIdentifierRef ? "requires" : "does NOT require") + " key identifier reference",
+            requiresKeyIdentifierRef, kerberosToken.isRequiresKeyIdentifierReference());
+        assertEquals("Expected KerberosToken that " + (requiresGssKerberosV5 ? "requires" : "does NOT require") + " GSS-API KerberosV5 mechanism token", 
+            requiresGssKerberosV5, kerberosToken.isRequiresGssKerberosV5Token());
+        assertEquals("Expected KerberosToken that " + (requiresGssKerberosV5 ? "requires" : "does NOT require") + " KerberosV5 mechanism token", 
+            requiresKerberosV5, kerberosToken.isRequiresKerberosV5Token());
+    }
+    
+    private void assertPolicyEquals(File expected, Policy actual) throws IOException, XMLStreamException, SAXException {
+        StringWriter writer = new StringWriter();
+        serializePolicy(actual, writer);
+        
+        XMLAssert.assertXMLEqual(String.format("Serialized policy '%s' differs from control policy '%s'", writer.toString(), printPolicy(actual)),
+            new FileReader(expected), new StringReader(writer.toString()));
+    }
+    
+    private Policy loadPolicy(File file) throws IOException {
+        FileReader reader = null;
+        try {
+            reader = new FileReader(file);
+            OMXMLParserWrapper builder = OMXMLBuilderFactory.createOMBuilder(reader);
+            OMElement policyElement = builder.getDocumentElement();
+            return PolicyEngine.getPolicy(policyElement);
+        }
+        finally {
+            if (reader != null) {
+                reader.close();
+            }
+        }
+    }
+
+    private String serializePolicy(Policy policy, Writer writer) throws XMLStreamException {
+        StringWriter stringWriter = new StringWriter();
+        XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+        policy.serialize(xmlWriter);
+        xmlWriter.flush();
+        
+        return stringWriter.toString();
+    }
+    
+    private String printPolicy(Policy policy) throws XMLStreamException {
+        StringWriter writer = new StringWriter();
+        serializePolicy(policy, writer);
+        
+        return writer.toString();
+    }
+    
+    private Assertion findAssertion(List<PolicyComponent> policyComponents, QName name) {
+        for (PolicyComponent policyComponent : policyComponents) {
+            if (policyComponent instanceof Assertion && ((Assertion)policyComponent).getName().equals(name)) {
+                return (Assertion)policyComponent;
+            }
+        }
+        
+        return null;
+    }
+    
+    private KerberosToken findKerberosToken(ArrayList<Token> tokens) {
+        for (Token token : tokens) {
+            if (token instanceof KerberosToken) {
+                return (KerberosToken)token;
+            }
+        }
+        
+        return null;
+    }
+}
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-11.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-11.xml
new file mode 100644
index 0000000..2ccdde0
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-11.xml
@@ -0,0 +1,16 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+    xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssKerberosV5ApReqToken11 />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-12.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-12.xml
new file mode 100644
index 0000000..a272956
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-12.xml
@@ -0,0 +1,16 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssKerberosV5ApReqToken11 />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-gss-11.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-11.xml
new file mode 100644
index 0000000..c947931
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-11.xml
@@ -0,0 +1,16 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+    xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssGssKerberosV5ApReqToken11 />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-gss-12.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-12.xml
new file mode 100644
index 0000000..9998a48
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-12.xml
@@ -0,0 +1,16 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssGssKerberosV5ApReqToken11 />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-11.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-11.xml
new file mode 100644
index 0000000..9b70e3f
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-11.xml
@@ -0,0 +1,18 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
+    xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken
+                        sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssGssKerberosV5ApReqToken11 />
+                            <sp:RequireKeyIdentifierReference />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-12.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-12.xml
new file mode 100644
index 0000000..a8474ae
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-gss-keyref-12.xml
@@ -0,0 +1,17 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
+    xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssGssKerberosV5ApReqToken11 />
+                            <sp:RequireKeyIdentifierReference />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-11.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-11.xml
new file mode 100644
index 0000000..6d0322a
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-11.xml
@@ -0,0 +1,17 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+   xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssKerberosV5ApReqToken11 />
+                            <sp:RequireKeyIdentifierReference />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-12.xml b/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-12.xml
new file mode 100644
index 0000000..6bf4ba6
--- /dev/null
+++ b/modules/rampart-policy/src/test/resources/policy/kerberos-keyref-12.xml
@@ -0,0 +1,17 @@
+<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" 
+   xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
+    <wsp:ExactlyOne>
+        <wsp:All>
+            <sp:EndorsingSupportingTokens>
+                <wsp:Policy>
+                    <sp:KerberosToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Once">
+                        <wsp:Policy>
+                            <sp:WssKerberosV5ApReqToken11 />
+                            <sp:RequireKeyIdentifierReference />
+                        </wsp:Policy>
+                    </sp:KerberosToken>
+                </wsp:Policy>
+            </sp:EndorsingSupportingTokens>
+        </wsp:All>
+    </wsp:ExactlyOne>
+</wsp:Policy>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index b7bc0d0..d89871d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -496,6 +496,10 @@
                         <groupId>org.slf4j</groupId>
                         <artifactId>log4j-over-slf4j</artifactId>
                     </exclusion>
+                    <exclusion>
+                        <groupId>org.bouncycastle</groupId>
+                        <artifactId>bcprov-jdk15</artifactId>
+                    </exclusion>
                 </exclusions>
             </dependency>
             
@@ -545,6 +549,11 @@
                 <artifactId>junit</artifactId>
                 <version>4.12</version>
             </dependency>
+            <dependency>
+                <groupId>xmlunit</groupId>
+                <artifactId>xmlunit</artifactId>
+                <version>1.5</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>