From 0436de6184c1a95d463da52929e3bf60923d6e04 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 13 Dec 2021 09:23:09 +0100 Subject: update third-party libs and resolve API issues --- .../moa/id/demoOA/servlet/pvp2/Authenticate.java | 529 ++++++++++----------- 1 file changed, 264 insertions(+), 265 deletions(-) (limited to 'id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java') diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java index d4c67cfae..040ec330c 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Authenticate.java @@ -48,12 +48,10 @@ import org.opensaml.common.impl.SecureRandomIdentifierGenerator; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; -import org.opensaml.saml2.common.Extensions; import org.opensaml.saml2.core.AuthnContextClassRef; import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.Issuer; -import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.core.NameIDPolicy; import org.opensaml.saml2.core.NameIDType; import org.opensaml.saml2.core.RequestedAuthnContext; @@ -64,12 +62,10 @@ import org.opensaml.saml2.metadata.SingleSignOnService; import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.ws.transport.http.HttpServletResponseAdapter; -import org.opensaml.xml.XMLObject; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.io.Unmarshaller; import org.opensaml.xml.io.UnmarshallingException; -import org.opensaml.xml.schema.XSAny; import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; import org.opensaml.xml.security.x509.X509Credential; import org.opensaml.xml.signature.Signature; @@ -82,296 +78,299 @@ import org.xml.sax.SAXException; import at.gv.egiz.eaaf.core.api.data.EAAFConstants; import at.gv.egiz.eaaf.core.impl.utils.DOMUtils; -import at.gv.egiz.eaaf.core.impl.utils.EAAFDomEntityResolver; import at.gv.egovernment.moa.id.demoOA.Configuration; import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; import at.gv.egovernment.moa.util.MiscUtil; - - /** * Servlet implementation class Authenticate */ public class Authenticate extends HttpServlet { - private static final long serialVersionUID = 1L; - - private static final Logger log = LoggerFactory - .getLogger(Authenticate.class); - - /** - * @see HttpServlet#HttpServlet() - */ - public Authenticate() { - super(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - try { - builder = factory.newDocumentBuilder(); - - } catch (ParserConfigurationException e) { - log.warn("PVP2 AuthenticationServlet can not be initialized.", e); - } - } - - DocumentBuilder builder; - - - //generate AuthenticationRequest - protected void process(HttpServletRequest request, - HttpServletResponse response, Map legacyParameter) throws ServletException, IOException { - try { - - Configuration config = Configuration.getInstance(); - config.initializePVP2Login(); - - AuthnRequest authReq = SAML2Utils - .createSAMLObject(AuthnRequest.class); - SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); - authReq.setID(gen.generateIdentifier()); - - String relayState = String.valueOf(RandomUtils.nextLong()); - - if (config.useRedirectBindingResponse()) - authReq.setAssertionConsumerServiceIndex(1); - else - authReq.setAssertionConsumerServiceIndex(0); - - authReq.setAttributeConsumingServiceIndex(0); - - authReq.setIssueInstant(new DateTime()); + private static final long serialVersionUID = 1L; + + private static final Logger log = LoggerFactory + .getLogger(Authenticate.class); + + /** + * @see HttpServlet#HttpServlet() + */ + public Authenticate() { + super(); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + builder = factory.newDocumentBuilder(); + + } catch (final ParserConfigurationException e) { + log.warn("PVP2 AuthenticationServlet can not be initialized.", e); + } + } + + DocumentBuilder builder; + + // generate AuthenticationRequest + protected void process(HttpServletRequest request, + HttpServletResponse response, Map legacyParameter) throws ServletException, + IOException { + try { + + final Configuration config = Configuration.getInstance(); + config.initializePVP2Login(); + + AuthnRequest authReq = SAML2Utils + .createSAMLObject(AuthnRequest.class); + final SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + authReq.setID(gen.generateIdentifier()); + + final String relayState = String.valueOf(RandomUtils.nextLong()); + + if (config.useRedirectBindingResponse()) { + authReq.setAssertionConsumerServiceIndex(1); + } else { + authReq.setAssertionConsumerServiceIndex(0); + } + + authReq.setAttributeConsumingServiceIndex(0); + + authReq.setIssueInstant(new DateTime()); // Subject subject = SAML2Utils.createSAMLObject(Subject.class); // NameID name = SAML2Utils.createSAMLObject(NameID.class); - Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); - - String serviceURL = config.getPublicUrlPreFix(request); - if (!serviceURL.endsWith("/")) - serviceURL = serviceURL + "/"; - //name.setValue(serviceURL); - issuer.setValue(serviceURL); - + final Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); + + String serviceURL = config.getPublicUrlPreFix(request); + if (!serviceURL.endsWith("/")) { + serviceURL = serviceURL + "/"; + } + // name.setValue(serviceURL); + issuer.setValue(serviceURL); + // subject.setNameID(name); // authReq.setSubject(subject); - issuer.setFormat(NameIDType.ENTITY); - authReq.setIssuer(issuer); - - if (config.setNameIdPolicy()) { - NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); - policy.setAllowCreate(true); - policy.setFormat(NameID.PERSISTENT); - authReq.setNameIDPolicy(policy); - } - - String entityname = config.getPVP2IDPMetadataEntityName(); - if (MiscUtil.isEmpty(entityname)) { - log.info("No IDP EntityName configurated"); - throw new ConfigurationException("No IDP EntityName configurated"); - } - - //get IDP metadata from metadataprovider - HTTPMetadataProvider idpmetadata = config.getMetaDataProvier(); - EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); - if (idpEntity == null) { - log.info("IDP EntityName is not found in IDP Metadata"); - throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); - } - - //select authentication-service url from metadata - SingleSignOnService redirectEndpoint = null; - for (SingleSignOnService sss : - idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleSignOnServices()) { - - //Get the service address for the binding you wish to use - if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI) && !config.useRedirectBindingRequest()) { - redirectEndpoint = sss; - } - - //Get the service address for the binding you wish to use - if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) && config.useRedirectBindingRequest()) { - redirectEndpoint = sss; - } - - } - - if (redirectEndpoint == null) { - log.warn("Can not find valid EndPoint for SAML2 response"); - throw new ConfigurationException("Can not find valid EndPoint for SAML2 response"); - - } - - authReq.setDestination(redirectEndpoint.getLocation()); - - //authReq.setDestination("http://test.test.test"); - - if (config.setAuthnContextClassRef()) { - RequestedAuthnContext reqAuthContext = - SAML2Utils.createSAMLObject(RequestedAuthnContext.class); - AuthnContextClassRef authnClassRef = - SAML2Utils.createSAMLObject(AuthnContextClassRef.class); - - if (MiscUtil.isNotEmpty(config.getAuthnContextClassRefValue())) { - authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRefValue()); - - } else { - authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); - - } - - reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); - reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); - authReq.setRequestedAuthnContext(reqAuthContext); - } - - if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { - Scoping scope = SAML2Utils.createSAMLObject(Scoping.class); - RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class); - requesterId.setRequesterID(config.getScopeRequesterId()); - scope.getRequesterIDs().add(requesterId ); - authReq.setScoping(scope ); - - } - - if (config.isEidasProxySimulatorEnabled()) { - authReq = injectEidasMsProxyAttributes(request, authReq); - - } - - - //sign authentication request - KeyStore keyStore = config.getPVP2KeyStore(); - X509Credential authcredential = new KeyStoreX509CredentialAdapter( - keyStore, - config.getPVP2KeystoreAuthRequestKeyAlias(), - config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); - - Signature signer = SAML2Utils.createSAMLObject(Signature.class); - signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); - signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); - signer.setSigningCredential(authcredential); - authReq.setSignature(signer); - - - if (!config.useRedirectBindingRequest()) { - //generate Http-POST Binding message - VelocityEngine engine = new VelocityEngine(); - engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); - engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); - engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); - engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); - engine.setProperty("classpath.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); - engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, - "org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); - engine.init(); - - HTTPPostEncoder encoder = new HTTPPostEncoder(engine, - "templates/pvp_postbinding_template.html"); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - response, true); - BasicSAMLMessageContext context = new BasicSAMLMessageContext(); - SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); - service.setLocation(redirectEndpoint.getLocation());; - context.setOutboundSAMLMessageSigningCredential(authcredential); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(authReq); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - encoder.encode(context); - - } else { - //generate Redirect Binding message - HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); - HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( - response, true); - BasicSAMLMessageContext context = new BasicSAMLMessageContext(); - SingleSignOnService service = new SingleSignOnServiceBuilder() - .buildObject(); - service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); - service.setLocation(redirectEndpoint.getLocation()); - context.setOutboundSAMLMessageSigningCredential(authcredential); - context.setPeerEntityEndpoint(service); - context.setOutboundSAMLMessage(authReq); - context.setOutboundMessageTransport(responseAdapter); - context.setRelayState(relayState); - encoder.encode(context); - - } - - } catch (Exception e) { - log.warn("Authentication Request can not be generated", e); - throw new ServletException("Authentication Request can not be generated.", e); - } - } - - - private AuthnRequest injectEidasMsProxyAttributes(HttpServletRequest request, AuthnRequest authReq) - throws SAXException, IOException, ParserConfigurationException, MarshallingException, UnmarshallingException { - - //build extension from template - String xmlTemplate = IOUtils.toString( - Authenticate.class.getResourceAsStream("/templates/reqAttributes.xml"), - StandardCharsets.UTF_8); - - String target = EAAFConstants.URN_PREFIX_EIDAS + "AT+" + getParameterOrDefault(request, "eidasCountry", "DE"); - String loa = EAAFConstants.EIDAS_LOA_PREFIX + getParameterOrDefault(request, "loa", "high"); - String eidasConnector = "https://simple.test/" + getParameterOrDefault(request, "eidasIdPostfix", "test"); - String xmlString = MessageFormat.format(xmlTemplate, target, loa, eidasConnector); + issuer.setFormat(NameIDType.ENTITY); + authReq.setIssuer(issuer); + + if (config.setNameIdPolicy()) { + final NameIDPolicy policy = SAML2Utils.createSAMLObject(NameIDPolicy.class); + policy.setAllowCreate(true); + policy.setFormat(NameIDType.PERSISTENT); + authReq.setNameIDPolicy(policy); + } + + final String entityname = config.getPVP2IDPMetadataEntityName(); + if (MiscUtil.isEmpty(entityname)) { + log.info("No IDP EntityName configurated"); + throw new ConfigurationException("No IDP EntityName configurated"); + } + + // get IDP metadata from metadataprovider + final HTTPMetadataProvider idpmetadata = config.getMetaDataProvier(); + final EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); + if (idpEntity == null) { + log.info("IDP EntityName is not found in IDP Metadata"); + throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); + } + + // select authentication-service url from metadata + SingleSignOnService redirectEndpoint = null; + for (final SingleSignOnService sss : idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS) + .getSingleSignOnServices()) { + + // Get the service address for the binding you wish to use + if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI) && !config + .useRedirectBindingRequest()) { + redirectEndpoint = sss; + } + + // Get the service address for the binding you wish to use + if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI) && config + .useRedirectBindingRequest()) { + redirectEndpoint = sss; + } + + } + + if (redirectEndpoint == null) { + log.warn("Can not find valid EndPoint for SAML2 response"); + throw new ConfigurationException("Can not find valid EndPoint for SAML2 response"); + + } + + authReq.setDestination(redirectEndpoint.getLocation()); + + // authReq.setDestination("http://test.test.test"); + + if (config.setAuthnContextClassRef()) { + final RequestedAuthnContext reqAuthContext = + SAML2Utils.createSAMLObject(RequestedAuthnContext.class); + final AuthnContextClassRef authnClassRef = + SAML2Utils.createSAMLObject(AuthnContextClassRef.class); + + if (MiscUtil.isNotEmpty(config.getAuthnContextClassRefValue())) { + authnClassRef.setAuthnContextClassRef(config.getAuthnContextClassRefValue()); + + } else { + authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); + + } + + reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); + reqAuthContext.getAuthnContextClassRefs().add(authnClassRef); + authReq.setRequestedAuthnContext(reqAuthContext); + } + + if (StringUtils.isNotEmpty(config.getScopeRequesterId())) { + final Scoping scope = SAML2Utils.createSAMLObject(Scoping.class); + final RequesterID requesterId = SAML2Utils.createSAMLObject(RequesterID.class); + requesterId.setRequesterID(config.getScopeRequesterId()); + scope.getRequesterIDs().add(requesterId); + authReq.setScoping(scope); + + } + + if (config.isEidasProxySimulatorEnabled()) { + authReq = injectEidasMsProxyAttributes(request, authReq); + + } + + // sign authentication request + final KeyStore keyStore = config.getPVP2KeyStore(); + final X509Credential authcredential = new KeyStoreX509CredentialAdapter( + keyStore, + config.getPVP2KeystoreAuthRequestKeyAlias(), + config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); + + final Signature signer = SAML2Utils.createSAMLObject(Signature.class); + signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); + signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); + signer.setSigningCredential(authcredential); + authReq.setSignature(signer); + + if (!config.useRedirectBindingRequest()) { + // generate Http-POST Binding message + final VelocityEngine engine = new VelocityEngine(); + engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); + engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); + engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); + engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); + engine.setProperty("classpath.resource.loader.class", + "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, + "org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); + engine.init(); + + final HTTPPostEncoder encoder = new HTTPPostEncoder(engine, + "templates/pvp_postbinding_template.html"); + final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( + response, true); + final BasicSAMLMessageContext context = + new BasicSAMLMessageContext<>(); + final SingleSignOnService service = new SingleSignOnServiceBuilder() + .buildObject(); + service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); + service.setLocation(redirectEndpoint.getLocation()); + context.setOutboundSAMLMessageSigningCredential(authcredential); + context.setPeerEntityEndpoint(service); + context.setOutboundSAMLMessage(authReq); + context.setOutboundMessageTransport(responseAdapter); + context.setRelayState(relayState); + encoder.encode(context); + + } else { + // generate Redirect Binding message + final HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder(); + final HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( + response, true); + final BasicSAMLMessageContext context = + new BasicSAMLMessageContext<>(); + final SingleSignOnService service = new SingleSignOnServiceBuilder() + .buildObject(); + service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + service.setLocation(redirectEndpoint.getLocation()); + context.setOutboundSAMLMessageSigningCredential(authcredential); + context.setPeerEntityEndpoint(service); + context.setOutboundSAMLMessage(authReq); + context.setOutboundMessageTransport(responseAdapter); + context.setRelayState(relayState); + encoder.encode(context); + + } + + } catch (final Exception e) { + log.warn("Authentication Request can not be generated", e); + throw new ServletException("Authentication Request can not be generated.", e); + } + } + + private AuthnRequest injectEidasMsProxyAttributes(HttpServletRequest request, AuthnRequest authReq) + throws SAXException, IOException, ParserConfigurationException, MarshallingException, + UnmarshallingException { + + // build extension from template + final String xmlTemplate = IOUtils.toString( + Authenticate.class.getResourceAsStream("/templates/reqAttributes.xml"), + StandardCharsets.UTF_8); + + final String target = EAAFConstants.URN_PREFIX_EIDAS + "AT+" + getParameterOrDefault(request, + "eidasCountry", "DE"); + final String loa = EAAFConstants.EIDAS_LOA_PREFIX + getParameterOrDefault(request, "loa", "high"); + final String eidasConnector = "https://simple.test/" + getParameterOrDefault(request, "eidasIdPostfix", + "test"); + final String xmlString = MessageFormat.format(xmlTemplate, target, loa, eidasConnector); log.debug("Formated requested attributes: " + xmlString); - - Document extension = DOMUtils.parseDocument(xmlString, false, null, null); - - - //marshalle, inject, and unmarshalle request to set extension - //TODO: find better solution, be it is good enough for a first simple test + + final Document extension = DOMUtils.parseDocument(xmlString, false, null, null); + + // marshalle, inject, and unmarshalle request to set extension + // TODO: find better solution, be it is good enough for a first simple test DocumentBuilder builder; - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); builder = factory.newDocumentBuilder(); - Document document = builder.newDocument(); - Marshaller out = org.opensaml.Configuration.getMarshallerFactory().getMarshaller(authReq); + final Document document = builder.newDocument(); + final Marshaller out = org.opensaml.xml.Configuration.getMarshallerFactory().getMarshaller(authReq); out.marshall(authReq, document); - - Node extElement = document.importNode(extension.getDocumentElement(), true); - //document.getDocumentElement().appendChild(extElement); + + final Node extElement = document.importNode(extension.getDocumentElement(), true); + // document.getDocumentElement().appendChild(extElement); document.getDocumentElement().insertBefore(extElement, document.getChildNodes().item(2)); - - Unmarshaller in = org.opensaml.Configuration.getUnmarshallerFactory().getUnmarshaller(document.getDocumentElement()); + + final Unmarshaller in = org.opensaml.xml.Configuration.getUnmarshallerFactory().getUnmarshaller(document + .getDocumentElement()); return (AuthnRequest) in.unmarshall(document.getDocumentElement()); - + } - - + private String getParameterOrDefault(HttpServletRequest request, String paramName, String defaultValue) { - String reqParam = request.getParameter(paramName); + final String reqParam = request.getParameter(paramName); if (MiscUtil.isEmpty(reqParam)) { return defaultValue; - + } else { return reqParam; - + } - + } + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + process(request, response, null); + } /** - * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - - process(request, response, null); - } - - /** - * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse - * response) - */ - protected void doPost(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - process(request, response, null); - } + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + process(request, response, null); + } } -- cgit v1.2.3