aboutsummaryrefslogtreecommitdiff
path: root/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java')
-rw-r--r--id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java648
1 files changed, 648 insertions, 0 deletions
diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java
new file mode 100644
index 000000000..e9d9c7175
--- /dev/null
+++ b/id.server/src/at/gv/egovernment/moa/id/auth/AuthenticationServer.java
@@ -0,0 +1,648 @@
+package at.gv.egovernment.moa.id.auth;
+
+import iaik.pki.PKIException;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.w3c.dom.Element;
+
+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.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.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.VPKBuilder;
+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.IdentityLink;
+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.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.ValidateException;
+import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator;
+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.data.AuthenticationData;
+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.logging.Logger;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.DateTimeUtils;
+import at.gv.egovernment.moa.util.FileUtils;
+
+/**
+ * API for MOA ID Authentication Service.<br>
+ * {@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 <code>AuthenticationServer</code>.
+ *
+ * @return the single instance of <code>AuthenticationServer</code>
+ */
+ public static AuthenticationServer getInstance() {
+ if (instance == null)
+ instance = new AuthenticationServer();
+ return instance;
+ }
+ /**
+ * Constructor for AuthenticationServer.
+ */
+ public AuthenticationServer() {
+ super();
+ }
+ /**
+ * Processes request to select a BKU.
+ * <br/>Processing depends on value of {@link AuthConfigurationProvider#getBKUSelectionType}.
+ * <br/>For <code>bkuSelectionType==HTMLComplete</code>, a <code>returnURI</code> for the
+ * "BKU Auswahl" service is returned.
+ * <br/>For <code>bkuSelectionType==HTMLSelect</code>, an HTML form for BKU selection is returned.
+ * @param authURL base URL of MOA-ID Auth component
+ * @param target "Gesch&auml;ftsbereich"
+ * @param oaURL online application URL requested
+ * @param bkuSelectionTemplateURL template for BKU selection form to be used
+ * in case of <code>HTMLSelect</code>; may be null
+ * @param templateURL URL providing an HTML template for the HTML form to be used
+ * for call <code>startAuthentication</code>
+ * @return for <code>bkuSelectionType==HTMLComplete</code>, the <code>returnURI</code> for the
+ * "BKU Auswahl" service;
+ * for <code>bkuSelectionType==HTMLSelect</code>, 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 {
+
+ if (isEmpty(authURL))
+ throw new WrongParametersException("StartAuthentication", "AuthURL");
+ if (isEmpty(target))
+ throw new WrongParametersException("StartAuthentication", PARAM_TARGET);
+ if (isEmpty(oaURL))
+ throw new WrongParametersException("StartAuthentication", PARAM_OA);
+ if (! authURL.startsWith("https:"))
+ throw new AuthenticationException("auth.07", null);
+ 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});
+ 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);
+ 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.03", new Object[] {bkuConnParam.getUrl(), ex.toString()}, ex);
+ }
+ String bkuSelectionTemplate = null;
+ 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 new String(SSLUtils.readHttpsURL(conf, connParam));
+ else
+ return new String(FileUtils.readURL(connParam.getUrl()));
+ }
+ /**
+ * Processes the beginning of an authentication session.
+ * <ul>
+ * <li>Starts an authentication session</li>
+ * <li>Creates an <code>&lt;InfoboxReadRequest&gt;</code></li>
+ * <li>Creates an HTML form for querying the identity link from the
+ * security layer implementation.
+ * <br>Form parameters include
+ * <ul>
+ * <li>the <code>&lt;InfoboxReadRequest&gt;</code></li>
+ * <li>the data URL where the security layer implementation sends it response to</li>
+ * </ul>
+ * </ul>
+ * @param authURL URL of the servlet to be used as data URL
+ * @param target "Gesch&auml;ftsbereich" of the online application requested
+ * @param oaURL online application URL requested
+ * @param bkuURL URL of the "B&uuml;rgerkartenumgebung" to be used;
+ * may be <code>null</code>; in this case, the default location will be used
+ * @param templateURL URL providing an HTML template for the HTML form generated
+ * @return HTML form
+ * @throws AuthenticationException
+ * @see GetIdentityLinkFormBuilder
+ * @see InfoboxReadRequestBuilder
+ */
+ public String startAuthentication(
+ String authURL, String target, String oaURL, String templateURL, String bkuURL, String sessionID)
+ throws WrongParametersException, AuthenticationException, ConfigurationException, BuildException {
+
+ if (isEmpty(sessionID)) {
+ if (isEmpty(authURL))
+ throw new WrongParametersException("StartAuthentication", "AuthURL");
+ if (! authURL.startsWith("https:"))
+ throw new AuthenticationException("auth.07", null);
+ if (isEmpty(target))
+ throw new WrongParametersException("StartAuthentication", PARAM_TARGET);
+ if (isEmpty(oaURL))
+ throw new WrongParametersException("StartAuthentication", PARAM_OA);
+ }
+ AuthenticationSession session;
+ if (sessionID != null)
+ session = getSession(sessionID);
+ else {
+ OAAuthParameter oaParam =
+ AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);
+ if (oaParam == null)
+ throw new AuthenticationException("auth.00", new Object[] {oaURL});
+ session = newSession();
+ Logger.info("MOASession " + session.getSessionID() + " angelegt");
+ session.setTarget(target);
+ session.setOAURLRequested(oaURL);
+ session.setPublicOAURLPrefix(oaParam.getPublicURLPrefix());
+ session.setAuthURL(authURL);
+ session.setTemplateURL(templateURL);
+ }
+ String infoboxReadRequest = new InfoboxReadRequestBuilder().build();
+ String dataURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(), REQ_VERIFY_IDENTITY_LINK, session.getSessionID());
+ String template = null;
+ if (session.getTemplateURL() != null) {
+ try {
+ template = new String(FileUtils.readURL(session.getTemplateURL()));
+ }
+ catch (IOException ex) {
+ throw new AuthenticationException("auth.03", new Object[] {session.getTemplateURL(), ex.toString()}, ex);
+ }
+ }
+ String certInfoRequest = new CertInfoVerifyXMLSignatureRequestBuilder().build();
+ String certInfoDataURL = new DataURLBuilder().buildDataURL(
+ session.getAuthURL(), REQ_START_AUTHENTICATION, session.getSessionID());
+ String htmlForm = new GetIdentityLinkFormBuilder().build(
+ template, bkuURL, infoboxReadRequest, dataURL, certInfoRequest, certInfoDataURL);
+ return htmlForm;
+ }
+ /**
+ * Processes an <code>&lt;InfoboxReadResponse&gt;</code> sent by the
+ * security layer implementation.<br>
+ * <ul>
+ * <li>Validates given <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * <li>Parses identity link enclosed in <code>&lt;InfoboxReadResponse&gt;</code></li>
+ * <li>Verifies identity link by calling the MOA SP component</li>
+ * <li>Checks certificate authority of identity link</li>
+ * <li>Stores identity link in the session</li>
+ * <li>Creates an authentication block to be signed by the user</li>
+ * <li>Creates and returns a <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ * containg the authentication block, meant to be returned to the
+ * security layer implementation</li>
+ * </ul>
+ *
+ * @param sessionID ID of associated authentication session data
+ * @param xmlInfoboxReadResponse String representation of the
+ * <code>&lt;InfoboxReadResponse&gt;</code>
+ * @return String representation of the <code>&lt;CreateXMLSignatureRequest&gt;</code>
+ */
+ public String verifyIdentityLink (String sessionID, String xmlInfoboxReadResponse)
+ throws AuthenticationException, ParseException, ConfigurationException, ValidateException, ServiceException, WrongParametersException {
+
+ if (isEmpty(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID);
+ if (isEmpty(xmlInfoboxReadResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", 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 <InfoboxReadResponse>
+ IdentityLink identityLink = new InfoboxReadResponseParser(xmlInfoboxReadResponse).
+ parseIdentityLink();
+ // validates the identity link
+ IdentityLinkValidator.getInstance().validate(identityLink);
+ // builds a <VerifyXMLSignatureRequest> for a call of MOA-SP
+ Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder().build(
+ identityLink, authConf.getMoaSpIdentityLinkTrustProfileID());
+ // debug output
+ debugOutputXMLFile("VerifyIdentityLinkRequest.xml", domVerifyXMLSignatureRequest);
+ // invokes the call
+ Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker().
+ verifyXMLSignature(domVerifyXMLSignatureRequest);
+ // parses the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponse verifyXMLSignatureResponse =
+ new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData();
+ // debug output
+ debugOutputXMLFile("VerifyIdentityLinkResponse.xml", domVerifyXMLSignatureResponse);
+ // validates the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponseValidator.getInstance().validate(
+ verifyXMLSignatureResponse,
+ authConf.getIdentityLinkX509SubjectNames(),
+ VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK);
+
+ session.setIdentityLink(identityLink);
+ // builds the AUTH-block
+ String authBlock = buildAuthenticationBlock(session);
+ session.setAuthBlock(authBlock);
+ // builds the <CreateXMLSignatureRequest>
+ String[] transformInfos = authConf.getTransformsInfos();
+ String createXMLSignatureRequest = new CreateXMLSignatureRequestBuilder().
+ build(authBlock, transformInfos);
+ return createXMLSignatureRequest;
+ }
+ /**
+ * Builds an authentication block <code>&lt;saml:Assertion&gt;</code> from given session data.
+ * @param session authentication session
+ * @return <code>&lt;saml:Assertion&gt;</code> as a String
+ */
+ private String buildAuthenticationBlock(AuthenticationSession session) {
+ IdentityLink identityLink = session.getIdentityLink();
+ String issuer = identityLink.getGivenName() + " " + identityLink.getFamilyName();
+ String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance());
+ String authURL = session.getAuthURL();
+ String target = session.getTarget();
+ String oaURL = session.getPublicOAURLPrefix();
+ String authBlock = new AuthenticationBlockAssertionBuilder().
+ build(issuer, issueInstant, authURL, target, oaURL);
+ return authBlock;
+ }
+ /**
+ * Processes a <code>&lt;CreateXMLSignatureResponse&gt;</code> sent by the
+ * security layer implementation.<br>
+ * <ul>
+ * <li>Validates given <code>&lt;CreateXMLSignatureResponse&gt;</code></li>
+ * <li>Parses <code>&lt;CreateXMLSignatureResponse&gt;</code> for error codes</li>
+ * <li>Parses authentication block enclosed in
+ * <code>&lt;CreateXMLSignatureResponse&gt;</code></li>
+ * <li>Verifies authentication block by calling the MOA SP component</li>
+ * <li>Creates authentication data</li>
+ * <li>Creates a corresponding SAML artifact</li>
+ * <li>Stores authentication data in the authentication data store
+ * indexed by the SAML artifact</li>
+ * <li>Deletes authentication session</li>
+ * <li>Returns the SAML artifact, encoded BASE64</li>
+ * </ul>
+ *
+ * @param sessionID session ID of the running authentication session
+ * @param xmlCreateXMLSignatureReadResponse String representation of the
+ * <code>&lt;CreateXMLSignatureResponse&gt;</code>
+ * @return SAML artifact needed for retrieving authentication data, encoded BASE64
+ */
+ public String verifyAuthenticationBlock(
+ String sessionID, String xmlCreateXMLSignatureReadResponse)
+ throws AuthenticationException, BuildException, ParseException, ConfigurationException, ServiceException, ValidateException, WrongParametersException {
+
+ if (isEmpty(sessionID))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID);
+ if (isEmpty(xmlCreateXMLSignatureReadResponse))
+ throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE);
+ AuthenticationSession session = getSession(sessionID);
+ AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
+ // parses <CreateXMLSignatureResponse>
+ CreateXMLSignatureResponse csresp =
+ new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureReadResponse).parseResponse();
+ // validates <CreateXMLSignatureResponse>
+ new CreateXMLSignatureResponseValidator().validate(csresp, session.getTarget(), session.getPublicOAURLPrefix());
+ // builds a <VerifyXMLSignatureRequest> for a MOA-SPSS call
+ String[] vtids = authConf.getMoaSpAuthBlockVerifyTransformsInfoIDs();
+ String tpid = authConf.getMoaSpAuthBlockTrustProfileID();
+ Element domVsreq = new VerifyXMLSignatureRequestBuilder().build(csresp, vtids, tpid);
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockRequest.xml", domVsreq);
+ // invokes the call
+ Element domVsresp = new SignatureVerificationInvoker().verifyXMLSignature(domVsreq);
+ // parses the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponseParser(domVsresp).parseData();
+ // debug output
+ AuthenticationServer.debugOutputXMLFile("VerifyAuthenticationBlockResponse.xml", domVsresp);
+ // validates the <VerifyXMLSignatureResponse>
+ VerifyXMLSignatureResponseValidator.getInstance().validate(
+ vsresp, null,VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK);
+ // compares the public keys from the identityLink with the AuthBlock
+ VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(vsresp, session.getIdentityLink());
+
+ // builds authentication data and stores it together with a SAML artifact
+ AuthenticationData authData = buildAuthenticationData(session, vsresp);
+ String samlArtifact = new SAMLArtifactBuilder().build(session.getAuthURL(), session.getSessionID());
+ storeAuthenticationData(samlArtifact, authData);
+ // invalidates the authentication session
+ sessionStore.remove(sessionID);
+ Logger.info("Anmeldedaten zu MOASession " + sessionID + " angelegt, SAML Artifakt " + samlArtifact);
+ return samlArtifact;
+ }
+ /**
+ * Builds the AuthenticationData object together with the
+ * corresponding <code>&lt;saml:Assertion&gt;</code>
+ * @param session authentication session
+ * @param verifyXMLSigResp VerifyXMLSignatureResponse from MOA-SP
+ * @return AuthenticationData object
+ * @throws ConfigurationException while accessing configuration data
+ * @throws BuildException while building the <code>&lt;saml:Assertion&gt;</code>
+ */
+ private AuthenticationData buildAuthenticationData(
+ AuthenticationSession session,
+ VerifyXMLSignatureResponse verifyXMLSigResp)
+ throws ConfigurationException, BuildException {
+
+ IdentityLink identityLink = session.getIdentityLink();
+ AuthenticationData authData = new AuthenticationData();
+ authData.setMajorVersion(1);
+ authData.setMinorVersion(0);
+ authData.setAssertionID(Random.nextRandom());
+ authData.setIssuer(session.getAuthURL());
+ authData.setIssueInstant(DateTimeUtils.buildDateTime(Calendar.getInstance()));
+ String vpkBase64 = new VPKBuilder().buildVPK(
+ identityLink.getIdentificationValue(), identityLink.getDateOfBirth(), session.getTarget());
+ authData.setVPK(vpkBase64);
+ authData.setGivenName(identityLink.getGivenName());
+ authData.setFamilyName(identityLink.getFamilyName());
+ authData.setDateOfBirth(identityLink.getDateOfBirth());
+ authData.setQualifiedCertificate(verifyXMLSigResp.isQualifiedCertificate());
+ authData.setPublicAuthority(verifyXMLSigResp.isPublicAuthority());
+ authData.setPublicAuthorityCode(verifyXMLSigResp.getPublicAuthorityCode());
+ OAAuthParameter oaParam =
+ AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
+ session.getPublicOAURLPrefix());
+ String prPerson = new PersonDataBuilder().build(
+ identityLink, oaParam.getProvideZMRZahl());
+
+ try {
+ String ilAssertion =
+ oaParam.getProvideIdentityLink() ? DOMUtils.serializeNode(identityLink.getSamlAssertion()) : "";
+ String authBlock = oaParam.getProvideAuthBlock() ? session.getAuthBlock() : "";
+ String samlAssertion = new AuthenticationDataAssertionBuilder().build(
+ authData, prPerson, authBlock, ilAssertion);
+ authData.setSamlAssertion(samlAssertion);
+ return authData;
+ }
+ catch (Throwable ex) {
+ throw new BuildException(
+ "builder.00",
+ new Object[] { "AuthenticationData", ex.toString() },
+ ex);
+ }
+ }
+ /**
+ * Retrieves <code>AuthenticationData</code> indexed by the SAML artifact.
+ * The <code>AuthenticationData</code> is deleted from the store upon end of this call.
+ *
+ * @return <code>AuthenticationData</code>
+ */
+ 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) {
+ authData = (AuthenticationData)authenticationDataStore.get(assertionHandle);
+ if (authData == null) {
+ Logger.error("Assertion not found for SAML Artifact: " + samlArtifact);
+ throw new AuthenticationException("1206", new Object[] {samlArtifact});
+ }
+ 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 <code>AuthenticationSession</code> 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 <code>AuthenticationSession</code> stored with given session ID,
+ * <code>null</code> 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 samlArtifact = (String) iter.next();
+ AuthenticationData authData = (AuthenticationData) authenticationDataStore.get(samlArtifact);
+ if (now - authData.getTimestamp().getTime() > authDataTimeOut) {
+ Logger.info(MOAIDMessageProvider.getInstance().getMessage("cleaner.03", new Object[] {samlArtifact}));
+ authenticationDataStore.remove(samlArtifact);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets the sessionTimeOut.
+ * @param sessionTimeOut time out in seconds
+ */
+ public void setSecondsSessionTimeOut(long seconds) {
+ sessionTimeOut = 1000 * seconds;
+ }
+ /**
+ * Sets the authDataTimeOut.
+ * @param authDataTimeOut time out 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;
+ }
+
+ /**
+ * Writes an XML structure to file for debugging purposes, encoding UTF-8.
+ *
+ * @param filename file name
+ * @param rootElem root element in DOM tree
+ */
+ public static void debugOutputXMLFile(String filename, Element rootElem) {
+ if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) {
+ try {
+ String xmlString = new String(DOMUtils.serializeNode(rootElem));
+ debugOutputXMLFile(filename, xmlString);
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ /**
+ * Writes an XML structure to file for debugging purposes, encoding UTF-8.
+ *
+ * @param filename file name
+ * @param xmlString XML string
+ */
+ public static void debugOutputXMLFile(String filename, String xmlString) {
+ if (Logger.isDebugEnabled(DEBUG_OUTPUT_HIERARCHY)) {
+ try {
+ java.io.OutputStream fout = new java.io.FileOutputStream(filename);
+ byte[] xmlData = xmlString.getBytes("UTF-8");
+ fout.write(xmlData);
+ fout.close();
+ }
+ catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+}