/*******************************************************************************
* 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;
}
}