/*
* Copyright 2003 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;
import iaik.pki.PKIException;
import iaik.x509.X509Certificate;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import at.gv.egovernment.moa.id.AuthenticationException;
import at.gv.egovernment.moa.id.BuildException;
import at.gv.egovernment.moa.id.ParseException;
import at.gv.egovernment.moa.id.ServiceException;
import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder;
import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataAssertionBuilder;
import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;
import at.gv.egovernment.moa.id.auth.builder.CertInfoVerifyXMLSignatureRequestBuilder;
import at.gv.egovernment.moa.id.auth.builder.CreateXMLSignatureRequestBuilder;
import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
import at.gv.egovernment.moa.id.auth.builder.GetIdentityLinkFormBuilder;
import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilder;
import at.gv.egovernment.moa.id.auth.builder.InfoboxValidatorParamsBuilder;
import at.gv.egovernment.moa.id.auth.builder.PersonDataBuilder;
import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder;
import at.gv.egovernment.moa.id.auth.builder.SelectBKUFormBuilder;
import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder;
import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse;
import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttributeImpl;
import at.gv.egovernment.moa.id.auth.data.IdentityLink;
import at.gv.egovernment.moa.id.auth.data.InfoboxValidationResult;
import at.gv.egovernment.moa.id.auth.data.InfoboxValidatorParams;
import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse;
import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker;
import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
import at.gv.egovernment.moa.id.auth.parser.ExtendedInfoboxReadResponseParser;
import at.gv.egovernment.moa.id.auth.parser.InfoboxReadResponseParser;
import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser;
import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;
import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
import at.gv.egovernment.moa.id.auth.validator.CreateXMLSignatureResponseValidator;
import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;
import at.gv.egovernment.moa.id.auth.validator.InfoboxValidator;
import at.gv.egovernment.moa.id.auth.validator.ValidateException;
import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator;
import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;
import at.gv.egovernment.moa.id.auth.validator.parep.ParepValidator;
import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWConstants;
import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.config.ConnectionParameter;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameter;
import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameters;
import at.gv.egovernment.moa.id.data.AuthenticationData;
import at.gv.egovernment.moa.id.util.HTTPUtils;
import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
import at.gv.egovernment.moa.id.util.Random;
import at.gv.egovernment.moa.id.util.SSLUtils;
import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
import at.gv.egovernment.moa.logging.LogMsg;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.Base64Utils;
import at.gv.egovernment.moa.util.BoolUtils;
import at.gv.egovernment.moa.util.Constants;
import at.gv.egovernment.moa.util.DOMUtils;
import at.gv.egovernment.moa.util.DateTimeUtils;
import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.StringUtils;
/**
* API for MOA ID Authentication Service.
* {@link AuthenticationSession} is stored in a session store and retrieved
* by giving the session ID.
*
* @author Paul Ivancsics
* @version $Id$
*/
public class AuthenticationServer implements MOAIDAuthConstants {
/** single instance */
private static AuthenticationServer instance;
/** session data store (session ID -> AuthenticationSession) */
private static Map sessionStore = new HashMap();
/** authentication data store (assertion handle -> AuthenticationData) */
private static Map authenticationDataStore = new HashMap();
/**
* time out in milliseconds used by {@link cleanup} for session store
*/
private long sessionTimeOut = 10 * 60 * 1000; // default 10 minutes
/**
* time out in milliseconds used by {@link cleanup} for authentication data store
*/
private long authDataTimeOut = 2 * 60 * 1000; // default 2 minutes
/**
* Returns the single instance of AuthenticationServer
.
*
* @return the single instance of AuthenticationServer
*/
public static AuthenticationServer getInstance() {
if (instance == null)
instance = new AuthenticationServer();
return instance;
}
/**
* Constructor for AuthenticationServer.
*/
public AuthenticationServer() {
super();
}
/**
* Processes request to select a BKU.
*
Processing depends on value of {@link AuthConfigurationProvider#getBKUSelectionType}.
*
For bkuSelectionType==HTMLComplete
, a returnURI
for the
* "BKU Auswahl" service is returned.
*
For bkuSelectionType==HTMLSelect
, an HTML form for BKU selection is returned.
* @param authURL base URL of MOA-ID Auth component
* @param target "Geschäftsbereich"
* @param oaURL online application URL requested
* @param bkuSelectionTemplateURL template for BKU selection form to be used
* in case of HTMLSelect
; may be null
* @param templateURL URL providing an HTML template for the HTML form to be used
* for call startAuthentication
* @return for bkuSelectionType==HTMLComplete
, the returnURI
for the
* "BKU Auswahl" service;
* for bkuSelectionType==HTMLSelect
, an HTML form for BKU selection
* @throws WrongParametersException upon missing parameters
* @throws AuthenticationException when the configured BKU selection service cannot be reached,
* and when the given bkuSelectionTemplateURL cannot be reached
* @throws ConfigurationException on missing configuration data
* @throws BuildException while building the HTML form
*/
public String selectBKU(
String authURL,
String target,
String oaURL,
String bkuSelectionTemplateURL,
String templateURL)
throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException {
//check if HTTP Connection may be allowed (through FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
String boolStr = AuthConfigurationProvider.getInstance().getGenericConfigurationParameter(
AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
if ((!authURL.startsWith("https:")) && (false == BoolUtils.valueOf(boolStr)))
throw new AuthenticationException("auth.07", new Object[] { authURL + "*" });
if (isEmpty(authURL))
throw new WrongParametersException("StartAuthentication", "AuthURL", "auth.05");
if (isEmpty(oaURL))
throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.05");
ConnectionParameter bkuConnParam =
AuthConfigurationProvider.getInstance().getBKUConnectionParameter();
if (bkuConnParam == null)
throw new ConfigurationException(
"config.08",
new Object[] { "BKUSelection/ConnectionParameter" });
OAAuthParameter oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);
if (oaParam == null)
throw new AuthenticationException("auth.00", new Object[] { oaURL });
if (!oaParam.getBusinessService()) {
if (isEmpty(target))
throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.05");
} else {
if (!isEmpty(target)) {
Logger.info("Ignoring target parameter thus application type is \"businessService\"");
}
target = null;
}
AuthenticationSession session = newSession();
Logger.info("MOASession " + session.getSessionID() + " angelegt");
session.setTarget(target);
session.setOAURLRequested(oaURL);
session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix());
session.setAuthURL(authURL);
session.setTemplateURL(templateURL);
session.setBusinessService(oaParam.getBusinessService());
String returnURL =
new DataURLBuilder().buildDataURL(authURL, REQ_START_AUTHENTICATION, session.getSessionID());
String bkuSelectionType = AuthConfigurationProvider.getInstance().getBKUSelectionType();
if (bkuSelectionType.equals(AuthConfigurationProvider.BKU_SELECTION_TYPE_HTMLCOMPLETE)) {
// bkuSelectionType==HTMLComplete
String redirectURL = bkuConnParam.getUrl() + "?" + AuthServlet.PARAM_RETURN + "=" + returnURL;
return redirectURL;
} else {
// bkuSelectionType==HTMLSelect
String bkuSelectTag;
try {
bkuSelectTag = readBKUSelectTag(AuthConfigurationProvider.getInstance(), bkuConnParam);
} catch (Throwable ex) {
throw new AuthenticationException(
"auth.11",
new Object[] { bkuConnParam.getUrl(), ex.toString()},
ex);
}
String bkuSelectionTemplate = null;
// override template url by url from configuration file
if (oaParam.getBkuSelectionTemplateURL() != null) {
bkuSelectionTemplateURL = oaParam.getBkuSelectionTemplateURL();
}
if (bkuSelectionTemplateURL != null) {
try {
bkuSelectionTemplate = new String(FileUtils.readURL(bkuSelectionTemplateURL));
} catch (IOException ex) {
throw new AuthenticationException(
"auth.03",
new Object[] { bkuSelectionTemplateURL, ex.toString()},
ex);
}
}
String htmlForm =
new SelectBKUFormBuilder().build(bkuSelectionTemplate, returnURL, bkuSelectTag);
return htmlForm;
}
}
/**
* Method readBKUSelectTag.
* @param conf the ConfigurationProvider
* @param connParam the ConnectionParameter for that connection
* @return String
* @throws ConfigurationException on config-errors
* @throws PKIException on PKI errors
* @throws IOException on any data error
* @throws GeneralSecurityException on security errors
*/
private String readBKUSelectTag(ConfigurationProvider conf, ConnectionParameter connParam)
throws ConfigurationException, PKIException, IOException, GeneralSecurityException {
if (connParam.isHTTPSURL())
return SSLUtils.readHttpsURL(conf, connParam);
else
return HTTPUtils.readHttpURL(connParam.getUrl());
}
/**
* Processes the beginning of an authentication session.
*
<InfoboxReadRequest>
<InfoboxReadRequest>
null
; in this case, the default location will be used
* @param useMandate Indicates if mandate is used or not
* @param templateURL URL providing an HTML template for the HTML form generated
* @param templateMandteURL URL providing an HTML template for the HTML form generated (for signing in mandates mode)
* @param scheme determines the protocol used
* @param sourceID
* @return HTML form
* @throws AuthenticationException
* @see GetIdentityLinkFormBuilder
* @see InfoboxReadRequestBuilder
*/
public String startAuthentication(
String authURL,
String target,
String targetFriendlyName,
String oaURL,
String templateURL,
String bkuURL,
String useMandate,
String sessionID,
String scheme,
String sourceID)
throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException {
String useMandateString = null;
boolean useMandateBoolean = false;
if ((useMandate != null) && (useMandate.compareTo("") != 0)) {
useMandateString = useMandate;
}
else {
useMandateString = "false";
}
if (useMandateString.compareToIgnoreCase("true") == 0)
useMandateBoolean = true;
else
useMandateBoolean = false;
if (isEmpty(sessionID)) {
if (isEmpty(authURL))
throw new WrongParametersException("StartAuthentication", "AuthURL", "auth.05");
//check if HTTP Connection may be allowed (through FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY)
String boolStr =
AuthConfigurationProvider.getInstance().getGenericConfigurationParameter(
AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY);
if ((!authURL.startsWith("https:")) && (false == BoolUtils.valueOf(boolStr)))
throw new AuthenticationException("auth.07", new Object[] { authURL + "*" });
if (isEmpty(oaURL))
throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.05");
}
AuthenticationSession session;
OAAuthParameter oaParam;
if (sessionID != null) {
session = getSession(sessionID);
oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
session.getPublicOAURLPrefix());
} else {
oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);
if (oaParam == null)
throw new AuthenticationException("auth.00", new Object[] { oaURL });
if (!oaParam.getBusinessService()) {
if (isEmpty(target))
throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.05");
} else {
if (useMandateBoolean) {
Logger.error("Online-Mandate Mode for bussines application not supported.");
throw new AuthenticationException("auth.17", null);
}
target = null;
targetFriendlyName = null;
}
session = newSession();
Logger.info("MOASession " + session.getSessionID() + " angelegt");
session.setTarget(target);
session.setTargetFriendlyName(targetFriendlyName);
session.setOAURLRequested(oaURL);
session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix());
session.setAuthURL(authURL);
session.setTemplateURL(templateURL);
session.setBusinessService(oaParam.getBusinessService());
if (sourceID != null)
session.setSourceID(sourceID);
}
// BKU URL has not been set yet, even if session already exists
if (bkuURL == null) {
if (scheme!=null && scheme.equalsIgnoreCase("https")) {
bkuURL = DEFAULT_BKU_HTTPS;
} else {
bkuURL = DEFAULT_BKU;
}
}
session.setBkuURL(bkuURL);
session.setDomainIdentifier(oaParam.getIdentityLinkDomainIdentifier());
session.setUseMandate(useMandateString);
String infoboxReadRequest =
new InfoboxReadRequestBuilder().build(oaParam.getSlVersion12(),
oaParam.getBusinessService(),
oaParam.getIdentityLinkDomainIdentifier());
String dataURL =
new DataURLBuilder().buildDataURL(
session.getAuthURL(),
REQ_VERIFY_IDENTITY_LINK,
session.getSessionID());
String template = null;
// override template url by url from configuration file
if (oaParam.getTemplateURL() != null) {
templateURL = oaParam.getTemplateURL();
} else {
templateURL = session.getTemplateURL();
}
if (templateURL != null) {
try {
template = new String(FileUtils.readURL(templateURL));
} catch (IOException ex) {
throw new AuthenticationException(
"auth.03",
new Object[] { templateURL, ex.toString()},
ex);
}
}
String pushInfobox = "";
VerifyInfoboxParameters verifyInfoboxParameters = oaParam.getVerifyInfoboxParameters();
if (verifyInfoboxParameters != null) {
pushInfobox = verifyInfoboxParameters.getPushInfobox();
session.setPushInfobox(pushInfobox);
}
String certInfoRequest = new CertInfoVerifyXMLSignatureRequestBuilder().build(oaParam.getSlVersion12());
String certInfoDataURL =
new DataURLBuilder().buildDataURL(
session.getAuthURL(),
REQ_START_AUTHENTICATION,
session.getSessionID());
String htmlForm =
new GetIdentityLinkFormBuilder().build(
template,
bkuURL,
infoboxReadRequest,
dataURL,
certInfoRequest,
certInfoDataURL,
pushInfobox);
return htmlForm;
}
/**
* Processes an <InfoboxReadResponse>
sent by the
* security layer implementation.<InfoboxReadResponse>
<InfoboxReadResponse>
<CreateXMLSignatureRequest>
* containg the authentication block, meant to be returned to the
* security layer implementation<InfoboxReadResponse>
* @return String representation of the <CreateXMLSignatureRequest>
*/
public String verifyIdentityLink(String sessionID, Map infoboxReadResponseParameters)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ValidateException,
ServiceException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_IDENTITY_LINK, PARAM_SESSIONID});
String xmlInfoboxReadResponse = (String)infoboxReadResponseParameters.get(PARAM_XMLRESPONSE);
//System.out.println("PB: " + xmlInfoboxReadResponse);
if (isEmpty(xmlInfoboxReadResponse))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_IDENTITY_LINK, PARAM_XMLRESPONSE});
AuthenticationSession session = getSession(sessionID);
if (session.getTimestampIdentityLink() != null)
throw new AuthenticationException("auth.01", new Object[] { sessionID });
session.setTimestampIdentityLink();
AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
// check if an identity link was found
// Errorcode 2911 von Trustdesk BKU (nicht spezifikationskonform (SL1.2))
//CharSequence se = "ErrorCode>2911".substring(0);
//boolean b = xmlInfoboxReadResponse.contains(se);
String se = "ErrorCode>2911";
int b = xmlInfoboxReadResponse.indexOf(se);
if (b!=-1) { // no identity link found
Logger.info("Es konnte keine Personenbindung auf der Karte gefunden werden. Versuche Anmeldung als ausländische eID.");
return null;
}
// spezifikationsgemäßer (SL1.2) Errorcode
se = "ErrorCode>4002";
//b = xmlInfoboxReadResponse.contains(se);
b = xmlInfoboxReadResponse.indexOf(se);
if (b!=-1) { // Unbekannter Infoboxbezeichner
Logger.info("Unbekannter Infoboxbezeichner. Versuche Anmeldung als ausländische eID.");
return null;
}
// for testing new identity link certificate
// xmlInfoboxReadResponse = null;
// try {
// File file = new File("c:/temp/XXXMuster.xml");
// FileInputStream fis;
//
// fis = new FileInputStream(file);
// byte[] array = Utils.readFromInputStream(fis);
//
// xmlInfoboxReadResponse = new String(array);
// System.out.println(xmlInfoboxReadResponse);
//
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (UtilsException e) {
// e.printStackTrace();
// }
// parses the Mandate
sent by the
* MIS.Mandate
<CreateXMLSignatureRequest>
* containg the authentication block, meant to be returned to the
* security layer implementation<InfoboxReadResponse>
* @return String representation of the <CreateXMLSignatureRequest>
*/
public void verifyMandate(String sessionID, MISMandate mandate)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ValidateException,
ServiceException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { GET_MIS_SESSIONID, PARAM_SESSIONID});
String sMandate = new String(mandate.getMandate());
if (sMandate == null | sMandate.compareToIgnoreCase("") == 0) {
Logger.error("Mandate is empty.");
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID});
}
AuthenticationSession session = getSession(sessionID);
OAAuthParameter oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
session.getPublicOAURLPrefix());
try {
// sets the extended SAML attributes for OID (Organwalter)
setExtendedSAMLAttributeForMandatesOID(session, mandate, oaParam.getBusinessService());
} catch (SAXException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (IOException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (ParserConfigurationException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (TransformerException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
}
if (oaParam.getProvideFullMandatorData()) {
try {
// set extended SAML attributes if provideMandatorData is true
setExtendedSAMLAttributeForMandates(session, mandate, oaParam.getBusinessService(), oaParam.getProvideStammzahl());
} catch (SAXException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (IOException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (ParserConfigurationException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
} catch (TransformerException e) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID}, e);
}
}
}
/**
*
* @param session
* @param authConf
* @param oaParam
* @return
* @throws ConfigurationException
* @throws BuildException
* @throws ValidateException
*/
public String getCreateXMLSignatureRequestAuthBlockOrRedirect(AuthenticationSession session, AuthConfigurationProvider authConf, OAAuthParameter oaParam)
throws
ConfigurationException,
BuildException,
ValidateException {
// check for intermediate processing of the infoboxes
if (session.isValidatorInputPending()) return "Redirect to Input Processor";
if (authConf==null) authConf = AuthConfigurationProvider.getInstance();
if (oaParam==null) oaParam = AuthConfigurationProvider.getInstance().
getOnlineApplicationParameter(session.getPublicOAURLPrefix());
// if (!fromMandate) {
//BZ.., calculate bPK for signing to be already present in AuthBlock
IdentityLink identityLink = session.getIdentityLink();
if (identityLink.getIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {
// only compute bPK if online application is a public service and we have the Stammzahl
String bpkBase64 = new BPKBuilder().buildBPK(
identityLink.getIdentificationValue(),
session.getTarget());
identityLink.setIdentificationValue(bpkBase64);
}
//..BZ
// }
// builds the AUTH-block
String authBlock = buildAuthenticationBlock(session, oaParam);
// session.setAuthBlock(authBlock);
// builds the <CreateXMLSignatureRequest>
*/
public String createXMLSignatureRequestForeignID(String sessionID, X509Certificate cert)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ValidateException,
ServiceException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_CERTIFICATE, PARAM_SESSIONID});
AuthenticationSession session = getSession(sessionID);
AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
OAAuthParameter oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
session.getPublicOAURLPrefix());
return getCreateXMLSignatureRequestForeigID(session, authConf, oaParam, cert);
}
public String getCreateXMLSignatureRequestForeigID(AuthenticationSession session, AuthConfigurationProvider authConf, OAAuthParameter oaParam, X509Certificate cert) throws ConfigurationException
{
// check for intermediate processing of the infoboxes
if (session.isValidatorInputPending()) return "Redirect to Input Processor";
if (authConf==null) authConf = AuthConfigurationProvider.getInstance();
if (oaParam==null) oaParam = AuthConfigurationProvider.getInstance().
getOnlineApplicationParameter(session.getPublicOAURLPrefix());
Principal subject = cert.getSubjectDN();
String createXMLSignatureRequest =
new CreateXMLSignatureRequestBuilder().buildForeignID(subject.toString(), oaParam, session);
return createXMLSignatureRequest;
}
/**
* Processes an <CreateXMLSignatureResponse>
sent by the
* security layer implementation.<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
*/
public X509Certificate verifyXMLSignature(String sessionID, Map createXMLSignatureResponseParameters)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ValidateException,
ServiceException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_GET_FOREIGN_ID, PARAM_SESSIONID});
String xmlCreateXMLSignatureResponse = (String)createXMLSignatureResponseParameters.get(PARAM_XMLRESPONSE);
if (isEmpty(xmlCreateXMLSignatureResponse))
throw new AuthenticationException("auth.10", new Object[] { REQ_GET_FOREIGN_ID, PARAM_XMLRESPONSE});
AuthenticationSession session = getSession(sessionID);
/*if (session.getTimestampIdentityLink() != null)
throw new AuthenticationException("auth.01", new Object[] { sessionID });*/
//session.setTimestampIdentityLink();
AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
// parses the <CreateXMLSignatureResponse>
sent by the
* security layer implementation.<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
<ReadInfoboxResponse>
*/
public X509Certificate getCertificate(String sessionID, Map readInfoboxResponseParameters)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ValidateException,
ServiceException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_CERTIFICATE, PARAM_SESSIONID});
String xmlReadInfoboxResponse = (String)readInfoboxResponseParameters.get(PARAM_XMLRESPONSE);
if (isEmpty(xmlReadInfoboxResponse))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_CERTIFICATE, PARAM_XMLRESPONSE});
// parses the <saml:Assertion>
from given session data.
* @param session authentication session
*
* @return <saml:Assertion>
as a String
*
* @throws BuildException If an error occurs on serializing an extended SAML attribute
* to be appended to the AUTH-Block.
*/
private String buildAuthenticationBlock(AuthenticationSession session, OAAuthParameter oaParam) throws BuildException {
IdentityLink identityLink = session.getIdentityLink();
String issuer = identityLink.getName();
String gebDat = identityLink.getDateOfBirth();
String identificationValue = identityLink.getIdentificationValue();
String identificationType = identityLink.getIdentificationType();
String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance(), oaParam.getUseUTC());
session.setIssueInstant(issueInstant);
String authURL = session.getAuthURL();
String target = session.getTarget();
String targetFriendlyName = session.getTargetFriendlyName();
//Bug #485 (https://egovlabs.gv.at/tracker/index.php?func=detail&aid=485&group_id=6&atid=105)
//String oaURL = session.getPublicOAURLPrefix();
String oaURL = session.getPublicOAURLPrefix().replaceAll("&", "&");
List extendedSAMLAttributes = session.getExtendedSAMLAttributesAUTH();
String authBlock = new AuthenticationBlockAssertionBuilder().buildAuthBlock(
issuer,
issueInstant,
authURL,
target,
targetFriendlyName,
identificationValue,
identificationType,
oaURL,
gebDat,
extendedSAMLAttributes,
session);
return authBlock;
}
/**
* Verifies the infoboxes (except of the identity link infobox) returned by the BKU by
* calling appropriate validator classes.
*
* @param session The actual authentication session.
* @param infoboxReadResponseParams The parameters returned from the BKU as response
* to an infobox read request (including the infobox
* tokens to be verified).
* @param hideStammzahl Indicates whether source pins (Stammzahl
en)
* should be hidden in any SAML attribute that may be
* returned by a validator.
*
* @throws AuthenticationException If the verification of at least one infobox fails.
* @throws ConfigurationException If the OAuthParameter cannot be extracted.
*/
private void verifyInfoboxes(
AuthenticationSession session, Map infoboxReadResponseParams, boolean hideStammzahl)
throws ValidateException, ConfigurationException
{
AuthConfigurationProvider authConfigurationProvider = AuthConfigurationProvider.getInstance();
// get the default VerifyInfobox parameters
Map defaultInfoboxParameters = null;
VerifyInfoboxParameters defaultVerifyInfoboxParameters =
authConfigurationProvider.getDefaultVerifyInfoboxParameters();
if (defaultVerifyInfoboxParameters != null) {
defaultInfoboxParameters = defaultVerifyInfoboxParameters.getInfoboxParameters();
}
// get the OA specific VerifyInfobox parameters
Map infoboxParameters = null;
OAAuthParameter oaParam =
authConfigurationProvider.getOnlineApplicationParameter(session.getPublicOAURLPrefix());
VerifyInfoboxParameters verifyInfoboxParameters = oaParam.getVerifyInfoboxParameters();
session.setExtendedSAMLAttributesAUTH(new Vector()); // Initialize SAML Attributes
session.setExtendedSAMLAttributesOA(new Vector());
//System.out.println("SAML set: " + session.getExtendedSAMLAttributesAUTH().size());
if (verifyInfoboxParameters != null) {
infoboxParameters = verifyInfoboxParameters.getInfoboxParameters();
// get the list of infobox identifiers
List identifiers = verifyInfoboxParameters.getIdentifiers();
if (identifiers != null) {
// step through the identifiers and verify the infoboxes
Iterator it = identifiers.iterator();
while (it.hasNext()) {
String identifier = (String)it.next();
// get the infobox read response from the map of parameters
String infoboxReadResponse = (String)infoboxReadResponseParams.get(identifier);
// get the configuration parameters
VerifyInfoboxParameter verifyInfoboxParameter = null;
Object object = infoboxParameters.get(identifier);
// if not present, use default
if ((object == null) && (defaultInfoboxParameters != null)) {
object = defaultInfoboxParameters.get(identifier);
}
if (object != null) {
verifyInfoboxParameter = (VerifyInfoboxParameter)object;
}
if (infoboxReadResponse != null) {
if (verifyInfoboxParameter == null) {
// should not happen because of the pushinfobox mechanism; check it anyway
Logger.error("No validator for verifying \"" + identifier + "\"-infobox configured.");
throw new ValidateException("validator.41", new Object[] {identifier});
} else {
String friendlyName = verifyInfoboxParameter.getFriendlyName();
boolean isParepRequest = false;
// parse the infobox read reponse
List infoboxTokenList = null;
try {
infoboxTokenList =
ExtendedInfoboxReadResponseParser.parseInfoboxReadResponse(infoboxReadResponse, friendlyName);
} catch (ParseException e) {
Logger.error("InfoboxReadResponse for \"" + identifier +
"\"-infobox could not be parsed successfully: " + e.getMessage());
throw new ValidateException("validator.43", new Object[] {friendlyName});
}
// set compatibility mode for mandates infobox and all infoboxes (it is possible to be a parep infobox)
//session.setMandateCompatibilityMode(ParepConfiguration.isMandateCompatibilityMode(verifyInfoboxParameter.getApplicationSpecificParams()));
// check for party representation in mandates infobox
if (Constants.INFOBOXIDENTIFIER_MANDATES.equalsIgnoreCase(identifier) && !((infoboxTokenList == null || infoboxTokenList.size() == 0))){
//We need app specific parameters
if (null==verifyInfoboxParameter.getApplicationSpecificParams()) {
throw new ValidateException("validator.66", new Object[] {friendlyName});
}
Element mandate = ParepValidator.extractPrimaryToken(infoboxTokenList);
//ParepUtils.serializeElement(mandate, System.out);
String mandateID = ParepUtils.extractRepresentativeID(mandate);
if (!isEmpty(mandateID) &&
("*".equals(mandateID) || mandateID.startsWith(MOAIDAuthConstants.PARTY_REPRESENTATION_OID_NUMBER))) {
isParepRequest = true;
}
if (!isParepRequest) {
//if mandates validator is disabled we must throw an error in this case
if (!ParepUtils.isValidatorEnabled(verifyInfoboxParameter.getApplicationSpecificParams())) {
throw new ValidateException("validator.60", new Object[] {friendlyName});
}
}
}
// get the class for validating the infobox
InfoboxValidator infoboxValidator = null;
try {
Class validatorClass = null;
if (isParepRequest) {
// Mandates infobox in party representation mode
validatorClass = Class.forName("at.gv.egovernment.moa.id.auth.validator.parep.ParepValidator");
} else {
validatorClass = Class.forName(verifyInfoboxParameter.getValidatorClassName());
}
infoboxValidator = (InfoboxValidator) validatorClass.newInstance();
} catch (Exception e) {
Logger.error("Could not load validator class \"" + verifyInfoboxParameter.getValidatorClassName() +
"\" for \"" + identifier + "\"-infobox: " + e.getMessage());
throw new ValidateException("validator.42", new Object[] {friendlyName});
}
Logger.debug("Successfully loaded validator class \"" + verifyInfoboxParameter.getValidatorClassName() +
"\" for \"" + identifier + "\"-infobox.");
// build the parameters for validating the infobox
InfoboxValidatorParams infoboxValidatorParams =
InfoboxValidatorParamsBuilder.buildInfoboxValidatorParams(
session, verifyInfoboxParameter, infoboxTokenList, oaParam);
// now validate the infobox
InfoboxValidationResult infoboxValidationResult = null;
try {
infoboxValidationResult = infoboxValidator.validate(infoboxValidatorParams);
} catch (ValidateException e) {
Logger.error("Error validating " + identifier + " infobox:" + e.getMessage());
throw new ValidateException(
"validator.44", new Object[] {friendlyName});
}
if (!infoboxValidationResult.isValid()) {
Logger.info("Validation of " + identifier + " infobox failed.");
throw new ValidateException(
"validator.40", new Object[] {friendlyName, infoboxValidationResult.getErrorMessage()});
}
Logger.info(identifier + " infobox successfully validated.");
// store the validator for post processing
session.addInfoboxValidator(identifier, friendlyName, infoboxValidator);
// get the SAML attributes to be appended to the AUTHBlock or to the final
// SAML Assertion
AddAdditionalSAMLAttributes(session, infoboxValidationResult.getExtendedSamlAttributes(), identifier, friendlyName);
}
} else {
if ((verifyInfoboxParameter !=null) && (verifyInfoboxParameter.isRequired())) {
Logger.info("Infobox \"" + identifier + "\" is required, but not returned from the BKU");
throw new ValidateException(
"validator.48", new Object[] {verifyInfoboxParameter.getFriendlyName()});
}
Logger.debug("Infobox \"" + identifier + "\" not returned from BKU.");
}
}
}
}
}
/**
* Verifies the infoboxes (except of the identity link infobox) returned by the BKU by
* calling appropriate validator classes.
*
* @param session The actual authentication session.
* @param mandate The Mandate from the MIS
*
* @throws AuthenticationException
* @throws ConfigurationException
* @throws TransformerException
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
private void setExtendedSAMLAttributeForMandates(
AuthenticationSession session, MISMandate mandate, boolean business, boolean provideStammzahl)
throws ValidateException, ConfigurationException, SAXException, IOException, ParserConfigurationException, TransformerException
{
ExtendedSAMLAttribute[] extendedSamlAttributes = addExtendedSamlAttributes(mandate, business, provideStammzahl);
AddAdditionalSAMLAttributes(session, extendedSamlAttributes, "MISService", "MISService");
}
/**
* Verifies the infoboxes (except of the identity link infobox) returned by the BKU by
* calling appropriate validator classes.
*
* @param session The actual authentication session.
* @param mandate The Mandate from the MIS
*
* @throws AuthenticationException
* @throws ConfigurationException
* @throws TransformerException
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
private void setExtendedSAMLAttributeForMandatesOID(
AuthenticationSession session, MISMandate mandate, boolean business)
throws ValidateException, ConfigurationException, SAXException, IOException, ParserConfigurationException, TransformerException
{
ExtendedSAMLAttribute[] extendedSamlAttributes = addExtendedSamlAttributesOID(mandate, business);
AddAdditionalSAMLAttributes(session, extendedSamlAttributes, "MISService", "MISService");
}
/**
* Intermediate processing of the infoboxes. The first pending infobox
* validator may validate the provided input
*
* @param session The current authentication session
* @param parameters The parameters got returned by the user input fields
*/
public static void processInput(AuthenticationSession session, Map parameters) throws ValidateException
{
// post processing of the infoboxes
Iterator iter = session.getInfoboxValidatorIterator();
if (iter != null) {
while (iter.hasNext()) {
Vector infoboxValidatorVector = (Vector) iter.next();
InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector.get(2);
if (!ParepUtils.isEmpty(infoboxvalidator.getForm())) {
String identifier = (String) infoboxValidatorVector.get(0);
String friendlyName = (String) infoboxValidatorVector.get(1);
InfoboxValidationResult infoboxValidationResult = null;
try {
infoboxValidationResult = infoboxvalidator.validate(parameters);
} catch (ValidateException e) {
Logger.error("Error validating " + identifier + " infobox:" + e.getMessage());
throw new ValidateException(
"validator.44", new Object[] {friendlyName});
}
if (!infoboxValidationResult.isValid()) {
Logger.info("Validation of " + identifier + " infobox failed.");
throw new ValidateException(
"validator.40", new Object[] {friendlyName, infoboxValidationResult.getErrorMessage()});
}
AddAdditionalSAMLAttributes(session, infoboxValidationResult.getExtendedSamlAttributes(), identifier, friendlyName);
}
}
}
}
/**
* Adds given SAML Attributes to the current session. They will be appended
* to the final SAML Assertion or the AUTH block. If the attributes are
* already in the list, they will be replaced.
*
* @param session The current session
* @param extendedSAMLAttributes The SAML attributes to add
* @param identifier The infobox identifier for debug purposes
* @param friendlyNam The friendly name of the infobox for debug purposes
*/
private static void AddAdditionalSAMLAttributes(AuthenticationSession session, ExtendedSAMLAttribute[] extendedSAMLAttributes,
String identifier, String friendlyName) throws ValidateException
{
if (extendedSAMLAttributes == null) return;
List oaAttributes = session.getExtendedSAMLAttributesOA();
if (oaAttributes==null) oaAttributes = new Vector();
List authAttributes = session.getExtendedSAMLAttributesAUTH();
if (authAttributes==null) authAttributes = new Vector();
int length = extendedSAMLAttributes.length;
for (int i=0; i<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
for error codes<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
* @return SAML artifact needed for retrieving authentication data, encoded BASE64
*/
public String verifyAuthenticationBlock(
String sessionID,
String xmlCreateXMLSignatureReadResponse)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ServiceException,
ValidateException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID});
if (isEmpty(xmlCreateXMLSignatureReadResponse))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE});
AuthenticationSession session = getSession(sessionID);
AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
// parses <CreateXMLSignatureResponse>
sent by the
* security layer implementation.<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
for error codes<CreateXMLSignatureResponse>
<CreateXMLSignatureResponse>
* @return SAML artifact needed for retrieving authentication data, encoded BASE64
*/
public String verifyAuthenticationBlockMandate(
String sessionID,
Element mandate)
throws
AuthenticationException,
BuildException,
ParseException,
ConfigurationException,
ServiceException,
ValidateException {
if (isEmpty(sessionID))
throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID});
AuthenticationSession session = getSession(sessionID);
//AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
IdentityLink tempIdentityLink = null;
if (session.getUseMandate()) {
tempIdentityLink = new IdentityLink();
Element mandator = ParepUtils.extractMandator(mandate);
String dateOfBirth = "";
Element prPerson = null;
String familyName = "";
String givenName = "";
String identificationType = "";
String identificationValue = "";
if (mandator != null) {
boolean physical = ParepUtils.isPhysicalPerson(mandator);
if (physical) {
familyName = ParepUtils.extractText(mandator, "descendant-or-self::pr:Name/pr:FamilyName/text()");
givenName = ParepUtils.extractText(mandator, "descendant-or-self::pr:Name/pr:GivenName/text()");
dateOfBirth = ParepUtils.extractMandatorDateOfBirth(mandator);
} else {
familyName = ParepUtils.extractMandatorFullName(mandator);
}
identificationType = ParepUtils.getIdentification(mandator, "Type");
identificationValue = ParepUtils.extractMandatorWbpk(mandator);
prPerson = ParepUtils.extractPrPersonOfMandate(mandate);
if (physical && session.getBusinessService() && identificationType!=null && Constants.URN_PREFIX_BASEID.equals(identificationType)) {
// now we calculate the wbPK and do so if we got it from the BKU
identificationType = Constants.URN_PREFIX_WBPK + "+" + session.getDomainIdentifier();
identificationValue = new BPKBuilder().buildWBPK(identificationValue, session.getDomainIdentifier());
ParepUtils.HideStammZahlen(prPerson, true, null, null, true);
}
tempIdentityLink.setDateOfBirth(dateOfBirth);
tempIdentityLink.setFamilyName(familyName);
tempIdentityLink.setGivenName(givenName);
tempIdentityLink.setIdentificationType(identificationType);
tempIdentityLink.setIdentificationValue(identificationValue);
tempIdentityLink.setPrPerson(prPerson);
try {
tempIdentityLink.setSamlAssertion(session.getIdentityLink().getSamlAssertion());
} catch (Exception e) {
throw new ValidateException("validator.64", null);
}
}
}
// builds authentication data and stores it together with a SAML artifact
AuthenticationData authData = session.getAssertionAuthData(); //buildAuthenticationData(session, vsresp, replacementIdentityLink);
Element mandatePerson = tempIdentityLink.getPrPerson();
try {
System.out.println("MANDATE: " + DOMUtils.serializeNode(mandatePerson));
}
catch(Exception e) {
e.printStackTrace();
}
String mandateData = null;
try {
OAAuthParameter oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
session.getPublicOAURLPrefix());
boolean provideStammzahl = oaParam.getProvideStammzahl();
if (!provideStammzahl) {
String isPrPerson = mandatePerson.getAttribute("xsi:type");
if (!StringUtils.isEmpty(isPrPerson)) {
if (isPrPerson.equalsIgnoreCase("pr:PhysicalPerson")) {
Node prIdentification = mandatePerson.getFirstChild();
prIdentification.getFirstChild().setTextContent("");
// Element.appendChild(Document.createTextNode(String));
// prIdentification.getFirstChild().
}
}
}
mandateData = DOMUtils.serializeNode(mandatePerson);
} catch (TransformerException e1) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID});
} catch (IOException e1) {
throw new AuthenticationException("auth.16", new Object[] { GET_MIS_SESSIONID});
}
String samlAssertion =
new AuthenticationDataAssertionBuilder().buildMandate(
authData,
session.getAssertionPrPerson(),
mandateData,
session.getAssertionAuthBlock(),
session.getAssertionIlAssertion(),
session.getBkuURL(),
session.getAssertionSignerCertificateBase64(),
session.getAssertionBusinessService(),
session.getSourceID(),
session.getExtendedSAMLAttributesOA());
authData.setSamlAssertion(samlAssertion);
String assertionFile = AuthConfigurationProvider.getInstance().getGenericConfigurationParameter("AuthenticationServer.WriteAssertionToFile");
if (!ParepUtils.isEmpty(assertionFile))
try {
ParepUtils.saveStringToFile(samlAssertion, new File(assertionFile));
} catch (IOException e) {
throw new BuildException(
"builder.00",
new Object[] { "AuthenticationData", e.toString()},
e);
}
String samlArtifact =
new SAMLArtifactBuilder().build(session.getAuthURL(), session.getSessionID(), session.getSourceID());
storeAuthenticationData(samlArtifact, authData);
// invalidates the authentication session
sessionStore.remove(sessionID);
Logger.info(
"Anmeldedaten zu MOASession " + sessionID + " angelegt, SAML Artifakt " + samlArtifact);
return samlArtifact;
}
/**
* Gets the foreign authentication data.<saml:Assertion>
* @param session authentication session
* @param verifyXMLSigResp VerifyXMLSignatureResponse from MOA-SP
* @return AuthenticationData object
* @throws ConfigurationException while accessing configuration data
* @throws BuildException while building the <saml:Assertion>
*/
private AuthenticationData buildAuthenticationData(
AuthenticationSession session,
VerifyXMLSignatureResponse verifyXMLSigResp,
boolean useUTC)
throws ConfigurationException, BuildException {
IdentityLink identityLink = session.getIdentityLink();
AuthenticationData authData = new AuthenticationData();
OAAuthParameter oaParam =
AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
session.getPublicOAURLPrefix());
boolean businessService = oaParam.getBusinessService();
authData.setMajorVersion(1);
authData.setMinorVersion(0);
authData.setAssertionID(Random.nextRandom());
authData.setIssuer(session.getAuthURL());
authData.setIssueInstant(DateTimeUtils.buildDateTime(Calendar.getInstance(), useUTC));
authData.setIdentificationType(identityLink.getIdentificationType());
authData.setGivenName(identityLink.getGivenName());
authData.setFamilyName(identityLink.getFamilyName());
authData.setDateOfBirth(identityLink.getDateOfBirth());
authData.setQualifiedCertificate(verifyXMLSigResp.isQualifiedCertificate());
authData.setPublicAuthority(verifyXMLSigResp.isPublicAuthority());
authData.setPublicAuthorityCode(verifyXMLSigResp.getPublicAuthorityCode());
authData.setBkuURL(session.getBkuURL());
authData.setUseUTC(oaParam.getUseUTC());
boolean provideStammzahl = oaParam.getProvideStammzahl();
if (provideStammzahl) {
authData.setIdentificationValue(identityLink.getIdentificationValue());
}
String prPerson = new PersonDataBuilder().build(identityLink, provideStammzahl);
try {
String signerCertificateBase64 = "";
if (oaParam.getProvideCertifcate()) {
X509Certificate signerCertificate = verifyXMLSigResp.getX509certificate();
if (signerCertificate != null) {
signerCertificateBase64 = Base64Utils.encode(signerCertificate.getEncoded());
} else {
Logger.info("\"provideCertificate\" is \"true\", but no signer certificate available");
}
}
authData.setSignerCertificate(signerCertificateBase64);
if (businessService) {
authData.setWBPK(identityLink.getIdentificationValue());
} else {
authData.setBPK(identityLink.getIdentificationValue());
//BZ.., calculation of bPK already before sending AUTHBlock
/*
if (identityLink.getIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {
// only compute bPK if online application is a public service and we have the Stammzahl
String bpkBase64 = new BPKBuilder().buildBPK(
identityLink.getIdentificationValue(),
session.getTarget());
authData.setBPK(bpkBase64);
}*/
}
String ilAssertion =
oaParam.getProvideIdentityLink()
? identityLink.getSerializedSamlAssertion()
: "";
if (!oaParam.getProvideStammzahl()) {
ilAssertion = StringUtils.replaceAll(ilAssertion, identityLink.getIdentificationValue(), "");
}
String authBlock = oaParam.getProvideAuthBlock() ? session.getAuthBlock() : "";
session.setAssertionAuthBlock(authBlock);
session.setAssertionAuthData(authData);
session.setAssertionBusinessService(businessService);
session.setAssertionIlAssertion(ilAssertion);
session.setAssertionPrPerson(prPerson);
session.setAssertionSignerCertificateBase64(signerCertificateBase64);
return authData;
} catch (Throwable ex) {
throw new BuildException(
"builder.00",
new Object[] { "AuthenticationData", ex.toString()},
ex);
}
}
/**
* Retrieves AuthenticationData
indexed by the SAML artifact.
* The AuthenticationData
is deleted from the store upon end of this call.
*
* @return AuthenticationData
*/
public AuthenticationData getAuthenticationData(String samlArtifact)
throws AuthenticationException {
String assertionHandle;
try {
assertionHandle = new SAMLArtifactParser(samlArtifact).parseAssertionHandle();
} catch (ParseException ex) {
throw new AuthenticationException("1205", new Object[] { samlArtifact, ex.toString()});
}
AuthenticationData authData = null;
synchronized (authenticationDataStore) {
//System.out.println("assertionHandle: " + assertionHandle);
authData = (AuthenticationData) authenticationDataStore.get(assertionHandle);
if (authData == null) {
Logger.error("Assertion not found for SAML Artifact: " + samlArtifact);
throw new AuthenticationException("1206", new Object[] { samlArtifact });
}
boolean keepAssertion = false;
try {
String boolStr = AuthConfigurationProvider.getInstance().getGenericConfigurationParameter("AuthenticationServer.KeepAssertion");
if (null!=boolStr && boolStr.equalsIgnoreCase("true")) keepAssertion = true;//Only allowed for debug purposes!!!
} catch (ConfigurationException ex) {
throw new AuthenticationException("1205", new Object[] { samlArtifact, ex.toString()});
}
if (!keepAssertion) {
authenticationDataStore.remove(assertionHandle);
}
}
long now = new Date().getTime();
if (now - authData.getTimestamp().getTime() > authDataTimeOut)
throw new AuthenticationException("1207", new Object[] { samlArtifact });
Logger.debug("Assertion delivered for SAML Artifact: " + samlArtifact);
return authData;
}
/**
* Stores authentication data indexed by the assertion handle contained in the
* given saml artifact.
* @param samlArtifact SAML artifact
* @param authData authentication data
* @throws AuthenticationException when SAML artifact is invalid
*/
private void storeAuthenticationData(String samlArtifact, AuthenticationData authData)
throws AuthenticationException {
try {
SAMLArtifactParser parser = new SAMLArtifactParser(samlArtifact);
// check type code 0x0001
byte[] typeCode = parser.parseTypeCode();
if (typeCode[0] != 0 || typeCode[1] != 1)
throw new AuthenticationException("auth.06", new Object[] { samlArtifact });
String assertionHandle = parser.parseAssertionHandle();
synchronized (authenticationDataStore) {
Logger.debug("Assertion stored for SAML Artifact: " + samlArtifact);
authenticationDataStore.put(assertionHandle, authData);
}
} catch (AuthenticationException ex) {
throw ex;
} catch (Throwable ex) {
throw new AuthenticationException("auth.06", new Object[] { samlArtifact });
}
}
/**
* Creates a new session and puts it into the session store.
*
* @param id Session ID
* @return AuthenticationSession created
* @exception AuthenticationException
* thrown when an AuthenticationSession
is running
* already for the given session ID
*/
private static AuthenticationSession newSession() throws AuthenticationException {
String sessionID = Random.nextRandom();
AuthenticationSession newSession = new AuthenticationSession(sessionID);
synchronized (sessionStore) {
AuthenticationSession session = (AuthenticationSession) sessionStore.get(sessionID);
if (session != null)
throw new AuthenticationException("auth.01", new Object[] { sessionID });
sessionStore.put(sessionID, newSession);
}
return newSession;
}
/**
* Retrieves a session from the session store.
*
* @param id session ID
* @return AuthenticationSession
stored with given session ID,
* null
if session ID unknown
*/
public static AuthenticationSession getSession(String id) throws AuthenticationException {
AuthenticationSession session = (AuthenticationSession) sessionStore.get(id);
if (session == null)
throw new AuthenticationException("auth.02", new Object[] { id });
return session;
}
/**
* Cleans up expired session and authentication data stores.
*/
public void cleanup() {
long now = new Date().getTime();
synchronized (sessionStore) {
Set keys = new HashSet(sessionStore.keySet());
for (Iterator iter = keys.iterator(); iter.hasNext();) {
String sessionID = (String) iter.next();
AuthenticationSession session = (AuthenticationSession) sessionStore.get(sessionID);
if (now - session.getTimestampStart().getTime() > sessionTimeOut) {
Logger.info(
MOAIDMessageProvider.getInstance().getMessage(
"cleaner.02",
new Object[] { sessionID }));
sessionStore.remove(sessionID);
}
}
}
synchronized (authenticationDataStore) {
Set keys = new HashSet(authenticationDataStore.keySet());
for (Iterator iter = keys.iterator(); iter.hasNext();) {
String samlAssertionHandle = (String) iter.next();
AuthenticationData authData = (AuthenticationData) authenticationDataStore.get(samlAssertionHandle);
if (now - authData.getTimestamp().getTime() > authDataTimeOut) {
Logger.info(
MOAIDMessageProvider.getInstance().getMessage(
"cleaner.03",
new Object[] { authData.getAssertionID() }));
authenticationDataStore.remove(samlAssertionHandle);
}
}
}
}
/**
* Sets the sessionTimeOut.
* @param seconds Time out of the session in seconds
*/
public void setSecondsSessionTimeOut(long seconds) {
sessionTimeOut = 1000 * seconds;
}
/**
* Sets the authDataTimeOut.
* @param seconds Time out for signing AuthData in seconds
*/
public void setSecondsAuthDataTimeOut(long seconds) {
authDataTimeOut = 1000 * seconds;
}
/**
* Checks a parameter.
* @param param parameter
* @return true if the parameter is null or empty
*/
private boolean isEmpty(String param) {
return param == null || param.length() == 0;
}
/**
* Checks the correctness of SAML attributes and returns its value.
* @param param samlAttribute
* @param i the number of the verified attribute for messages
* @param identifier the infobox identifier for messages
* @param friendlyname the friendly name of the infobox for messages
* @return the SAML attribute value (Element or String)
*/
private static Object verifySAMLAttribute(ExtendedSAMLAttribute samlAttribute, int i, String identifier, String friendlyName)
throws ValidateException{
String name = samlAttribute.getName();
if (name == null) {
Logger.info("The name of SAML-Attribute number " + (i+1) + " returned from " +
identifier + "-infobox validator is null.");
throw new ValidateException(
"validator.45", new Object[] {friendlyName, "Name", String.valueOf((i+1)), "null"});
}
if (name == "") {
Logger.info("The name of SAML-Attribute number " + (i+1) + " returned from " +
identifier + "-infobox validator is empty.");
throw new ValidateException(
"validator.45", new Object[] {friendlyName, "Name", String.valueOf((i+1)), "leer"});
}
if (samlAttribute.getNameSpace() == null) {
Logger.info("The namespace of SAML-Attribute number " + (i+1) + " returned from " +
identifier + "-infobox validator is null.");
throw new ValidateException(
"validator.45", new Object[] {friendlyName, "Namespace", String.valueOf((i+1)), "null"});
}
Object value = samlAttribute.getValue();
if (value == null) {
Logger.info("The value of SAML-Attribute number " + (i+1) + " returned from " +
identifier + "-infobox validator is null.");
throw new ValidateException(
"validator.45", new Object[] {friendlyName ,"Wert", String.valueOf((i+1)), "null"});
}
return value;
}
}