From 82e06bcc6000af413cd6a8efd522a5017d123f86 Mon Sep 17 00:00:00 2001 From: Stephan Schwär Date: Thu, 8 Jul 2021 13:37:04 +0200 Subject: First unfinished work on better ecp error feedback Issue #3797 --- .../edu/kit/scc/dei/ecplean/ECPAuthenticator.java | 83 +++++++++++++++------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java b/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java index 089bc88..702e678 100644 --- a/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java +++ b/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java @@ -2,6 +2,8 @@ package edu.kit.scc.dei.ecplean; import java.io.IOException; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; @@ -24,18 +26,17 @@ import org.xml.sax.SAXException; public class ECPAuthenticator extends ECPAuthenticatorBase { - public ECPAuthenticator(CloseableHttpClient client, String username, String password, - URI idpEcpEndpoint, URI spUrl) { + public ECPAuthenticator(CloseableHttpClient client, String username, String password, URI idpEcpEndpoint, + URI spUrl) { super(client); authInfo = new ECPAuthenticationInfo(username, password, idpEcpEndpoint, spUrl); } - - public ECPAuthenticator(String username, String password, - URI idpEcpEndpoint, URI spUrl) { + + public ECPAuthenticator(String username, String password, URI idpEcpEndpoint, URI spUrl) { super(); authInfo = new ECPAuthenticationInfo(username, password, idpEcpEndpoint, spUrl); } - + public HttpResponse authenticate() throws ECPAuthenticationException { logger.info("Starting authentication"); @@ -43,12 +44,13 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { authInfo.setAuthState(ECPAuthState.INITIAL_PAOS_SP); setChanged(); notifyObservers(authInfo); - + logger.info("Sending initial SP Request"); - + HttpGet httpGet = new HttpGet(authInfo.getSpUrl().toString()); httpGet.setHeader("Accept", "text/html, application/vnd.paos+xml"); - httpGet.setHeader("PAOS", "ver=\"urn:liberty:paos:2003-08\";\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\""); + httpGet.setHeader("PAOS", + "ver=\"urn:liberty:paos:2003-08\";\"urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp\""); HttpClientContext ctx = HttpClientContext.create(); ctx.setCookieStore(new BasicCookieStore()); @@ -62,7 +64,7 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { logger.debug("Initial SP Request failed"); throw new ECPAuthenticationException(e); } - + Document initResponse; try { initResponse = buildDocumentFromString(responseBody); @@ -70,7 +72,7 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { logger.debug("Parsing SP Response failed"); throw new ECPAuthenticationException(e); } - + String relayState; try { relayState = (String) queryDocument(initResponse, "//ecp:RelayState", XPathConstants.STRING); @@ -81,7 +83,8 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { logger.info("Got relayState: " + relayState); String responseConsumerUrl; try { - responseConsumerUrl = (String) queryDocument(initResponse, "/S:Envelope/S:Header/paos:Request/@responseConsumerURL", XPathConstants.STRING); + responseConsumerUrl = (String) queryDocument(initResponse, + "/S:Envelope/S:Header/paos:Request/@responseConsumerURL", XPathConstants.STRING); } catch (XPathException e) { logger.debug("Could not find response consumer url in PAOS answer from SP"); throw new ECPAuthenticationException(e); @@ -104,23 +107,29 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { throw e; } - String statusCode = getStatusCode(idpResponse); + List statusCodes = getStatusCode(idpResponse); - if (statusCode == null) + if (statusCodes.isEmpty()) throw new ECPAuthenticationException("IdP returned no status code!!!x"); - if (!statusCode.endsWith(":Success") && !statusCode.endsWith(":success")) - throw new ECPAuthenticationException("IdP Returned StatusCode " + statusCode); - + if (!statusCodes.get(0).endsWith(":Success") && !statusCodes.get(0).endsWith(":success")) { + String allCodes = ""; + for (String sCode : statusCodes) { + allCodes = allCodes + sCode + "\n"; + } + throw new ECPAuthenticationException("IdP Returned StatusCodes:\n" + allCodes); + } + String assertionConsumerUrl; try { - assertionConsumerUrl = (String) queryDocument(idpResponse, "/S:Envelope/S:Header/ecp:Response/@AssertionConsumerServiceURL", XPathConstants.STRING); + assertionConsumerUrl = (String) queryDocument(idpResponse, + "/S:Envelope/S:Header/ecp:Response/@AssertionConsumerServiceURL", XPathConstants.STRING); } catch (Exception e) { logger.debug("Could not find assertion consumer url in answer from IdP"); throw new ECPAuthenticationException(e); } logger.info("Got assertionConsumerUrl: " + assertionConsumerUrl); - if (! assertionConsumerUrl.equals(responseConsumerUrl)) { + if (!assertionConsumerUrl.equals(responseConsumerUrl)) { throw new ECPAuthenticationException("Assertion- and ResponseConsumerURL don't match"); } @@ -139,7 +148,7 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { logger.debug("Could not post assertion back to SP"); throw new ECPAuthenticationException(e); } - + logger.info("Requesting original URL"); httpGet = new HttpGet(authInfo.getSpUrl().toString()); try { @@ -151,16 +160,27 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { return httpResponse; } - private String getStatusCode(Document idpResponse) { + /** + * Parse the IDP Response for the status code. + * + * @param idpResponse + * @return A list of strings of messages returned by the IDP or an empty list on + * error. + */ + private List getStatusCode(Document idpResponse) { NodeList nl; - String result = null; + List result = new ArrayList(); try { nl = (NodeList) queryDocument(idpResponse, "//*", XPathConstants.NODESET); } catch (XPathException e) { - return null; + result.clear(); + return result; } - if (nl == null) - return null; + if (nl == null) { + result.clear(); + return result; + } + for (int i = 0; i < nl.getLength(); ++i) { Node ns = nl.item(i); if (!ns.getLocalName().endsWith("StatusCode")) @@ -170,8 +190,17 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { Node val = ns.getAttributes().getNamedItem("Value"); if (val == null) continue; - if (result == null || result.endsWith(":Responder")) { - result = val.getNodeValue(); + + if (result.isEmpty() || result.get(0).endsWith(":Responder")) { + result.clear(); + result.add(val.getNodeValue()); + logger.debug("Current idpResponse status code result: " + result); + NodeList subnodes = ns.getChildNodes(); + if (subnodes.getLength() != 0) { + Node subval = subnodes.item(0).getAttributes().getNamedItem("Value"); + if (subval != null) + result.add(subval.getNodeValue()); + } } } return result; -- cgit v1.2.3-55-g7522