summaryrefslogtreecommitdiff
path: root/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java')
-rw-r--r--eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java247
1 files changed, 247 insertions, 0 deletions
diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
new file mode 100644
index 00000000..1c7a9652
--- /dev/null
+++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/utils/Saml2Utils.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a
+ * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology.
+ *
+ * Licensed under the EUPL, Version 1.2 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:
+ * https://joinup.ec.europa.eu/news/understanding-eupl-v12
+ *
+ * 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.egiz.eaaf.modules.pvp2.impl.utils;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.Validator;
+import at.gv.egiz.eaaf.core.impl.utils.Random;
+import at.gv.egiz.eaaf.modules.pvp2.PvpConstants;
+import at.gv.egiz.eaaf.modules.pvp2.api.reqattr.EaafRequestedAttribute;
+import org.apache.commons.lang3.StringUtils;
+import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
+import org.opensaml.common.xml.SAMLSchemaBuilder;
+import org.opensaml.saml2.core.Attribute;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.metadata.AssertionConsumerService;
+import org.opensaml.saml2.metadata.SPSSODescriptor;
+import org.opensaml.ws.soap.soap11.Body;
+import org.opensaml.ws.soap.soap11.Envelope;
+import org.opensaml.xml.XMLObject;
+import org.opensaml.xml.XMLObjectBuilderFactory;
+import org.opensaml.xml.io.Marshaller;
+import org.opensaml.xml.io.MarshallingException;
+import org.opensaml.xml.schema.XSString;
+import org.opensaml.xml.schema.impl.XSStringBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+public class Saml2Utils {
+ private static final Logger log = LoggerFactory.getLogger(Saml2Utils.class);
+
+ private static SecureRandomIdentifierGenerator idGenerator;
+
+ private static DocumentBuilder builder;
+
+ static {
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+
+ try {
+ builder = factory.newDocumentBuilder();
+
+ } catch (final ParserConfigurationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ try {
+ idGenerator = new SecureRandomIdentifierGenerator();
+
+ } catch (final NoSuchAlgorithmException e) {
+ e.printStackTrace();
+
+ }
+ }
+
+ /**
+ * Create a SAML2 object.
+ *
+ * @param <T> SAML2 object class
+ * @param clazz object class
+ * @return SAML2 object
+ */
+ public static <T> T createSamlObject(final Class<T> clazz) {
+ try {
+ final XMLObjectBuilderFactory builderFactory =
+ org.opensaml.xml.Configuration.getBuilderFactory();
+
+ final QName defaultElementName =
+ (QName) clazz.getDeclaredField("DEFAULT_ELEMENT_NAME").get(null);
+ @SuppressWarnings("unchecked")
+ final T object =
+ (T) builderFactory.getBuilder(defaultElementName).buildObject(defaultElementName);
+ return object;
+ } catch (final Throwable e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * Get a new SAML2 conform random value.
+ *
+ * @return
+ */
+ public static String getSecureIdentifier() {
+ return "_".concat(Random.nextHexRandom16());
+
+ }
+
+
+ /**
+ * Transform SAML2 Object to Element.
+ *
+ * @param object SAML2 object
+ * @return Element
+ * @throws IOException In case of an transformation error
+ * @throws MarshallingException In case of an transformation error
+ * @throws TransformerException In case of an transformation error
+ */
+ public static Document asDomDocument(final XMLObject object)
+ throws IOException, MarshallingException, TransformerException {
+ final Document document = builder.newDocument();
+ final Marshaller out =
+ org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(object);
+ out.marshall(object, document);
+ return document;
+ }
+
+ /**
+ * Build success status element.
+ *
+ * @return
+ */
+ public static Status getSuccessStatus() {
+ final Status status = Saml2Utils.createSamlObject(Status.class);
+ final StatusCode statusCode = Saml2Utils.createSamlObject(StatusCode.class);
+ statusCode.setValue(StatusCode.SUCCESS_URI);
+ status.setStatusCode(statusCode);
+ return status;
+ }
+
+ /**
+ * Get AssertionConsumerService Index from metadata element.
+ *
+ * @param spSsoDescriptor metadata element
+ * @return
+ */
+ public static int getDefaultAssertionConsumerServiceIndex(final SPSSODescriptor spSsoDescriptor) {
+
+ final List<AssertionConsumerService> assertionConsumerList =
+ spSsoDescriptor.getAssertionConsumerServices();
+
+ for (final AssertionConsumerService el : assertionConsumerList) {
+ if (el.isDefault()) {
+ return el.getIndex();
+ }
+
+ }
+
+ return 0;
+ }
+
+ /**
+ * Build SOAP11 body from SAML2 object.
+ *
+ * @param payload SAML2 object
+ * @return
+ */
+ public static Envelope buildSoap11Envelope(final XMLObject payload) {
+ final XMLObjectBuilderFactory bf = org.opensaml.xml.Configuration.getBuilderFactory();
+ final Envelope envelope = (Envelope) bf.getBuilder(Envelope.DEFAULT_ELEMENT_NAME)
+ .buildObject(Envelope.DEFAULT_ELEMENT_NAME);
+ final Body body =
+ (Body) bf.getBuilder(Body.DEFAULT_ELEMENT_NAME).buildObject(Body.DEFAULT_ELEMENT_NAME);
+
+ body.getUnknownXMLObjects().add(payload);
+ envelope.setBody(body);
+
+ return envelope;
+ }
+
+ /**
+ * Generate EAAF specific requested attribute.
+ *
+ * @param attr SAML2 attribute definition
+ * @param isRequired is-mandatory flag
+ * @param value Attribute value
+ * @return
+ */
+ public static EaafRequestedAttribute generateReqAuthnAttributeSimple(final Attribute attr,
+ final boolean isRequired, final String value) {
+ final EaafRequestedAttribute requested =
+ Saml2Utils.createSamlObject(EaafRequestedAttribute.class);
+ requested.setName(attr.getName());
+ requested.setNameFormat(attr.getNameFormat());
+ requested.setFriendlyName(attr.getFriendlyName());
+ requested.setIsRequired(String.valueOf(isRequired));
+ final List<XMLObject> attributeValues = requested.getAttributeValues();
+ if (StringUtils.isNotEmpty(value)) {
+ final XMLObject attributeValueForRequest =
+ createAttributeValue(PvpConstants.EIDAS_REQUESTED_ATTRIBUTE_VALUE_TYPE, value);
+ attributeValues.add(attributeValueForRequest);
+ }
+ return requested;
+
+ }
+
+ /**
+ * Perform XML schema-validation on SAML2 object.
+ *
+ * @param xmlObject SAML2 object
+ * @throws Exception In case of a validation error
+ */
+ public static void schemeValidation(final XMLObject xmlObject) throws Exception {
+ try {
+ final Schema test = SAMLSchemaBuilder.getSAML11Schema();
+ final Validator val = test.newValidator();
+ final DOMSource source = new DOMSource(xmlObject.getDOM());
+ val.validate(source);
+ log.debug("SAML2 Scheme validation successful");
+ return;
+
+ } catch (final Exception e) {
+ log.warn("SAML2 scheme validation FAILED.", e);
+ throw e;
+
+ }
+ }
+
+ private static XMLObject createAttributeValue(final QName attributeValueType,
+ final String value) {
+ final XSStringBuilder stringBuilder = (XSStringBuilder) org.opensaml.xml.Configuration
+ .getBuilderFactory().getBuilder(XSString.TYPE_NAME);
+ final XSString stringValue = stringBuilder.buildObject(attributeValueType, XSString.TYPE_NAME);
+ stringValue.setValue(value);
+ return stringValue;
+
+ }
+}