at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder.java Source code

Java tutorial

Introduction

Here is the source code for at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion.PVP2AssertionBuilder.java

Source

/*******************************************************************************
 * Copyright 2014 Federal Chancellery Austria
 * MOA-ID has been developed in a cooperation between BRZ, the Federal
 * Chancellery Austria - ICT staff unit, and Graz University of Technology.
 *
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
 * the European Commission - subsequent versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at:
 * http://www.osor.eu/eupl/
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the Licence is distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the Licence for the specific language governing permissions and
 * limitations under the Licence.
 *
 * This product combines work with different licenses. See the "NOTICE" text
 * file for details on the various modules and licenses.
 * The "NOTICE" text file is part of the distribution. Any derivative works
 * that you distribute must include a readable copy of the "NOTICE" text file.
 *******************************************************************************/
package at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.joda.time.DateTime;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeQuery;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Audience;
import org.opensaml.saml2.core.AudienceRestriction;
import org.opensaml.saml2.core.AuthnContext;
import org.opensaml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.AuthnStatement;
import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.RequestedAuthnContext;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.SubjectConfirmation;
import org.opensaml.saml2.core.SubjectConfirmationData;
import org.opensaml.saml2.core.impl.AuthnRequestImpl;
import org.opensaml.saml2.metadata.AssertionConsumerService;
import org.opensaml.saml2.metadata.AttributeConsumingService;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.NameIDFormat;
import org.opensaml.saml2.metadata.RequestedAttribute;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.w3c.dom.Element;

import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate;
import at.gv.e_government.reference.namespace.persondata._20020228_.CorporateBodyType;
import at.gv.e_government.reference.namespace.persondata._20020228_.IdentificationType;
import at.gv.e_government.reference.namespace.persondata._20020228_.PhysicalPersonType;
import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;
import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.UnavailableAttributeException;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMandateDataAvailableException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.QAANotSupportedException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.UnprovideableAttributeException;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import at.gv.egovernment.moa.id.util.MandateBuilder;
import at.gv.egovernment.moa.id.util.QAALevelVerifier;
import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.MiscUtil;

public class PVP2AssertionBuilder implements PVPConstants {

    public static Assertion buildAssertion(AttributeQuery attrQuery, List<String> reqAttributes, IAuthData authData,
            DateTime date, String sessionIndex) throws ConfigurationException {

        AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class);
        authnContextClassRef.setAuthnContextClassRef(authData.getQAALevel());

        List<Attribute> attrList = new ArrayList<Attribute>();
        if (reqAttributes != null) {
            Iterator<String> it = reqAttributes.iterator();
            while (it.hasNext()) {
                String reqAttributName = it.next();
                try {
                    Attribute attr = PVPAttributeBuilder.buildAttribute(reqAttributName, null, authData);
                    if (attr == null) {
                        Logger.error("Attribute generation failed! for " + reqAttributName);

                    } else {
                        attrList.add(attr);

                    }

                } catch (PVP2Exception e) {
                    Logger.error("Attribute generation failed! for " + reqAttributName);

                } catch (Exception e) {
                    Logger.error("General Attribute generation failed! for " + reqAttributName, e);

                }
            }
        }

        NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);
        subjectNameID.setFormat(attrQuery.getSubject().getNameID().getFormat());
        subjectNameID.setValue(attrQuery.getSubject().getNameID().getValue());

        SubjectConfirmationData subjectConfirmationData = null;

        return buildGenericAssertion(attrQuery.getIssuer().getValue(), date, authnContextClassRef, attrList,
                subjectNameID, subjectConfirmationData, sessionIndex,
                new DateTime(authData.getSsoSessionValidTo().getTime()));
    }

    public static Assertion buildAssertion(AuthnRequest authnRequest, IAuthData authData,
            EntityDescriptor peerEntity, DateTime date, AssertionConsumerService assertionConsumerService,
            SLOInformationImpl sloInformation) throws MOAIDException {

        RequestedAuthnContext reqAuthnContext = authnRequest.getRequestedAuthnContext();

        AuthnContextClassRef authnContextClassRef = SAML2Utils.createSAMLObject(AuthnContextClassRef.class);

        OAAuthParameter oaParam = AuthConfigurationProvider.getInstance()
                .getOnlineApplicationParameter(peerEntity.getEntityID());

        if (reqAuthnContext == null) {
            authnContextClassRef.setAuthnContextClassRef(authData.getQAALevel());

        } else {

            boolean stork_qaa_1_4_found = false;

            List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs();

            if (reqAuthnContextClassRefIt.size() == 0) {

                QAALevelVerifier.verifyQAALevel(authData.getQAALevel(), STORK_QAA_1_4);

                stork_qaa_1_4_found = true;
                authnContextClassRef.setAuthnContextClassRef(STORK_QAA_1_4);

            } else {
                for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) {
                    String qaa_uri = authnClassRef.getAuthnContextClassRef();
                    if (qaa_uri.trim().equals(STORK_QAA_1_4) || qaa_uri.trim().equals(STORK_QAA_1_3)
                            || qaa_uri.trim().equals(STORK_QAA_1_2) || qaa_uri.trim().equals(STORK_QAA_1_1)) {

                        if (authData.isForeigner()) {
                            QAALevelVerifier.verifyQAALevel(authData.getQAALevel(),
                                    STORK_QAA_PREFIX + oaParam.getQaaLevel());

                            stork_qaa_1_4_found = true;
                            authnContextClassRef.setAuthnContextClassRef(authData.getQAALevel());

                        } else {

                            QAALevelVerifier.verifyQAALevel(authData.getQAALevel(), qaa_uri.trim());

                            stork_qaa_1_4_found = true;
                            authnContextClassRef.setAuthnContextClassRef(authData.getQAALevel());

                        }
                        break;
                    }
                }
            }

            if (!stork_qaa_1_4_found) {
                throw new QAANotSupportedException(STORK_QAA_1_4);
            }
        }

        SPSSODescriptor spSSODescriptor = peerEntity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);

        //add Attributes to Assertion
        List<Attribute> attrList = new ArrayList<Attribute>();
        if (spSSODescriptor.getAttributeConsumingServices() != null
                && spSSODescriptor.getAttributeConsumingServices().size() > 0) {

            Integer aIdx = authnRequest.getAttributeConsumingServiceIndex();
            int idx = 0;

            AttributeConsumingService attributeConsumingService = null;

            if (aIdx != null) {
                idx = aIdx.intValue();
                attributeConsumingService = spSSODescriptor.getAttributeConsumingServices().get(idx);

            } else {
                List<AttributeConsumingService> attrConsumingServiceList = spSSODescriptor
                        .getAttributeConsumingServices();
                for (AttributeConsumingService el : attrConsumingServiceList) {
                    if (el.isDefault())
                        attributeConsumingService = el;
                }
            }

            if (attributeConsumingService != null) {
                Iterator<RequestedAttribute> it = attributeConsumingService.getRequestAttributes().iterator();
                while (it.hasNext()) {
                    RequestedAttribute reqAttribut = it.next();
                    try {
                        Attribute attr = PVPAttributeBuilder.buildAttribute(reqAttribut.getName(), oaParam,
                                authData);
                        if (attr == null) {
                            if (reqAttribut.isRequired()) {
                                throw new UnprovideableAttributeException(reqAttribut.getName());
                            }
                        } else {
                            attrList.add(attr);
                        }

                    } catch (UnavailableAttributeException e) {
                        Logger.info("Attribute generation for " + reqAttribut.getFriendlyName() + " not possible.");
                        if (reqAttribut.isRequired()) {
                            throw new UnprovideableAttributeException(reqAttribut.getName());
                        }

                    } catch (PVP2Exception e) {
                        Logger.warn("Attribute generation failed! for " + reqAttribut.getFriendlyName());
                        if (reqAttribut.isRequired()) {
                            throw new UnprovideableAttributeException(reqAttribut.getName());
                        }

                    } catch (Exception e) {
                        Logger.error("General Attribute generation failed! for " + reqAttribut.getFriendlyName(),
                                e);
                        if (reqAttribut.isRequired()) {
                            throw new UnprovideableAttributeException(reqAttribut.getName());
                        }

                    }
                }
            }
        }

        NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class);

        //build nameID and nameID Format from moasession
        if (authData.isUseMandate()) {
            Element mandate = authData.getMandate();
            if (mandate == null) {
                throw new NoMandateDataAvailableException();
            }
            Mandate mandateObject = MandateBuilder.buildMandate(mandate);
            if (mandateObject == null) {
                throw new NoMandateDataAvailableException();
            }
            CorporateBodyType corporation = mandateObject.getMandator().getCorporateBody();
            PhysicalPersonType pysicalperson = mandateObject.getMandator().getPhysicalPerson();

            IdentificationType id;
            if (corporation != null && corporation.getIdentification().size() > 0)
                id = corporation.getIdentification().get(0);

            else if (pysicalperson != null && pysicalperson.getIdentification().size() > 0)
                id = pysicalperson.getIdentification().get(0);

            else {
                Logger.error("Failed to generate IdentificationType");
                throw new NoMandateDataAvailableException();
            }

            String bpktype = id.getType();
            String bpk = id.getValue().getValue();

            if (bpktype.equals(Constants.URN_PREFIX_BASEID)) {
                if (oaParam.getBusinessService()) {
                    subjectNameID
                            .setValue(new BPKBuilder().buildWBPK(bpk, oaParam.getIdentityLinkDomainIdentifier()));
                    if (oaParam.getIdentityLinkDomainIdentifier()
                            .startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
                        subjectNameID.setNameQualifier(oaParam.getIdentityLinkDomainIdentifier());
                    else
                        subjectNameID.setNameQualifier(
                                Constants.URN_PREFIX_WBPK + "+" + oaParam.getIdentityLinkDomainIdentifier());

                } else {
                    subjectNameID.setValue(new BPKBuilder().buildBPK(bpk, oaParam.getTarget()));
                    if (oaParam.getTarget().startsWith(Constants.URN_PREFIX_CDID + "+"))
                        subjectNameID.setNameQualifier(oaParam.getTarget());
                    else
                        subjectNameID.setNameQualifier(Constants.URN_PREFIX_CDID + "+" + oaParam.getTarget());
                }

            } else {
                subjectNameID.setNameQualifier(bpktype);
                subjectNameID.setValue(bpk);
            }

        } else {
            subjectNameID.setNameQualifier(authData.getBPKType());
            subjectNameID.setValue(authData.getBPK());
        }

        String nameIDFormat = NameID.TRANSIENT;

        //get NameIDFormat from request      
        AuthnRequest authnReq = (AuthnRequestImpl) authnRequest;
        if (authnReq.getNameIDPolicy() != null) {
            nameIDFormat = authnReq.getNameIDPolicy().getFormat();

        } else {
            //get NameIDFormat from metadata
            List<NameIDFormat> metadataNameIDFormats = spSSODescriptor.getNameIDFormats();

            if (metadataNameIDFormats != null) {

                for (NameIDFormat el : metadataNameIDFormats) {
                    if (NameID.PERSISTENT.equals(el.getFormat())) {
                        nameIDFormat = NameID.PERSISTENT;
                        break;

                    } else if (NameID.TRANSIENT.equals(el.getFormat()) || NameID.UNSPECIFIED.equals(el.getFormat()))
                        break;

                }
            }
        }

        if (NameID.TRANSIENT.equals(nameIDFormat) || NameID.UNSPECIFIED.equals(nameIDFormat)) {
            String random = Random.nextRandom();
            String nameID = subjectNameID.getValue();

            try {
                MessageDigest md = MessageDigest.getInstance("SHA-1");
                byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));
                subjectNameID.setValue(Base64Utils.encode(hash));
                subjectNameID.setNameQualifier(null);
                subjectNameID.setFormat(NameID.TRANSIENT);

            } catch (Exception e) {
                Logger.warn("PVP2 subjectNameID error", e);
                throw new MOAIDException("pvp2.13", null, e);
            }

        } else
            subjectNameID.setFormat(nameIDFormat);

        String sessionIndex = null;

        //if request is a reauthentication and NameIDFormat match reuse old session information
        if (MiscUtil.isNotEmpty(authData.getNameID()) && MiscUtil.isNotEmpty(authData.getNameIDFormat())
                && nameIDFormat.equals(authData.getNameIDFormat())) {
            subjectNameID.setValue(authData.getNameID());
            sessionIndex = authData.getSessionIndex();

        } else
            sessionIndex = SAML2Utils.getSecureIdentifier();

        SubjectConfirmationData subjectConfirmationData = SAML2Utils
                .createSAMLObject(SubjectConfirmationData.class);
        subjectConfirmationData.setInResponseTo(authnRequest.getID());
        subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime()));

        subjectConfirmationData.setRecipient(assertionConsumerService.getLocation());

        //set SLO information
        sloInformation.setUserNameIdentifier(subjectNameID.getValue());
        sloInformation.setNameIDFormat(subjectNameID.getFormat());
        sloInformation.setSessionIndex(sessionIndex);

        return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID,
                subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter());
    }

    private static Assertion buildGenericAssertion(String entityID, DateTime date,
            AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, NameID subjectNameID,
            SubjectConfirmationData subjectConfirmationData, String sessionIndex, DateTime isValidTo)
            throws ConfigurationException {
        Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class);

        AuthnContext authnContext = SAML2Utils.createSAMLObject(AuthnContext.class);
        authnContext.setAuthnContextClassRef(authnContextClassRef);

        AuthnStatement authnStatement = SAML2Utils.createSAMLObject(AuthnStatement.class);

        authnStatement.setAuthnInstant(date);
        authnStatement.setSessionIndex(sessionIndex);
        authnStatement.setAuthnContext(authnContext);

        assertion.getAuthnStatements().add(authnStatement);

        AttributeStatement attributeStatement = SAML2Utils.createSAMLObject(AttributeStatement.class);
        attributeStatement.getAttributes().addAll(attrList);
        if (attributeStatement.getAttributes().size() > 0) {
            assertion.getAttributeStatements().add(attributeStatement);
        }

        Subject subject = SAML2Utils.createSAMLObject(Subject.class);
        subject.setNameID(subjectNameID);

        SubjectConfirmation subjectConfirmation = SAML2Utils.createSAMLObject(SubjectConfirmation.class);
        subjectConfirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
        subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);

        subject.getSubjectConfirmations().add(subjectConfirmation);

        Conditions conditions = SAML2Utils.createSAMLObject(Conditions.class);
        AudienceRestriction audienceRestriction = SAML2Utils.createSAMLObject(AudienceRestriction.class);
        Audience audience = SAML2Utils.createSAMLObject(Audience.class);

        audience.setAudienceURI(entityID);
        audienceRestriction.getAudiences().add(audience);
        conditions.setNotBefore(date);
        conditions.setNotOnOrAfter(isValidTo);

        conditions.getAudienceRestrictions().add(audienceRestriction);

        assertion.setConditions(conditions);

        Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);

        issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
        issuer.setFormat(NameID.ENTITY);

        assertion.setIssuer(issuer);
        assertion.setSubject(subject);
        assertion.setID(SAML2Utils.getSecureIdentifier());
        assertion.setIssueInstant(date);

        return assertion;
    }
}