/* * 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.auth.modules.eidas.utils; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; import com.google.common.collect.ImmutableSet; import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; import at.gv.egiz.eaaf.core.api.idp.IAttributeGenerator; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; import at.gv.egiz.eaaf.core.exceptions.AttributeBuilderException; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PVPAttributeBuilder; import at.gv.egovernment.moa.id.data.IMOAAuthData; import at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.IeIDASAttribute; import at.gv.egovernment.moa.id.protocols.eidas.attributes.builder.eIDASMetadata; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; import eu.eidas.auth.commons.attribute.AttributeDefinition; import eu.eidas.auth.commons.attribute.AttributeDefinition.Builder; import eu.eidas.auth.commons.attribute.AttributeValue; import eu.eidas.auth.commons.attribute.AttributeValueMarshaller; import eu.eidas.auth.commons.attribute.AttributeValueMarshallingException; /** * @author tlenz * */ public class eIDASAttributeBuilder extends PVPAttributeBuilder { private static IAttributeGenerator generator = new SimpleEidasAttributeGenerator(); private static List listOfSupportedeIDASAttributes; private static ServiceLoader eIDASAttributLoader = ServiceLoader.load(IeIDASAttribute.class); static { List supportAttrList = new ArrayList(); Logger.info("Select eIDAS attributes that are corrently providable:"); if (eIDASAttributLoader != null ) { Iterator moduleLoaderInterator = eIDASAttributLoader.iterator(); while (moduleLoaderInterator.hasNext()) { try { IeIDASAttribute modul = moduleLoaderInterator.next(); if (modul.getClass().isAnnotationPresent(eIDASMetadata.class)) { Logger.info("Loading eIDAS attribut-builder Modul Information: " + modul.getName()); supportAttrList.add(modul.getName()); } else Logger.trace(modul.getName() + " is not an eIDAS metadata attribute"); } catch(Throwable e) { Logger.error("Check configuration! " + "Some attribute-builder modul" + " is not a valid IAttributeBuilder", e); } } } listOfSupportedeIDASAttributes = Collections.unmodifiableList(supportAttrList); Logger.info("Selection of providable eIDAS attributes done"); } /** * Get all eIDAS attribute names that can be generated by the Austrian eIDAS node. * This list is dynamically generated from loaded eIDAS attribute builders that are found in Java Classpath * * @return {@link List} of {@link String} of eIDAS attribute names */ public static List getAllProvideableeIDASAttributes() { return listOfSupportedeIDASAttributes; } /** * This method build an eIDAS response attribute, by using a loaded eIDAS attribute builder. * * @param attr eIDAS attribute that should be generated * @param onlineApplicationConfiguration SP configuration * @param authData Authentication data that contains user information for attribute generation * @return eIDAS attribute response {@link Pair} or null if the attribute generation FAILES */ public static Pair>> buildAttribute(AttributeDefinition attr, ISPConfiguration onlineApplicationConfiguration, IAuthData authData) { String attrName = attr.getNameUri().toString(); Logger.trace("Build eIDAS attribute: "+ attrName); IAttributeBuilder attrBuilder = getAttributeBuilder(attrName); if (attrBuilder != null) { try { String attrValue = attrBuilder.build(onlineApplicationConfiguration, authData, generator); boolean isMandatesUsed = false; if (authData instanceof IMOAAuthData) isMandatesUsed = ((IMOAAuthData)authData).isUseMandate(); if (MiscUtil.isNotEmpty(attrValue)) { //set uniqueIdentifier attribute, because eIDAS SAMLEngine use this flag to select the // Subject->NameID value from this attribute Builder eIDASAttrBuilder = AttributeDefinition.builder(attr); eIDASAttrBuilder.uniqueIdentifier(evaluateUniqueID(attrName, isMandatesUsed)); AttributeDefinition returnAttr = eIDASAttrBuilder.build(); //unmarshal attribute value into eIDAS attribute AttributeValueMarshaller attributeValueMarshaller = returnAttr.getAttributeValueMarshaller(); ImmutableSet.Builder> builder = ImmutableSet.builder(); AttributeValue attributeValue = null; try { attributeValue = attributeValueMarshaller.unmarshal(attrValue, false); builder.add(attributeValue); } catch (AttributeValueMarshallingException e) { throw new IllegalStateException(e); } return Pair.newInstance(returnAttr, builder.build()); } } catch (AttributeBuilderException e) { Logger.debug("Attribute can not generate requested attribute:" + attr.getNameUri().toString() + " Reason:" + e.getMessage()); } } else Logger.warn("NO attribute builder FOUND for eIDAS attr: " + attrName); return null; } /** * This method use the information from authenticated session and * evaluate the uniqueID flag according to eIDAS specification * * @param attrName eIDAS attribute name that is evaluated * @param useMandate flag that indicates if the current authenticated session includes a mandate * @return true if eIDAS attribute holds the unique ID, otherwise false */ private static boolean evaluateUniqueID(String attrName, boolean useMandate) { //from eIDAS spec 1.2 there exists single attr. for representation if (attrName.equals(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString())) return true; //if no mandate is used the natural person identifier is the unique ID // if (!useMandate && // attrName.equals(eu.eidas.auth.engine.core.eidas.spec.NaturalPersonSpec.Definitions.PERSON_IDENTIFIER.getNameUri().toString())) // return true; // // //if mandates are used the the legal person identifier or the natural person identifier of the mandator is the unique ID // else if (useMandate && // attrName.equals(eu.eidas.auth.engine.core.eidas.spec.LegalPersonSpec.Definitions.LEGAL_PERSON_IDENTIFIER.getNameUri().toString())) // return true; // // //TODO: implement flag selector for mandates and natural persons return false; } }