aboutsummaryrefslogtreecommitdiff
path: root/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java')
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java522
1 files changed, 522 insertions, 0 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
new file mode 100644
index 000000000..fec2d2b35
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java
@@ -0,0 +1,522 @@
+package at.gv.egovernment.moa.id.protocols.saml1;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.w3c.dom.Element;
+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.AuthenticationServer;
+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.PersonDataBuilder;
+import at.gv.egovernment.moa.id.auth.builder.SAMLArtifactBuilder;
+import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
+import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
+import at.gv.egovernment.moa.id.auth.data.IdentityLink;
+import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser;
+import at.gv.egovernment.moa.id.auth.validator.ValidateException;
+import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;
+import at.gv.egovernment.moa.id.commons.db.dao.config.OASAML1;
+import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.AuthenticationData;
+import at.gv.egovernment.moa.id.moduls.IRequest;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.Base64Utils;
+import at.gv.egovernment.moa.util.Constants;
+import at.gv.egovernment.moa.util.DOMUtils;
+import at.gv.egovernment.moa.util.StringUtils;
+
+public class SAML1AuthenticationServer extends AuthenticationServer {
+
+ private static SAML1AuthenticationServer instance;
+
+ public static SAML1AuthenticationServer getInstace() {
+ if (instance == null)
+ instance = new SAML1AuthenticationServer();
+
+ return instance;
+ }
+
+ //private static Map authenticationDataStore = new HashMap();
+ private static AssertionStorage authenticationDataStore = AssertionStorage.getInstance();
+
+
+ //TODO: make this time configurable
+ /**
+ * time out in milliseconds used by {@link cleanup} for authentication data
+ * store
+ */
+ private static final long authDataTimeOut = 2 * 60 * 1000; // default 2 minutes
+
+
+ public Throwable getErrorResponse(String samlArtifact) throws AuthenticationException {
+ try {
+ new SAMLArtifactParser(samlArtifact).parseAssertionHandle();
+
+ } catch (ParseException ex) {
+ throw new AuthenticationException("1205", new Object[] {
+ samlArtifact, ex.toString() });
+ }
+ Throwable error = null;
+ synchronized (authenticationDataStore) {
+ try {
+ error = authenticationDataStore
+ .get(samlArtifact, Throwable.class);
+
+ authenticationDataStore.remove(samlArtifact);
+
+ } catch (MOADatabaseException e) {
+ Logger.error("Assertion not found for SAML Artifact: " + samlArtifact);
+ throw new AuthenticationException("1206", new Object[] { samlArtifact });
+ }
+
+ }
+
+ return error;
+ }
+
+ /**
+ * 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 getSaml1AuthenticationData(String samlArtifact)
+ throws AuthenticationException {
+ try {
+ 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);
+
+ try {
+ authData = authenticationDataStore
+ .get(samlArtifact, AuthenticationData.class);
+
+ } catch (MOADatabaseException e) {
+ Logger.error("Assertion not found for SAML Artifact: " + samlArtifact);
+ throw new AuthenticationException("1206", new Object[] { samlArtifact });
+ }
+ }
+
+ boolean keepAssertion = false;
+
+ //removed from MOA-ID 2.0 config
+// 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(samlArtifact);
+ }
+
+ 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;
+ }
+
+ public String BuildErrorAssertion(Throwable error, IRequest protocolRequest)
+ throws BuildException, MOADatabaseException {
+
+ String samlArtifact = new SAMLArtifactBuilder().build(
+ protocolRequest.getOAURL(), protocolRequest.getRequestID(),
+ null);
+
+ authenticationDataStore.put(samlArtifact, error);
+
+ return samlArtifact;
+ }
+
+ public String BuildSAMLArtifact(AuthenticationSession session,
+ OAAuthParameter oaParam,
+ AuthenticationData authData)
+ throws ConfigurationException, BuildException, AuthenticationException {
+
+ //Load SAML1 Parameter from OA config
+ OASAML1 saml1parameter = oaParam.getSAML1Parameter();
+
+ boolean useCondition = saml1parameter.isUseCondition();
+ int conditionLength = saml1parameter.getConditionLength().intValue();
+
+ try {
+
+ //set BASE64 encoded signer certificate
+ String signerCertificateBase64 = "";
+ if (saml1parameter.isProvideCertificate()) {
+ byte[] signerCertificate = session.getEncodedSignerCertificate();
+ if (signerCertificate != null) {
+
+ signerCertificateBase64 = Base64Utils
+ .encode(signerCertificate);
+ } else {
+ Logger.info("\"provideCertificate\" is \"true\", but no signer certificate available");
+ }
+ }
+
+ //set prPersion
+ boolean provideStammzahl = saml1parameter.isProvideStammzahl();
+ String prPerson = new PersonDataBuilder().build(authData.getIdentityLink(),
+ provideStammzahl);
+
+ //set Authblock
+ String authBlock = saml1parameter.isProvideAUTHBlock() ? session
+ .getAuthBlock() : "";
+
+ //set IdentityLink for assortion
+ String ilAssertion = saml1parameter.isProvideIdentityLink() ? authData.getIdentityLink()
+ .getSerializedSamlAssertion()
+ : "";
+ if (!saml1parameter.isProvideStammzahl()) {
+ ilAssertion = StringUtils.replaceAll(ilAssertion, authData.getIdentityLink()
+ .getIdentificationValue(), "");
+ }
+
+ String samlAssertion;
+
+ if (session.getUseMandate()) {
+ List oaAttributes = session.getExtendedSAMLAttributesOA();
+
+ if (saml1parameter.isProvideFullMandatorData()) {
+
+ try {
+
+ ExtendedSAMLAttribute[] extendedSAMLAttributes = addExtendedSamlAttributes(
+ session.getMISMandate(), oaParam.getBusinessService(),
+ saml1parameter.isProvideStammzahl());
+
+ if (extendedSAMLAttributes != null) {
+
+ String identifier = "MISService";
+ String friendlyName ="MISService";
+
+ int length = extendedSAMLAttributes.length;
+ for (int i = 0; i < length; i++) {
+ ExtendedSAMLAttribute samlAttribute = extendedSAMLAttributes[i];
+
+ Object value = verifySAMLAttribute(samlAttribute, i, identifier,
+ friendlyName);
+
+ if ((value instanceof String) || (value instanceof Element)) {
+ switch (samlAttribute.getAddToAUTHBlock()) {
+ case ExtendedSAMLAttribute.ADD_TO_AUTHBLOCK:
+ replaceExtendedSAMLAttribute(oaAttributes, samlAttribute);
+ break;
+ case ExtendedSAMLAttribute.NOT_ADD_TO_AUTHBLOCK:
+ replaceExtendedSAMLAttribute(oaAttributes, samlAttribute);
+ break;
+ default:
+ Logger
+ .info("Invalid return value from method \"getAddToAUTHBlock()\" ("
+ + samlAttribute.getAddToAUTHBlock()
+ + ") in SAML attribute number "
+ + (i + 1)
+ + " for infobox " + identifier);
+ throw new ValidateException("validator.47", new Object[] {
+ friendlyName, String.valueOf((i + 1)) });
+ }
+ } else {
+ Logger
+ .info("The type of SAML-Attribute number "
+ + (i + 1)
+ + " returned from "
+ + identifier
+ + "-infobox validator is not valid. Must be either \"java.Lang.String\""
+ + " or \"org.w3c.dom.Element\"");
+ throw new ValidateException("validator.46", new Object[] {
+ identifier, String.valueOf((i + 1)) });
+ }
+ }
+ }
+
+ } 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);
+ }
+ }
+
+ String mandateDate = generateMandateDate(session, oaParam, authData);
+
+ samlAssertion = new AuthenticationDataAssertionBuilder().buildMandate(
+ authData,
+ prPerson,
+ mandateDate,
+ authBlock,
+ ilAssertion,
+ session.getBkuURL(),
+ signerCertificateBase64,
+ oaParam.getBusinessService(),
+ oaAttributes,
+ useCondition,
+ conditionLength);
+
+ } else {
+ samlAssertion = new AuthenticationDataAssertionBuilder().build(
+ authData,
+ prPerson,
+ authBlock,
+ ilAssertion,
+ session.getBkuURL(),
+ signerCertificateBase64,
+ oaParam.getBusinessService(),
+ session.getExtendedSAMLAttributesOA(),
+ useCondition,
+ conditionLength);
+ }
+
+ authData.setSamlAssertion(samlAssertion);
+
+ String samlArtifact = new SAMLArtifactBuilder().build(
+ session.getAuthURL(), session.getSessionID(),
+ saml1parameter.getSourceID());
+
+ storeAuthenticationData(samlArtifact, authData);
+
+ Logger.info("Anmeldedaten zu MOASession " + session.getSessionID()
+ + " angelegt, SAML Artifakt " + samlArtifact);
+ return samlArtifact;
+
+ } catch (Throwable ex) {
+ throw new BuildException("builder.00", new Object[] {
+ "AuthenticationData", ex.toString() }, ex);
+ }
+
+ }
+
+ private String generateMandateDate(AuthenticationSession session,
+ OAAuthParameter oaParam, AuthenticationData authData
+ ) throws AuthenticationException, BuildException,
+ ParseException, ConfigurationException, ServiceException,
+ ValidateException {
+
+ if (session == null)
+ throw new AuthenticationException("auth.10", new Object[] {
+ REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID });
+
+ //AuthenticationSession session = getSession(sessionID);
+ // AuthConfigurationProvider authConf =
+ // AuthConfigurationProvider.getInstance();
+
+ IdentityLink tempIdentityLink = null;
+
+ Element mandate = session.getMandate();
+
+ 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
+ && oaParam.getBusinessService()
+ && identificationType != null
+ && Constants.URN_PREFIX_BASEID
+ .equals(identificationType)) {
+ // now we calculate the wbPK and do so if we got it from the
+ // BKU
+
+
+ //load IdentityLinkDomainType from OAParam
+ String type = oaParam.getIdentityLinkDomainIdentifier();
+ if (type.startsWith(Constants.URN_PREFIX_WBPK + "+"))
+ identificationType = type;
+ else
+ identificationType = Constants.URN_PREFIX_WBPK + "+"
+ + type;
+
+
+ identificationValue = new BPKBuilder().buildWBPK(
+ identificationValue, identificationType);
+ 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(authData.getIdentityLink()
+ .getSamlAssertion());
+ } catch (Exception e) {
+ throw new ValidateException("validator.64", null);
+ }
+
+ }
+
+ }
+
+ Element mandatePerson = tempIdentityLink.getPrPerson();
+
+ String mandateData = null;
+ try {
+
+ boolean provideStammzahl = oaParam.getSAML1Parameter().isProvideStammzahl();
+
+ String oatargetType;
+
+ if(oaParam.getBusinessService()) {
+ oatargetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+session.getDomainIdentifier();
+
+ } else {
+ oatargetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
+ }
+
+ Element prIdentification = (Element) mandatePerson
+ .getElementsByTagNameNS(Constants.PD_NS_URI,
+ "Identification").item(0);
+
+ if (!oatargetType.equals(tempIdentityLink.getIdentificationType())) {
+
+ String isPrPerson = mandatePerson.getAttribute("xsi:type");
+
+ if (!StringUtils.isEmpty(isPrPerson)) {
+ if (isPrPerson.equalsIgnoreCase("pr:PhysicalPerson")) {
+ String baseid = getBaseId(mandatePerson);
+ Element identificationBpK = createIdentificationBPK(mandatePerson,
+ baseid, oaParam.getTarget());
+
+ if (!provideStammzahl) {
+ prIdentification.getFirstChild().setTextContent("");
+ }
+
+ mandatePerson.insertBefore(identificationBpK,
+ prIdentification);
+ }
+ }
+
+ } else {
+
+// Element identificationBpK = mandatePerson.getOwnerDocument()
+// .createElementNS(Constants.PD_NS_URI, "Identification");
+// Element valueBpK = mandatePerson.getOwnerDocument().createElementNS(
+// Constants.PD_NS_URI, "Value");
+//
+// valueBpK.appendChild(mandatePerson.getOwnerDocument().createTextNode(
+// tempIdentityLink.getIdentificationValue()));
+// Element typeBpK = mandatePerson.getOwnerDocument().createElementNS(
+// Constants.PD_NS_URI, "Type");
+// typeBpK.appendChild(mandatePerson.getOwnerDocument().createTextNode(
+// "urn:publicid:gv.at:cdid+bpk"));
+// identificationBpK.appendChild(valueBpK);
+// identificationBpK.appendChild(typeBpK);
+//
+// mandatePerson.insertBefore(identificationBpK, prIdentification);
+ }
+
+
+ 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 });
+ }
+
+ return mandateData;
+ }
+
+
+
+
+ /**
+ * 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 });
+ parser.parseAssertionHandle();
+
+ synchronized (authenticationDataStore) {
+ Logger.debug("Assertion stored for SAML Artifact: "
+ + samlArtifact);
+ authenticationDataStore.put(samlArtifact, authData);
+ }
+
+ } catch (AuthenticationException ex) {
+ throw ex;
+
+ } catch (Throwable ex) {
+ throw new AuthenticationException("auth.06",
+ new Object[] { samlArtifact });
+ }
+ }
+
+}