/*
 * Copyright 2004,2005 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.rahas.impl;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.*;
import org.apache.rahas.impl.util.*;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.common.SAMLException;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.saml2.core.*;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.io.*;
import org.opensaml.xml.schema.XSString;
import org.opensaml.xml.schema.impl.XSStringBuilder;
import org.opensaml.xml.signature.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * WS-Trust based SAML2 token issuer. This issuer will generate request security token responses with SAML2
 * assertions.
 */
public class SAML2TokenIssuer implements TokenIssuer {

    private String configParamName;

    private OMElement configElement;

    private String configFile;

    protected List<Signature> signatureList = new ArrayList<Signature>();

    private boolean isSymmetricKeyBasedHoK = false;

    private SAMLTokenIssuerConfig tokenIssuerConfiguration;

    private static Log log = LogFactory.getLog(SAML2TokenIssuer.class);

    /**
     * This is the main method which issues SAML2 assertions as security token responses. This method will
     * read issuer configuration and in message context properties (Basically request security token properties)
     * and will create a security token response with SAML2 assertion. The attributes are retrieved from a callback
     * class.
     * @param data A populated <code>RahasData</code> instance
     * @return A SOAP message with security token response (as per ws-trust spec) with a SAML2 assertion.
     * @throws TrustException If an error occurred while creating the response.
     */
    public SOAPEnvelope issue(RahasData data) throws TrustException {
        MessageContext inMsgCtx = data.getInMessageContext();

        this.tokenIssuerConfiguration = CommonUtil.getTokenIssuerConfiguration(this.configElement,
                this.configFile, inMsgCtx.getParameter(this.configParamName));

        if (tokenIssuerConfiguration == null) {

            if (log.isDebugEnabled()) {
                String parameterName;
                if (this.configElement != null) {
                    parameterName = "OMElement - " + this.configElement.toString();
                } else if (this.configFile != null) {
                    parameterName = "File - " + this.configFile;
                } else if (this.configParamName != null) {
                    parameterName = "With message context parameter name - " + this.configParamName;
                } else {
                    parameterName = "No method to build configurations";
                }

                log.debug("Unable to build token configurations, " + parameterName);
            }

            throw new TrustException("configurationIsNull");
        }

        SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx
                .getEnvelope().getNamespace().getNamespaceURI());

        Crypto crypto = tokenIssuerConfiguration.getIssuerCrypto(inMsgCtx
                .getAxisService().getClassLoader());

        // Get the document
        Document doc = ((Element) env).getOwnerDocument();

        // Get the key size and create a new byte array of that size
        int keySize = data.getKeySize();
        keySize = (keySize == -1) ? tokenIssuerConfiguration.getKeySize() : keySize;

        data.setKeySize(keySize);

        // Build the assertion
        Assertion assertion = buildAssertion(doc, crypto, data);

        // Sign the assertion
        Assertion signedAssertion = signAssertion(doc, assertion, crypto);

        return createRequestSecurityTokenResponse(data, signedAssertion, env);

    }

    /**
     * This method prepares the final response. This method will create a request security token response as
     * specified in WS-Trust specification. The equivalent XML would take following format,
     * <pre>  &lt;wst:RequestSecurityTokenResponse xmlns:wst="..."&gt;
     *       &lt;wst:TokenType&gt;...&lt;/wst:TokenType&gt;
     *       &lt;wst:RequestedSecurityToken&gt;...&lt;/wst:RequestedSecurityToken&gt;
     *       ...
     *       &lt;wsp:AppliesTo xmlns:wsp="..."&gt;...&lt;/wsp:AppliesTo&gt;
     *       &lt;wst:RequestedAttachedReference&gt;
     *       ...
     *       &lt;/wst:RequestedAttachedReference&gt;
     *       &lt;wst:RequestedUnattachedReference&gt;
     *       ...
     *       &lt;/wst:RequestedUnattachedReference&gt;
     *       &lt;wst:RequestedProofToken&gt;...&lt;/wst:RequestedProofToken&gt;
     *       &lt;wst:Entropy&gt;
     *       &lt;wst:BinarySecret&gt;...&lt;/wst:BinarySecret&gt;
     *       &lt;/wst:Entropy&gt;
     *       &lt;wst:Lifetime&gt;...&lt;/wst:Lifetime&gt;
     *   &lt;/wst:RequestSecurityTokenResponse&gt;</pre>
     *
     *   Thus the RequestedSecurityToken will have SAML2 assertion passed.
     * @param rahasData The configuration data which comes with RST
     * @param assertion OpenSAM representation of SAML2 assertion.
     * @param soapEnvelope SOAP message envelope
     * @return SOAPEnvelope which includes RequestSecurityTokenResponse
     * @throws TrustException If an error occurred while creating RequestSecurityTokenResponse.
     */
    protected SOAPEnvelope createRequestSecurityTokenResponse(RahasData rahasData,
                                                      Assertion assertion,
                                                      SOAPEnvelope soapEnvelope) throws TrustException {

        OMElement requestSecurityTokenResponse;
        int wstVersion = rahasData.getVersion();
        if (RahasConstants.VERSION_05_02 == wstVersion) {
            requestSecurityTokenResponse = TrustUtil.createRequestSecurityTokenResponseElement(
                    wstVersion, soapEnvelope.getBody());
        } else {
            OMElement requestSecurityTokenResponseCollectionElement = TrustUtil
                    .createRequestSecurityTokenResponseCollectionElement(
                            wstVersion, soapEnvelope.getBody());
            requestSecurityTokenResponse = TrustUtil.createRequestSecurityTokenResponseElement(
                    wstVersion, requestSecurityTokenResponseCollectionElement);
        }

        TrustUtil.createTokenTypeElement(wstVersion, requestSecurityTokenResponse).setText(
                RahasConstants.TOK_TYPE_SAML_20);

        if (rahasData.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {
            TrustUtil.createKeySizeElement(wstVersion, requestSecurityTokenResponse, rahasData.getKeySize());
        }

        if (tokenIssuerConfiguration.isAddRequestedAttachedRef()) {
            TrustUtil.createRequestedAttachedRef(wstVersion, requestSecurityTokenResponse, "#"
                    + assertion.getID(), RahasConstants.TOK_TYPE_SAML_20);
        }

        if (tokenIssuerConfiguration.isAddRequestedUnattachedRef()) {
            TrustUtil.createRequestedUnattachedRef(wstVersion, requestSecurityTokenResponse,
                    assertion.getID(), RahasConstants.TOK_TYPE_SAML_20);
        }

        if (rahasData.getAppliesToAddress() != null) {
            TrustUtil.createAppliesToElement(requestSecurityTokenResponse, rahasData
                    .getAppliesToAddress(), rahasData.getAddressingNs());
        }

        // Use GMT time in milliseconds
        DateFormat xmlSchemaDateFormat = new XmlSchemaDateFormat();

        // Add the Lifetime element
        TrustUtil.createLifetimeElement(wstVersion, requestSecurityTokenResponse, xmlSchemaDateFormat
                .format(rahasData.getAssertionCreatedDate()),
                xmlSchemaDateFormat.format(rahasData.getAssertionExpiringDate()));

        // Create the RequestedSecurityToken element and add the SAML token
        // to it
        OMElement requestedSecurityTokenElement = TrustUtil
                .createRequestedSecurityTokenElement(wstVersion, requestSecurityTokenResponse);

        Element assertionElement = assertion.getDOM();

        requestedSecurityTokenElement.addChild((OMNode)assertionElement);

        // Store the token
        Token assertionToken = new Token(assertion.getID(),
                (OMElement) assertionElement, rahasData.getAssertionCreatedDate(),
                rahasData.getAssertionExpiringDate());

        // At this point we definitely have the secret
        // Otherwise it should fail with an exception earlier
        assertionToken.setSecret(rahasData.getEphmeralKey());
        TrustUtil.getTokenStore(rahasData.getInMessageContext()).add(assertionToken);

        if (rahasData.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)
                && tokenIssuerConfiguration.getKeyComputation()
                != SAMLTokenIssuerConfig.KeyComputation.KEY_COMP_USE_REQ_ENT) {

            Document doc = ((Element) soapEnvelope).getOwnerDocument();

            // Add the RequestedProofToken
            TokenIssuerUtil.handleRequestedProofToken(rahasData, wstVersion,
                    tokenIssuerConfiguration,
                    requestSecurityTokenResponse, assertionToken, doc);
        }

        return soapEnvelope;

    }

    /**
     * This methods builds the SAML2 assertion. The equivalent XML would look as follows,
     * <pre>&lt;saml:Assertion
     *      xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
     *      xmlns:xs="http://www.w3.org/2001/XMLSchema"
     *      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     *      ID="b07b804c-7c29-ea16-7300-4f3d6f7928ac"
     *      Version="2.0"
     *      IssueInstant="2004-12-05T09:22:05Z"&gt;
     *      &lt;saml:Issuer&gt;https://idp.example.org/SAML2&lt;/saml:Issuer&gt;
     *      &lt;ds:Signature
     *        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&gt;...&lt;/ds:Signature&gt;
     *      &lt;saml:Subject&gt;
     *        &lt;saml:NameID
     *          Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"&gt;
     *          3f7b3dcf-1674-4ecd-92c8-1544f346baf8
     *        &lt;/saml:NameID&gt;
     *        &lt;saml:SubjectConfirmation
     *          Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"&gt;
     *          &lt;saml:SubjectConfirmationData
     *            InResponseTo="aaf23196-1773-2113-474a-fe114412ab72"
     *            Recipient="https://sp.example.com/SAML2/SSO/POST"
     *            NotOnOrAfter="2004-12-05T09:27:05Z"/&gt;
     *        &lt;/saml:SubjectConfirmation&gt;
     *      &lt;/saml:Subject&gt;
     *      &lt;saml:Conditions
     *        NotBefore="2004-12-05T09:17:05Z"
     *        NotOnOrAfter="2004-12-05T09:27:05Z"&gt;
     *        &lt;saml:AudienceRestriction&gt;
     *          &lt;saml:Audience&gt;https://sp.example.com/SAML2&lt;/saml:Audience&gt;
     *        &lt;/saml:AudienceRestriction&gt;
     *      &lt;/saml:Conditions&gt;
     *      &lt;saml:AuthnStatement
     *        AuthnInstant="2004-12-05T09:22:00Z"
     *        SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac"&gt;
     *        &lt;saml:AuthnContext&gt;
     *          &lt;saml:AuthnContextClassRef&gt;
     *            urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
     *         &lt;/saml:AuthnContextClassRef&gt;
     *        &lt;/saml:AuthnContext&gt;
     *      &lt;/saml:AuthnStatement&gt;
     *      &lt;saml:AttributeStatement&gt;
     *        &lt;saml:Attribute
     *          xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
     *          x500:Encoding="LDAP"
     *          NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
     *          Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
     *          FriendlyName="eduPersonAffiliation"&gt;
     *          &lt;saml:AttributeValue
     *            xsi:type="xs:string"&gt;member&lt;/saml:AttributeValue&gt;
     *          &lt;saml:AttributeValue
     *            xsi:type="xs:string"&gt;staff&lt;/saml:AttributeValue&gt;
     *        &lt;/saml:Attribute&gt;
     *      &lt;/saml:AttributeStatement&gt;
     *    &lt;/saml:Assertion&gt;</pre>
     *
     *    Reference - en.wikipedia.org/wiki/SAML_2.0#SAML_2.0_Assertions
     * @param doc The Document which comprises SAML 2 assertion.
     * @param crypto Crypto properties.
     * @param data The RST data and other configuration information.
     * @return OpenSAML representation of an Assertion.
     * @throws TrustException If an error occurred while creating the Assertion.
     */
    protected Assertion buildAssertion(Document doc, Crypto crypto, RahasData data) throws TrustException {
        //Build the assertion
        Assertion assertion = SAML2Utils.createAssertion();

        Issuer issuer = SAML2Utils.createIssuer(this.tokenIssuerConfiguration.getIssuerName());
        assertion.setIssuer(issuer);

        // Validity period
        DateTime creationDate = new DateTime();
        DateTime expirationDate = new DateTime(creationDate.getMillis() + tokenIssuerConfiguration.getTtl());

        data.setAssertionCreatedDate(creationDate.toDate());
        data.setAssertionExpiringDate(expirationDate.toDate());

        // Set the issued time.
        assertion.setIssueInstant(creationDate);

        // These variables are used to build the trust assertion
        Conditions conditions = SAML2Utils.createConditions(creationDate, expirationDate);
        assertion.setConditions(conditions);

        // Create the subject
        Subject subject;

        if (!data.getKeyType().endsWith(RahasConstants.KEY_TYPE_BEARER)) {
            subject = createSubjectWithHolderOfKeySubjectConfirmation(doc, crypto,
                    creationDate, expirationDate, data);
        } else {
            subject = createSubjectWithBearerSubjectConfirmation(data);
        }

        // Set the subject
        assertion.setSubject(subject);

        // If a SymmetricKey is used build an attr stmt, if a public key is build an authn stmt.
        if (isSymmetricKeyBasedHoK) {
            AttributeStatement attrStmt = createAttributeStatement(data);
            assertion.getAttributeStatements().add(attrStmt);
        } else {
            AuthnStatement authStmt = createAuthenticationStatement(data);
            assertion.getAuthnStatements().add(authStmt);
            if (data.getClaimDialect() != null && data.getClaimElem() != null) {
                assertion.getAttributeStatements().add(createAttributeStatement(data));
            }
        }

        return assertion;
    }

    /**
     * This method will create a SAML 2 subject based on Holder of Key confirmation method.
     * The relevant XML would look as follows,
     * <pre>  &lt;saml2:Subject&gt;
     *       &lt;saml2:NameID&gt;
     *           ...
     *       &lt;/saml2:NameID&gt;
     *       &lt;saml2:SubjectConfirmation
     *               Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"&gt;
     *           &lt;saml2:SubjectConfirmationData
     *                   xsi:type="saml2:KeyInfoConfirmationDataType"&gt;
     *               &lt;ds:KeyInfo&gt;
     *                   &lt;ds:KeyValue&gt;...&lt;/ds:KeyValue&gt;
     *               &lt;/ds:KeyInfo&gt;
     *           &lt;/saml2:SubjectConfirmationData&gt;
     *       &lt;/saml2:SubjectConfirmation&gt;
     *   &lt;/saml2:Subject&gt;</pre>
     *
     * KeyInfo can be created based on public key or symmetric key. That is decided by looking at
     * the RahasData.getKeyType. TODO make sure this implementation is correct.
     * Theoretically we should be able to have many subject confirmation methods in a SAML2 subject.
     * TODO - Do we need to support that ?
     * @param doc The original XML document which we need to include the assertion.
     * @param crypto The relevant crypto properties
     * @param creationTime The time that assertion was created.
     * @param expirationTime The expiring time
     * @param data The configuration data relevant request.
     * @return OpenSAML representation of the SAML2 object.
     * @throws TrustException If an error occurred while creating the subject.
     */
    protected Subject createSubjectWithHolderOfKeySubjectConfirmation(Document doc, Crypto crypto,
                                                            DateTime creationTime,
                                                            DateTime expirationTime, RahasData data)
            throws TrustException {


        // Create the subject
        Subject subject = (Subject)CommonUtil.buildXMLObject(Subject.DEFAULT_ELEMENT_NAME);

        // Set the subject name identifier
        if (data.getPrincipal() != null) {
            setSubjectNamedIdentifierData(subject, data.getPrincipal().getName(), NameID.EMAIL);
        }

        // Create KeyInfo
        KeyInfo keyInfo = createKeyInfo(doc, crypto, data);

        //Build the Subject Confirmation
        SubjectConfirmation subjectConfirmation
                = (SubjectConfirmation)CommonUtil.buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME);

        //Set the subject Confirmation method
        subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key");

        //Build the subject confirmation data element
        KeyInfoConfirmationDataType scData = createKeyInfoConfirmationDataType();

        //Set the keyInfo element
        scData.getKeyInfos().add(keyInfo);

        // Set the validity period
        scData.setNotBefore(creationTime);
        scData.setNotOnOrAfter(expirationTime);

        //Set the subject confirmation data
        subjectConfirmation.setSubjectConfirmationData(scData);

        //set the subject confirmation
        subject.getSubjectConfirmations().add(subjectConfirmation);

        log.debug("SAML2.0 subject is constructed successfully.");
        return subject;
    }

    private KeyInfoConfirmationDataType createKeyInfoConfirmationDataType() {
        XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
        @SuppressWarnings({"unchecked"}) SAMLObjectBuilder<KeyInfoConfirmationDataType> keyInfoSubjectConfirmationDataBuilder =
                (SAMLObjectBuilder<KeyInfoConfirmationDataType>) builderFactory.getBuilder
                        (KeyInfoConfirmationDataType.TYPE_NAME);

        //Build the subject confirmation data element
        return keyInfoSubjectConfirmationDataBuilder.
                buildObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME, KeyInfoConfirmationDataType.TYPE_NAME);
    }

    /**
     * This method creates a subject element with the bearer subject confirmation method.
     * <pre>   &lt;saml:Subject&gt;
     *       &lt;saml:NameIdentifier
     *                   NameQualifier="www.example.com"
     *                   Format="urn:oasis:names:tc:SAML:1.1:nameid-
     *           format:X509SubjectName"&gt;
     *           uid=joe,ou=people,ou=saml-demo,o=baltimore.com
     *       &lt;/saml:NameIdentifier&gt;
     *       &lt;saml:SubjectConfirmation&gt;
     *           &lt;saml:ConfirmationMethod&gt;
     *               urn:oasis:names:tc:SAML:1.0:cm:bearer
     *           &lt;/saml:ConfirmationMethod&gt;
     *       &lt;/saml:SubjectConfirmation&gt;
     *   &lt;/saml:Subject&gt;</pre>
     * @param data RahasData element
     * @return  SAML 2.0 Subject element with Bearer subject confirmation
     * @throws org.apache.rahas.TrustException if an error occurred while creating the subject.
     */
    protected Subject createSubjectWithBearerSubjectConfirmation(RahasData data) throws TrustException {

        // Create the subject
        Subject subject = (Subject)CommonUtil.buildXMLObject(Subject.DEFAULT_ELEMENT_NAME);

        //Create NameID and attach it to the subject
        setSubjectNamedIdentifierData(subject, data.getPrincipal().getName(), NameID.EMAIL);

        //Build the Subject Confirmation
        SubjectConfirmation subjectConfirmation
                = (SubjectConfirmation)CommonUtil.buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME);

        //Set the subject Confirmation method
        subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:bearer");

        subject.getSubjectConfirmations().add(subjectConfirmation);
        return subject;
    }


    /**
     * This method signs the given assertion with issuer's private key.
     * @param document The original RST document.
     * @param assertion Assertion to be signed.
     * @param crypto  The cryptographic properties.
     * @return The signed assertion.
     * @throws TrustException If an error occurred while signing the assertion.
     */
    protected Assertion signAssertion(Document document, Assertion assertion, Crypto crypto) throws TrustException {

        // Create a SignKeyHolder to hold the crypto objects that are used to sign the assertion
        SignKeyHolder signKeyHolder = createSignKeyHolder(crypto);

        // Build the signature object and set the credentials.
        Signature signature = (Signature) CommonUtil.buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);

        signature.setSigningCredential(signKeyHolder);
        signature.setSignatureAlgorithm(signKeyHolder.getSignatureAlgorithm());
        signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

        //Build the KeyInfo element and set the certificate
        try {
            KeyInfo keyInfo = (KeyInfo) CommonUtil.buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
            X509Data x509Data = (X509Data) CommonUtil.buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
            org.opensaml.xml.signature.X509Certificate cert
                    = (org.opensaml.xml.signature.X509Certificate) CommonUtil.buildXMLObject
                    (org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);
            String value
                    = org.apache.xml.security.utils.Base64.encode(signKeyHolder.getEntityCertificate().getEncoded());

            cert.setValue(value);
            x509Data.getX509Certificates().add(cert);
            keyInfo.getX509Datas().add(x509Data);

            signature.setKeyInfo(keyInfo);
            assertion.setSignature(signature);

            signatureList.add(signature);

            //Marshall and Sign
            MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
            Marshaller marshaller = marshallerFactory.getMarshaller(assertion);
            marshaller.marshall(assertion, document);

            Signer.signObjects(signatureList);

        } catch (CertificateEncodingException e) {
            throw new TrustException("Error in setting the signature", e);
        } catch (SignatureException e) {
            throw new TrustException("errorSigningAssertion", e);
        } catch (MarshallingException e) {
            throw new TrustException("errorMarshallingAssertion", e);
        }

        log.debug("SAML2.0 assertion is marshalled and signed..");

        return assertion;
    }

    /**
     * This method is used to create SignKeyHolder instances that contains the credentials required for signing the
     * assertion
     * @param crypto The crypto properties associated with the issuer.
     * @return  SignKeyHolder object.
     * @throws TrustException  If an error occurred while creating SignKeyHolder object.
     */
    private SignKeyHolder createSignKeyHolder(Crypto crypto) throws TrustException {

        SignKeyHolder signKeyHolder = new SignKeyHolder();

        try {
            X509Certificate[] issuerCerts = CommonUtil.getCertificatesByAlias(crypto,
                    this.tokenIssuerConfiguration.getIssuerKeyAlias());

            String sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
            String pubKeyAlgo = issuerCerts[0].getPublicKey().getAlgorithm();
            if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
            }

            java.security.Key issuerPK = crypto.getPrivateKey(
                    this.tokenIssuerConfiguration.getIssuerKeyAlias(),
                    this.tokenIssuerConfiguration.getIssuerKeyPassword());

            signKeyHolder.setIssuerCerts(issuerCerts);
            signKeyHolder.setIssuerPK((PrivateKey) issuerPK);
            signKeyHolder.setSignatureAlgorithm(sigAlgo);

        } catch (Exception e) {
            throw new TrustException("Error creating issuer signature");
        }

        log.debug("SignKeyHolder object is created with the credentials..");

        return signKeyHolder;
    }

    /**
     * This method creates an AttributeStatement. The relevant XML would look like as follows,
     * <pre>  &lt;saml:AttributeStatement&gt;
     *    &lt;saml:Attribute
     *      xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
     *      x500:Encoding="LDAP"
     *      NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
     *      Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
     *      FriendlyName="eduPersonAffiliation"&gt;
     *      &lt;saml:AttributeValue
     *        xsi:type="xs:string"&gt;member&lt;/saml:AttributeValue&gt;
     *      &lt;saml:AttributeValue
     *        xsi:type="xs:string"&gt;staff&lt;/saml:AttributeValue&gt;
     *    &lt;/saml:Attribute&gt;
     *  &lt;/saml:AttributeStatement&gt;</pre>
     *  Reference -  http://en.wikipedia.org/wiki/SAML_2.0#SAML_2.0_Assertions
     * @param data The RahasData which carry information about RST.
     * @return An AttributeStatement with filled attributes retrieved by calling callback class.
     * @throws TrustException If an error occurred while creating the AttributeStatement.
     */
    protected AttributeStatement createAttributeStatement(RahasData data) throws TrustException {


        AttributeStatement attributeStatement
                = (AttributeStatement) CommonUtil.buildXMLObject(AttributeStatement.DEFAULT_ELEMENT_NAME);

        Attribute[] attributes;

        SAMLCallbackHandler handler = CommonUtil.getSAMLCallbackHandler(this.tokenIssuerConfiguration, data);

        SAMLAttributeCallback cb = new SAMLAttributeCallback(data);
        if (handler != null) {
            try {
                handler.handle(cb);
            } catch (SAMLException e) {
                throw new TrustException(
                            "errorCallingSAMLCallback",
                            e);
            }

            attributes = cb.getSAML2Attributes();
        } else { //else add the attribute with a default value

            log.debug("No callback registered to get attributes ... Using default attributes");

            // TODO do we need to remove this ?
            Attribute attribute = (Attribute) CommonUtil.buildXMLObject(Attribute.DEFAULT_ELEMENT_NAME);
            attribute.setName("Name");
            attribute.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified");

            XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();

            XSStringBuilder attributeValueBuilder = (XSStringBuilder) builderFactory
                    .getBuilder(XSString.TYPE_NAME);

            XSString stringValue = attributeValueBuilder.buildObject(
                    AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
            stringValue.setValue("Colombo/Rahas");
            attribute.getAttributeValues().add(stringValue);
            attributes = new Attribute[1];
            attributes[0] = attribute;
        }
        //add attributes to the attribute statement
        attributeStatement.getAttributes().addAll(Arrays.asList(attributes));

        log.debug("SAML2.0 attribute statement is constructed successfully.");

        return attributeStatement;
    }

    /**
     * This method creates an authentication statement. The equivalent XML would look as follows,
     * <pre>  &lt;saml:AuthnStatement
     *    AuthnInstant="2004-12-05T09:22:00Z"
     *    SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac"&gt;
     *    &lt;saml:AuthnContext&gt;
     *      &lt;saml:AuthnContextClassRef&gt;
     *        urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
     *     &lt;/saml:AuthnContextClassRef&gt;
     *    &lt;/saml:AuthnContext&gt;
     *  &lt;/saml:AuthnStatement&gt;</pre>
     * @param data The RahasData which carry information about RST.
     * @return OpenSAML representation of an AuthnStatement class.
     * @throws TrustException If an error occurred while creating the authentication statement.
     */
    protected AuthnStatement createAuthenticationStatement(RahasData data) throws TrustException {

        MessageContext inMsgCtx = data.getInMessageContext();

        //build the auth stmt
        AuthnStatement authenticationStatement
                = (AuthnStatement)CommonUtil.buildXMLObject(AuthnStatement.DEFAULT_ELEMENT_NAME);

        // set the authn instance
        // TODO do we need to use the same time as specified in the conditions ?
        authenticationStatement.setAuthnInstant(new DateTime());

        // Create authentication context
        AuthnContext authContext = (AuthnContext)CommonUtil.buildXMLObject(AuthnContext.DEFAULT_ELEMENT_NAME);

        // Create authentication context class reference
        AuthnContextClassRef authCtxClassRef
                = (AuthnContextClassRef)CommonUtil.buildXMLObject(AuthnContextClassRef.DEFAULT_ELEMENT_NAME);
        
        //if username/password based authn
        if (inMsgCtx.getProperty(RahasConstants.USERNAME) != null) {
            authCtxClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX);
        } else if (inMsgCtx.getProperty(RahasConstants.X509_CERT) != null) { //if X.509 cert based authn
            authCtxClassRef.setAuthnContextClassRef(AuthnContext.X509_AUTHN_CTX);
        }

        authContext.setAuthnContextClassRef(authCtxClassRef);
        authenticationStatement.setAuthnContext(authContext);

        log.debug("SAML2.0 authentication statement is constructed successfully.");

        return authenticationStatement;
    }

    /**
     * This method will set the subject principal details to the given subject.
     * @param subject The subject.
     * @param subjectNameId Subject name id, to identify the principal
     * @param format Format of the subjectNameId, i.e. email, x509subject etc ...
     * @throws TrustException If an error occurred while building NameID.
     */
    protected static void setSubjectNamedIdentifierData(Subject subject, String subjectNameId, String format)
            throws TrustException {

        //Create NameID and attach it to the subject
        NameID nameID = SAML2Utils.createNamedIdentifier(subjectNameId, format);
        subject.setNameID(nameID);
    }

    /**
     * This method creates the KeyInfo relevant for the assertion. The KeyInfo could be created in 2 ways.
     * 1. Using symmetric key - KeyInfo is created using a symmetric key
     * 2. Using a public key - KeyInfo created using a public key
     * The methodology is decided by looking at RahasData.getKeyType() method.
     * @param doc The document which we are processing.
     * @param crypto Includes crypto properties relevant to issuer.
     * @param data Includes metadata about the RST.
     * @return OpenSAML representation of KeyInfo.
     * @throws TrustException If an error occurred while creating the KeyInfo object.
     */
    protected KeyInfo createKeyInfo(Document doc, Crypto crypto, RahasData data)
            throws TrustException {

        KeyInfo keyInfo;

        // If it is a Symmetric Key
        if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {

            isSymmetricKeyBasedHoK = true;
            X509Certificate serviceCert = null;
            try {

                // Get AppliesTo to figure out which service to issue the token
                // for
                serviceCert = this.tokenIssuerConfiguration.getServiceCert(crypto, data.getAppliesToAddress());

                keyInfo = CommonUtil.getSymmetricKeyBasedKeyInfo(doc, data, serviceCert, data.getKeySize(), crypto,
                        tokenIssuerConfiguration.getKeyComputation());

            } catch (Exception e) {
                if (serviceCert != null) {
                    throw new TrustException(
                            "errorInBuildingTheEncryptedKeyForPrincipal",
                            new String[]{serviceCert.getSubjectDN().getName()},
                            e);
                } else {
                    throw new TrustException(
                            "errorInBuildingTheEncryptedKeyForPrincipal",
                            new String[]{"UnknownSubjectDN"},
                            e);
                }
            }

        } else if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_PUBLIC_KEY)) {    // If it is a public Key

            try {
                // Create the ds:KeyValue element with the ds:X509Data
                X509Certificate clientCert = data.getClientCert();

                if (clientCert == null) {
                    // TODO are we always looking up by alias ? Dont we need to lookup by any other attribute ?
                    clientCert = CommonUtil.getCertificateByAlias(crypto, data.getPrincipal().getName());
                }

                keyInfo = CommonUtil.getCertificateBasedKeyInfo(clientCert);

            } catch (Exception e) {
                throw new TrustException("samlAssertionCreationError", e);
            }
        } else {
            log.error("Unidentified key type " + data.getKeyType());
            throw new TrustException(
                            "unidentifiedKeyType",
                            new String[]{data.getKeyType()});
        }

        return keyInfo;

    }

    public String getResponseAction(RahasData data) throws TrustException {
        return null;
    }

    public void setConfigurationFile(String configFile) {
        this.configFile = configFile;
    }

    public void setConfigurationElement(OMElement configElement) {
        this.configElement = configElement;
    }

    public void setConfigurationParamName(String configParamName) {
        this.configParamName = configParamName;
    }

}
