org.ojbc.util.camel.security.saml.GFIPM_SAML2ComponentBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.ojbc.util.camel.security.saml.GFIPM_SAML2ComponentBuilder.java

Source

/*
 * Unless explicitly acquired and licensed from Licensor under another license, the contents of
 * this file are subject to the Reciprocal Public License ("RPL") Version 1.5, or subsequent
 * versions as allowed by the RPL, and You may not copy or use this file in either source code
 * or executable form, except in compliance with the terms and conditions of the RPL
 *
 * All software distributed under the RPL is provided strictly on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND LICENSOR HEREBY DISCLAIMS ALL SUCH
 * WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the RPL for specific language
 * governing rights and limitations under the RPL.
 *
 * http://opensource.org/licenses/RPL-1.5
 *
 * Copyright 2012-2015 Open Justice Broker Consortium
 */
package org.ojbc.util.camel.security.saml;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.common.util.StringUtils;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.bean.AudienceRestrictionBean;
import org.apache.wss4j.common.saml.bean.SubjectBean;
import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean;
import org.apache.wss4j.common.saml.builder.SAML2ComponentBuilder;
import org.apache.wss4j.common.saml.builder.SAML2Constants;
import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.saml2.core.AudienceRestriction;
import org.opensaml.saml2.core.Condition;
import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.SubjectConfirmation;
import org.opensaml.saml2.core.SubjectConfirmationData;
import org.opensaml.samlext.saml2delrestrict.Delegate;
import org.opensaml.samlext.saml2delrestrict.DelegationRestrictionType;
import org.opensaml.xml.XMLObjectBuilderFactory;

public class GFIPM_SAML2ComponentBuilder {

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

    private static SAMLObjectBuilder<DelegationRestrictionType> delegationRestrictionBuilder;
    private static SAMLObjectBuilder<Delegate> delegateBuilder;
    private static SAMLObjectBuilder<Conditions> conditionsBuilder;
    private static XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
    private static SAMLObjectBuilder<Subject> subjectBuilder;

    /**
     * Create an AudienceRestriction object
     * Use provided SAML2 Component Builder
     *
     * @param audienceURI of type String
     * @return an AudienceRestriction object
     */
    public static AudienceRestriction createAudienceRestriction(String audienceURI) {

        AudienceRestrictionBean arBean = new AudienceRestrictionBean();

        List<String> audList = new ArrayList<String>();

        audList.add(audienceURI);
        arBean.setAudienceURIs(audList);

        return SAML2ComponentBuilder.createAudienceRestriction(arBean);
    }

    /**
     * Create a Subject.
     *
     * @param subjectBean of type SubjectBean
     * @return a Subject
     */
    @SuppressWarnings("unchecked")
    public static Subject createSaml2Subject(String inResponseTo, String recipient, DateTime notOnOrAfter,
            String confirmationMethodStr) throws org.opensaml.xml.security.SecurityException, WSSecurityException {
        if (subjectBuilder == null) {
            subjectBuilder = (SAMLObjectBuilder<Subject>) builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);
        }
        Subject subject = subjectBuilder.buildObject();

        //NameID nameID = SAML2ComponentBuilder.createNameID(subjectBean);
        //subject.setNameID(nameID);

        SubjectConfirmationDataBean subjectConfirmationDataBean = new SubjectConfirmationDataBean();
        subjectConfirmationDataBean.setInResponseTo(inResponseTo);
        subjectConfirmationDataBean.setRecipient(recipient);
        subjectConfirmationDataBean.setNotAfter(notOnOrAfter);

        SubjectConfirmationData subjectConfData = null;
        subjectConfData = SAML2ComponentBuilder.createSubjectConfirmationData(subjectConfirmationDataBean, null);

        if (confirmationMethodStr == null) {
            confirmationMethodStr = SAML2Constants.CONF_SENDER_VOUCHES;
        }
        SubjectConfirmation subjectConfirmation = SAML2ComponentBuilder
                .createSubjectConfirmation(confirmationMethodStr, subjectConfData);

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

    /**
     * Use provided SAML2 Component Builder
     * @param method of type String
     * @param subjectConfirmationData of type SubjectConfirmationData
     * @return a SubjectConfirmation object
     */
    public static SubjectConfirmation createSubjectConfirmation(String method,
            SubjectConfirmationData subjectConfirmationData) {
        return SAML2ComponentBuilder.createSubjectConfirmation(method, subjectConfirmationData);
    }

    @SuppressWarnings("unchecked")
    private static DelegationRestrictionType createDelegateRestriction(String nameIDString,
            List<Delegate> existingDelegates) {
        if (delegationRestrictionBuilder == null) {
            delegationRestrictionBuilder = (SAMLObjectBuilder<DelegationRestrictionType>) builderFactory
                    .getBuilder(DelegationRestrictionType.TYPE_NAME);
        }
        if (delegateBuilder == null) {
            delegateBuilder = (SAMLObjectBuilder<Delegate>) builderFactory
                    .getBuilder(Delegate.DEFAULT_ELEMENT_NAME);
        }

        DelegationRestrictionType delegateRestriction = delegationRestrictionBuilder.buildObject();

        Delegate delegate = delegateBuilder.buildObject();

        DateTime delegateInstant = new DateTime();
        log.debug("Not before time: " + delegateInstant.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));

        delegate.setDelegationInstant(delegateInstant);

        NameID nameID = createNameID(nameIDString);
        delegate.setNameID(nameID);

        //If we have existing delegates, add them to the beginning of the delegate conditions statement
        //This method must detach them from their original document to add them
        if (existingDelegates != null) {
            for (Delegate existingDelegate : existingDelegates) {
                existingDelegate.detach();
                delegateRestriction.getDelegates().add(existingDelegate);
            }
        }

        delegateRestriction.getDelegates().add(delegate);

        return delegateRestriction;
    }

    /**
     * Create a NameID object
     * @param subject A String that will be the Name ID subject
     * @return NameID
     */
    private static NameID createNameID(String subject) {

        SubjectBean subjectBean = new SubjectBean(subject, null, null, null);
        return SAML2ComponentBuilder.createNameID(subjectBean);

    }

    /**
     * Create a Conditions object
     *
     * @param entityIDfromAppliesToAddress a string to create an appliesTo element from
     * @param delegateNameID a string to create a new delegate element from
     * @param existingTokenConditions existing delegates to preserve
     * @return a Conditions object
     */
    @SuppressWarnings("unchecked")
    public static Conditions createConditions(String entityIDfromAppliesToAddress, String delegateNameID,
            Conditions existingTokenConditions) throws Exception {
        if (conditionsBuilder == null) {
            conditionsBuilder = (SAMLObjectBuilder<Conditions>) builderFactory
                    .getBuilder(Conditions.DEFAULT_ELEMENT_NAME);
        }

        //Within the <Conditions> element of the assertion, add a new <Delegate> element. 
        //Within the new <Delegate> element, add a <NameID> element with a value equal to the SAML 2.0 Metadata Entity ID that appears in the GFIPM CTF 
        //for the WSC that requested the assertion.58,59
        //Also, on the new <Delegate> element, add a 'DelegationInstant' attribute containing a timestamp representing the current moment in time.
        //Assertion/Conditions
        //Modify the 'NotBefore' attribute of the <Conditions> element to contain a timestamp representing the current moment in time.
        DateTime notBefore = new DateTime();
        log.debug("Not before time: " + notBefore.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));

        //Modify the 'NotOnOrAfter' attribute of the <Conditions> element to contain a timestamp representing a moment in time that is N seconds in the future, 
        //where N represents length of time, in seconds, for which the new assertion will be valid.
        DateTime notOnOrAfter = notBefore.plusMinutes(5);
        log.debug("Not On or After time: " + notOnOrAfter.toString("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));

        Conditions conditions = conditionsBuilder.buildObject();

        conditions.setNotBefore(notBefore);
        conditions.setNotOnOrAfter(notOnOrAfter);

        if (!StringUtils.isEmpty(entityIDfromAppliesToAddress)) {
            AudienceRestriction audienceRestriction = GFIPM_SAML2ComponentBuilder
                    .createAudienceRestriction(entityIDfromAppliesToAddress);
            conditions.getAudienceRestrictions().add(audienceRestriction);
        }

        //It is possible, through a chain of SAML assertion delegations, for multiple <Delegate> elements to appear inside a <Conditions> element. 
        //When adding a new <Delegate> element, the ADS MUST NOT delete or modify any previously existing <Delegate> elements that already appear in the assertion.
        DelegationRestrictionType existingDelegateConditions = null;

        //Only one delegate condition is allowed, find and detach
        //http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-delegation-cs-01.html
        //A SAML authority MUST NOT include more than one <saml:Condition> element of this type within a <saml:Conditions> element of an assertion.
        if (existingTokenConditions != null) {
            for (Condition condition : existingTokenConditions.getConditions()) {

                String conditionSchema = condition.getSchemaType().getNamespaceURI();
                log.debug("Condition schema type: " + condition.getSchemaType().getNamespaceURI());

                if (conditionSchema.equals("urn:oasis:names:tc:SAML:2.0:conditions:delegation")) {
                    existingDelegateConditions = (DelegationRestrictionType) condition;
                    break;
                }
            }

        }

        List<Delegate> existingDelegates = null;

        if (existingDelegateConditions != null) {
            existingDelegates = existingDelegateConditions.getDelegates();
        }

        if (!StringUtils.isEmpty(delegateNameID)) {
            DelegationRestrictionType delegateRestrictions = createDelegateRestriction(delegateNameID,
                    existingDelegates);

            conditions.getConditions().add(delegateRestrictions);
        }

        return conditions;
    }

}