From aec1b5913057d515d90a5f1a63ebdb763bd3065d Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Fri, 20 Sep 2019 12:38:26 +0200 Subject: Support retrying authentication without an @... suffix automatically --- .../edu/kit/scc/dei/ecplean/ECPAuthenticator.java | 17 +++++- .../kit/scc/dei/ecplean/ECPAuthenticatorBase.java | 69 ++++++++++++++++------ 2 files changed, 65 insertions(+), 21 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 b727fea..089bc88 100644 --- a/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java +++ b/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticator.java @@ -67,7 +67,7 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { try { initResponse = buildDocumentFromString(responseBody); } catch (IOException | SAXException | ParserConfigurationException e) { - logger.debug("Parsing SP Request failed"); + logger.debug("Parsing SP Response failed"); throw new ECPAuthenticationException(e); } @@ -90,8 +90,19 @@ public class ECPAuthenticator extends ECPAuthenticatorBase { Node firstChild = initResponse.getDocumentElement().getFirstChild(); initResponse.getDocumentElement().removeChild(firstChild); - - Document idpResponse = authenticateIdP(initResponse); + + Document idpResponse; + try { + idpResponse = authenticateIdP(initResponse); + } catch (ECPAuthenticationException e) { + logger.debug("Original SP response:\n" + responseBody); + try { + logger.debug("Sent to IdP:\n" + documentToString(initResponse)); + } catch (TransformerException e1) { + logger.debug("Barf", e1); + } + throw e; + } String statusCode = getStatusCode(idpResponse); diff --git a/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticatorBase.java b/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticatorBase.java index 56148e1..e40097c 100644 --- a/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticatorBase.java +++ b/src/main/java/edu/kit/scc/dei/ecplean/ECPAuthenticatorBase.java @@ -3,6 +3,7 @@ package edu.kit.scc.dei.ecplean; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import java.util.Observable; import javax.xml.namespace.QName; @@ -49,6 +50,8 @@ public abstract class ECPAuthenticatorBase extends Observable { protected NamespaceResolver namespaceResolver; protected TransformerFactory transformerFactory; + protected boolean retryWithoutAt; + public ECPAuthenticatorBase(CloseableHttpClient client) { this.client = client == null ? HttpClients.createSystem() : client; @@ -67,33 +70,59 @@ public abstract class ECPAuthenticatorBase extends Observable { public ECPAuthenticatorBase() { this(null); } - - protected Document authenticateIdP(Document idpRequest) - throws ECPAuthenticationException { - logger.info("Sending initial IdP Request"); + + private HttpResponse exec(Document idpRequest, String user, String pass) + throws ECPAuthenticationException { BasicCredentialsProvider bcp = new BasicCredentialsProvider(); - bcp.setCredentials(new AuthScope(authInfo.getIdpEcpEndpoint().getHost(), authInfo.getIdpEcpEndpoint().getPort()), - new UsernamePasswordCredentials(authInfo.getUsername(), authInfo.getPassword())); + bcp.setCredentials(new AuthScope(authInfo.getIdpEcpEndpoint().getHost(), authInfo.getIdpEcpEndpoint() + .getPort()), new UsernamePasswordCredentials(user, pass)); HttpClientContext passwordContext = HttpClientContext.create(); - passwordContext.setCredentialsProvider(bcp); - - HttpPost httpPost = new HttpPost(authInfo.getIdpEcpEndpoint().toString()); - HttpResponse httpResponse; + HttpPost httpPost = new HttpPost(authInfo.getIdpEcpEndpoint().toString()); try { httpPost.setEntity(new StringEntity(documentToString(idpRequest))); - httpPost.setHeader("Content-Type", "text/xml; charset=utf-8"); - httpResponse = client.execute(httpPost, passwordContext); - - if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - throw new ECPAuthenticationException("User not authorized"); - } + } catch (UnsupportedEncodingException | TransformerException e1) { + logger.debug("Error setting XML payload of IdP POST"); + throw new ECPAuthenticationException(e1); + } + httpPost.setHeader("Content-Type", "text/xml; charset=utf-8"); + passwordContext.setCredentialsProvider(bcp); + try { + return client.execute(httpPost, passwordContext); } catch (Exception e) { httpPost.reset(); logger.debug("Could not submit PAOS request to IdP"); throw new ECPAuthenticationException(e); } + } + protected Document authenticateIdP(Document idpRequest) throws ECPAuthenticationException { + logger.info("Sending initial IdP Request"); + + HttpResponse httpResponse = null; + String user = authInfo.getUsername(); + String pass = authInfo.getPassword(); + int at = user.lastIndexOf('@'); + boolean failed = false; + try { + httpResponse = exec(idpRequest, user, pass); + failed = (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED); + } catch (ECPAuthenticationException e) { + logger.debug("Could not submit PAOS request to IdP"); + if (at == -1) + throw new ECPAuthenticationException(e); + failed = true; + } + if (at != -1 && failed && retryWithoutAt) { + // Retrying without the @ in the username is desired + user = user.substring(0, at); + try { + httpResponse = exec(idpRequest, user, pass); + } catch (ECPAuthenticationException e) { + logger.debug("Could not submit PAOS request to IdP"); + throw new ECPAuthenticationException(e); + } + } String responseBody; try { responseBody = EntityUtils.toString(httpResponse.getEntity()); @@ -102,12 +131,12 @@ public abstract class ECPAuthenticatorBase extends Observable { throw new ECPAuthenticationException(e); } try { - httpPost.reset(); return buildDocumentFromString(responseBody); } catch (IOException | SAXException | ParserConfigurationException | RuntimeException e) { logger.debug("Could not parse XML response from IdP:\n" + responseBody); throw new ECPAuthenticationException(e); - } + } + } protected Document buildDocumentFromString(String input) @@ -145,4 +174,8 @@ public abstract class ECPAuthenticatorBase extends Observable { return client; } + public void setRetryWithoutAt(boolean b) { + this.retryWithoutAt = b; + } + } \ No newline at end of file -- cgit v1.2.3-55-g7522