/******************************************************************************* * 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.builder; import java.text.MessageFormat; import java.util.Calendar; import java.util.List; import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute; import at.gv.egovernment.moa.id.auth.exception.BuildException; import at.gv.egovernment.moa.id.auth.exception.ParseException; import at.gv.egovernment.moa.id.data.AuthenticationData; import at.gv.egovernment.moa.id.protocols.saml1.SAML1AuthenticationData; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DateTimeUtils; import at.gv.egovernment.moa.util.StringUtils; /** * Builder for the authentication data <saml:Assertion> * to be provided by the MOA ID Auth component. * * @author Paul Ivancsics * @version $Id$ */ public class AuthenticationDataAssertionBuilder extends AuthenticationAssertionBuilder implements Constants { /** 5 minutes (=300 seconds) default length of the assertion */ private static int DEFAULT_CONDITIONS_LENGTH = 300; /** private static String NL contains the NewLine representation in Java*/ private static final String NL = "\n"; /** * XML template for the <saml:Assertion> to be built */ private static final String AUTH_DATA = "" + NL + "" + NL + " " + NL + " " + NL + " {4}" + NL + " " + NL + " " + MOA_NS_URI + "cm" + NL + " {5}{6}" + NL + " " + NL + " " + NL + " " + NL + " {7}" + NL + " " + NL + " " + NL + " {8}" + NL + " " + NL + " " + NL + " {9}" + NL + " " + NL + "{10}" + "{11}" + "{12}" + " " + NL + ""; /** * XML template for the <saml:Assertion> to be built (with Conditions) */ private static final String AUTH_DATA_WITH_CONDITIONS = "" + NL + "" + NL + "" + NL + " " + NL + " " + NL + " {6}" + NL + " " + NL + " " + MOA_NS_URI + "cm" + NL + " {7}{8}" + NL + " " + NL + " " + NL + " " + NL + " {9}" + NL + " " + NL + " " + NL + " {10}" + NL + " " + NL + " " + NL + " {11}" + NL + " " + NL + "{12}" + "{13}" + "{14}" + " " + NL + ""; /** * XML template for the <saml:Assertion> to be built */ private static final String AUTH_DATA_MANDATE = "" + NL + "" + NL + " " + NL + " " + NL + " {4}" + NL + " " + NL + " " + MOA_NS_URI + "cm" + NL + " {5}{6}" + NL + " " + NL + " " + NL + " " + NL + " {7}" + NL + " " + NL + " " + NL + " {8}" + NL + " " + NL + " " + NL + " {9}" + NL + " " + NL + " " + NL + " {10}" + NL + " " + NL + "{11}" + "{12}" + "{13}" + " " + NL + ""; /** * XML template for the <saml:Assertion> to be built */ private static final String AUTH_DATA_MANDATE_WITH_CONDITIONS = "" + NL + "" + NL + "" + NL + " " + NL + " " + NL + " {6}" + NL + " " + NL + " " + MOA_NS_URI + "cm" + NL + " {7}{8}" + NL + " " + NL + " " + NL + " " + NL + " {9}" + NL + " " + NL + " " + NL + " {10}" + NL + " " + NL + " " + NL + " {11}" + NL + " " + NL + " " + NL + " {12}" + NL + " " + NL + "{13}" + "{14}" + "{15}" + " " + NL + ""; /** * XML template for the <saml:Attribute> named "isPublicAuthority", * to be inserted into the <saml:Assertion> */ private static final String PUBLIC_AUTHORITY_ATT = " " + NL + " {0}" + NL + " " + NL; private static final String SIGNER_CERTIFICATE_ATT = " " + NL + " {0}" + NL + " " + NL; /** * Constructor for AuthenticationDataAssertionBuilder. */ public AuthenticationDataAssertionBuilder() { super(); } /** * Builds the authentication data <saml:Assertion>. * * @param authData the AuthenticationData to build the * <saml:Assertion> from * @param xmlPersonData lt;pr:Person> element as a String * @param xmlAuthBlock authentication block to be included in a * lt;saml:SubjectConfirmationData> element; may include * the "Stammzahl" or not; may be empty * @param xmlIdentityLink the IdentityLink * @param signerCertificateBase64 Base64 encoded certificate of the signer. Maybe * an empty string if the signer certificate should not be provided. * Will be ignored if the businessService parameter is * set to false. * @param businessService true if the online application is a * business service, otherwise false * @return the <saml:Assertion> * @throws BuildException if an error occurs during the build process */ public String build( SAML1AuthenticationData authData, String xmlPersonData, String xmlAuthBlock, String xmlIdentityLink, String bkuURL, String signerCertificateBase64, boolean businessService, List extendedSAMLAttributes, boolean useCondition, int conditionLength) throws BuildException { String isQualifiedCertificate = authData.isQualifiedCertificate() ? "true" : "false"; String publicAuthorityAttribute = ""; if (authData.isPublicAuthority()) { String publicAuthorityIdentification = authData.getPublicAuthorityCode(); if (publicAuthorityIdentification == null) publicAuthorityIdentification = "True"; publicAuthorityAttribute = MessageFormat.format( PUBLIC_AUTHORITY_ATT, new Object[] { publicAuthorityIdentification }); } String signerCertificateAttribute = ""; if (signerCertificateBase64 != "") { signerCertificateAttribute = MessageFormat.format( SIGNER_CERTIFICATE_ATT, new Object[] { signerCertificateBase64 }); } String pkType; String pkValue; if (businessService) { pkType = authData.getBPKType(); pkValue = authData.getBPK(); } else { // always has the bPK as type/value pkType = URN_PREFIX_BPK; pkValue = authData.getBPK(); } // System.out.println("pkType; " + pkType); // System.out.println("pkValue; " + pkValue); String assertion; try { if (!useCondition) { assertion = MessageFormat.format(AUTH_DATA, new Object[] { authData.getAssertionID(), authData.getIssuer(), authData.getIssueInstantString(), pkType, pkValue, StringUtils.removeXMLDeclaration(xmlAuthBlock), StringUtils.removeXMLDeclaration(xmlIdentityLink), StringUtils.removeXMLDeclaration(xmlPersonData), isQualifiedCertificate, bkuURL, publicAuthorityAttribute, signerCertificateAttribute, buildExtendedSAMLAttributes(extendedSAMLAttributes)}); } else { Calendar cal = Calendar.getInstance(); String notBefore = DateTimeUtils.buildDateTimeUTC(cal); if (conditionLength <= 0) cal.add(Calendar.SECOND, DEFAULT_CONDITIONS_LENGTH); else cal.add(Calendar.SECOND, conditionLength); String notOnOrAfter = DateTimeUtils.buildDateTimeUTC(cal); assertion = MessageFormat.format(AUTH_DATA_WITH_CONDITIONS, new Object[] { authData.getAssertionID(), authData.getIssuer(), authData.getIssueInstantString(), notBefore, notOnOrAfter, pkType, pkValue, StringUtils.removeXMLDeclaration(xmlAuthBlock), StringUtils.removeXMLDeclaration(xmlIdentityLink), StringUtils.removeXMLDeclaration(xmlPersonData), isQualifiedCertificate, bkuURL, publicAuthorityAttribute, signerCertificateAttribute, buildExtendedSAMLAttributes(extendedSAMLAttributes)}); } } catch (ParseException e) { Logger.error("Error on building Authentication Data Assertion: " + e.getMessage()); throw new BuildException("builder.00", new Object[] { "Authentication Data Assertion", e.toString()}); } return assertion; } /** * Builds the authentication data <saml:Assertion>. * * @param authData the AuthenticationData to build the * <saml:Assertion> from * @param xmlPersonData lt;pr:Person> element as a String * @param xmlAuthBlock authentication block to be included in a * lt;saml:SubjectConfirmationData> element; may include * the "Stammzahl" or not; may be empty * @param xmlIdentityLink the IdentityLink * @param signerCertificateBase64 Base64 encoded certificate of the signer. Maybe * an empty string if the signer certificate should not be provided. * Will be ignored if the businessService parameter is * set to false. * @param businessService true if the online application is a * business service, otherwise false * @return the <saml:Assertion> * @throws BuildException if an error occurs during the build process */ public String buildMandate( SAML1AuthenticationData authData, String xmlPersonData, String xmlMandateData, String xmlAuthBlock, String xmlIdentityLink, String bkuURL, String signerCertificateBase64, boolean businessService, List extendedSAMLAttributes, boolean useCondition, int conditionLength) throws BuildException { String isQualifiedCertificate = authData.isQualifiedCertificate() ? "true" : "false"; String publicAuthorityAttribute = ""; if (authData.isPublicAuthority()) { String publicAuthorityIdentification = authData.getPublicAuthorityCode(); if (publicAuthorityIdentification == null) publicAuthorityIdentification = "True"; publicAuthorityAttribute = MessageFormat.format( PUBLIC_AUTHORITY_ATT, new Object[] { publicAuthorityIdentification }); } String signerCertificateAttribute = ""; if (signerCertificateBase64 != "") { signerCertificateAttribute = MessageFormat.format( SIGNER_CERTIFICATE_ATT, new Object[] { signerCertificateBase64 }); } String pkType; String pkValue; if (businessService) { pkType = authData.getBPKType(); pkValue = authData.getBPK(); } else { // always has the bPK as type/value pkType = URN_PREFIX_BPK; pkValue = authData.getBPK(); } // System.out.println("pkType; " + pkType); // System.out.println("pkValue; " + pkValue); String assertion; try { if (!useCondition) { assertion = MessageFormat.format(AUTH_DATA_MANDATE, new Object[] { authData.getAssertionID(), authData.getIssuer(), authData.getIssueInstantString(), pkType, pkValue, StringUtils.removeXMLDeclaration(xmlAuthBlock), StringUtils.removeXMLDeclaration(xmlIdentityLink), StringUtils.removeXMLDeclaration(xmlPersonData), StringUtils.removeXMLDeclaration(xmlMandateData), isQualifiedCertificate, bkuURL, publicAuthorityAttribute, signerCertificateAttribute, buildExtendedSAMLAttributes(extendedSAMLAttributes)}); } else { Calendar cal = Calendar.getInstance(); String notBefore = DateTimeUtils.buildDateTimeUTC(cal); if (conditionLength <= 0) cal.add(Calendar.SECOND, DEFAULT_CONDITIONS_LENGTH); else cal.add(Calendar.SECOND, conditionLength); String notOnOrAfter = DateTimeUtils.buildDateTimeUTC(cal); assertion = MessageFormat.format(AUTH_DATA_MANDATE_WITH_CONDITIONS, new Object[] { authData.getAssertionID(), authData.getIssuer(), authData.getIssueInstantString(), notBefore, notOnOrAfter, pkType, pkValue, StringUtils.removeXMLDeclaration(xmlAuthBlock), StringUtils.removeXMLDeclaration(xmlIdentityLink), StringUtils.removeXMLDeclaration(xmlPersonData), StringUtils.removeXMLDeclaration(xmlMandateData), isQualifiedCertificate, bkuURL, publicAuthorityAttribute, signerCertificateAttribute, buildExtendedSAMLAttributes(extendedSAMLAttributes)}); } } catch (ParseException e) { Logger.error("Error on building Authentication Data Assertion: " + e.getMessage()); throw new BuildException("builder.00", new Object[] { "Authentication Data Assertion", e.toString()}); } return assertion; } }