package at.gv.egovernment.moa.id.auth; import iaik.pki.PKIException; import iaik.x509.X509Certificate; 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 javax.xml.transform.TransformerException; 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.BPKBuilder; 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.OAParameter; 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.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.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.OutputXML2File; /** * 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"); if (isEmpty(oaURL)) throw new WrongParametersException("StartAuthentication", PARAM_OA); 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); } 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; 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. * * @param authURL URL of the servlet to be used as data URL * @param target "Geschäftsbereich" of the online application requested * @param oaURL online application URL requested * @param bkuURL URL of the "Bürgerkartenumgebung" to be used; * may be null; 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"); //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); } 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); } else { target = null; } 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()); } // BKU URL has not been set yet, even if session already exists if (bkuURL == null) { bkuURL = DEFAULT_BKU; } session.setBkuURL(bkuURL); 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; 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(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); return htmlForm; } /** * Processes an <InfoboxReadResponse> sent by the * security layer implementation.
* * * @param sessionID ID of associated authentication session data * @param xmlInfoboxReadResponse String representation of the * <InfoboxReadResponse> * @return String representation of the <CreateXMLSignatureRequest> */ public String verifyIdentityLink(String sessionID, String xmlInfoboxReadResponse) throws AuthenticationException, ParseException, ConfigurationException, ValidateException, ServiceException { if (isEmpty(sessionID)) throw new AuthenticationException("auth.10", new Object[] { REQ_VERIFY_IDENTITY_LINK, PARAM_SESSIONID}); 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(); // parses the IdentityLink identityLink = new InfoboxReadResponseParser(xmlInfoboxReadResponse).parseIdentityLink(); // validates the identity link IdentityLinkValidator.getInstance().validate(identityLink); // builds a for a call of MOA-SP Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder().build( identityLink, authConf.getMoaSpIdentityLinkTrustProfileID()); // debug output if(null != domVerifyXMLSignatureRequest) OutputXML2File.debugOutputXML2File("VerifyIdentityLinkRequest.xml", domVerifyXMLSignatureRequest, DEBUG_OUTPUT_HIERARCHY); // invokes the call Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker().verifyXMLSignature(domVerifyXMLSignatureRequest); // parses the VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser(domVerifyXMLSignatureResponse).parseData(); // debug output if(null != domVerifyXMLSignatureResponse) OutputXML2File.debugOutputXML2File("VerifyIdentityLinkResponse.xml", domVerifyXMLSignatureResponse, DEBUG_OUTPUT_HIERARCHY); if (identityLink.getIdentificationType().equalsIgnoreCase(Constants.URN_PREFIX_BASEID)) { } OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter( session.getPublicOAURLPrefix()); // if OA is type is business service the manifest validation result has to be ignored boolean ignoreManifestValidationResult = oaParam.getBusinessService() ? true : false; // validates the VerifyXMLSignatureResponseValidator.getInstance().validate( verifyXMLSignatureResponse, authConf.getIdentityLinkX509SubjectNames(), VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK, ignoreManifestValidationResult); session.setIdentityLink(identityLink); // builds the AUTH-block String authBlock = buildAuthenticationBlock(session); // session.setAuthBlock(authBlock); // builds the String[] transformsInfos = oaParam.getTransformsInfos(); if ((transformsInfos == null) || (transformsInfos.length == 0)) { // no OA specific transforms specified, use default ones transformsInfos = authConf.getTransformsInfos(); } String createXMLSignatureRequest = new CreateXMLSignatureRequestBuilder().build(authBlock, oaParam.getKeyBoxIdentifier(), transformsInfos, oaParam.getSlVersion12()); return createXMLSignatureRequest; } /** * Builds an authentication block <saml:Assertion> from given session data. * @param session authentication session * @return <saml:Assertion> as a String */ private String buildAuthenticationBlock(AuthenticationSession session) { IdentityLink identityLink = session.getIdentityLink(); String issuer = identityLink.getGivenName() + " " + identityLink.getFamilyName(); String gebDat = identityLink.getDateOfBirth(); String identificationValue = identityLink.getIdentificationValue(); String identificationType = identityLink.getIdentificationType(); String issueInstant = DateTimeUtils.buildDateTime(Calendar.getInstance()); String authURL = session.getAuthURL(); String target = session.getTarget(); String oaURL = session.getPublicOAURLPrefix(); String authBlock = new AuthenticationBlockAssertionBuilder().buildAuthBlock(issuer, issueInstant, authURL, target, identificationValue, identificationType, oaURL, gebDat); return authBlock; } /** * Processes a <CreateXMLSignatureResponse> sent by the * security layer implementation.
*
    *
  • Validates given <CreateXMLSignatureResponse>
  • *
  • Parses <CreateXMLSignatureResponse> for error codes
  • *
  • Parses authentication block enclosed in * <CreateXMLSignatureResponse>
  • *
  • Verifies authentication block by calling the MOA SP component
  • *
  • Creates authentication data
  • *
  • Creates a corresponding SAML artifact
  • *
  • Stores authentication data in the authentication data store * indexed by the SAML artifact
  • *
  • Deletes authentication session
  • *
  • Returns the SAML artifact, encoded BASE64
  • *
* * @param sessionID session ID of the running authentication session * @param xmlCreateXMLSignatureReadResponse String representation of the * <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 csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureReadResponse).parseResponse(); try { String serializedAssertion = DOMUtils.serializeNode(csresp.getSamlAssertion()); session.setAuthBlock(serializedAssertion); } catch (TransformerException e) { throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE}); } catch (IOException e) { throw new ParseException("parser.04", new Object[] { REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE}); } // validates new CreateXMLSignatureResponseValidator().validate(csresp, session); // builds a for a MOA-SPSS call String[] vtids = authConf.getMoaSpAuthBlockVerifyTransformsInfoIDs(); String tpid = authConf.getMoaSpAuthBlockTrustProfileID(); Element domVsreq = new VerifyXMLSignatureRequestBuilder().build(csresp, vtids, tpid); // debug output if(null != domVsreq) OutputXML2File.debugOutputXML2File("VerifyAuthenticationBlockRequest.xml", domVsreq, DEBUG_OUTPUT_HIERARCHY); // invokes the call Element domVsresp = new SignatureVerificationInvoker().verifyXMLSignature(domVsreq); // debug output if(null != domVsresp) OutputXML2File.debugOutputXML2File("VerifyAuthenticationBlockResponse.xml", domVsresp, DEBUG_OUTPUT_HIERARCHY); // parses the VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponseParser(domVsresp).parseData(); // validates the VerifyXMLSignatureResponseValidator.getInstance().validate( vsresp, null, VerifyXMLSignatureResponseValidator.CHECK_AUTH_BLOCK, true); // 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 <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) 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())); 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()); 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.setWPBK(identityLink.getIdentificationValue()); } else { // only compute bPK if online applcation is a public service String bpkBase64 = new BPKBuilder().buildBPK( identityLink.getIdentificationValue(), session.getTarget()); authData.setPBK(bpkBase64); } String ilAssertion = oaParam.getProvideIdentityLink() ? DOMUtils.serializeNode(identityLink.getSamlAssertion()) : ""; String authBlock = oaParam.getProvideAuthBlock() ? session.getAuthBlock() : ""; String samlAssertion = new AuthenticationDataAssertionBuilder().build(authData, prPerson, authBlock, ilAssertion, session.getBkuURL(), signerCertificateBase64, businessService); authData.setSamlAssertion(samlAssertion); 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) { 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 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 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; } }