From 19f91c16f69b97c70ffe9a290305737bd351aae8 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 25 Feb 2016 12:17:29 +0100 Subject: solve problems with LogOut and Single LogOut --- .../moa/id/auth/servlet/AbstractController.java | 7 +-- .../id/auth/servlet/IDPSingleLogOutServlet.java | 2 +- .../moa/id/auth/servlet/LogOutServlet.java | 2 +- .../moa/id/data/SLOInformationImpl.java | 24 +++++++-- .../moa/id/data/SLOInformationInterface.java | 7 +++ .../moa/id/moduls/AuthenticationManager.java | 32 +++++++---- .../AbstractAuthProtocolModulController.java | 63 ++++++++++++++-------- .../protocols/ProtocolFinalizationController.java | 23 ++++---- .../id/protocols/pvp2x/AuthenticationAction.java | 2 + .../pvp2x/builder/SingleLogOutBuilder.java | 7 ++- 10 files changed, 119 insertions(+), 50 deletions(-) (limited to 'id/server/idserverlib/src/main/java/at/gv') diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java index 8567d7834..396ffb53d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AbstractController.java @@ -197,15 +197,16 @@ public abstract class AbstractController extends MOAIDAuthConstants { * @param loggedException Exception to log */ protected void logExceptionToTechnicalLog(Throwable loggedException) { - if (!(loggedException instanceof MOAIDException)) { + if (!( loggedException instanceof MOAIDException + || loggedException instanceof ProcessExecutionException )) { Logger.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException); } else { if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) { - Logger.error(loggedException.getMessage(), loggedException); + Logger.warn(loggedException.getMessage(), loggedException); } else { - Logger.error(loggedException.getMessage()); + Logger.info(loggedException.getMessage()); } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java index 307b668b7..6631a1d53 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java @@ -71,7 +71,7 @@ public class IDPSingleLogOutServlet extends AbstractController { @RequestMapping(value = "/idpSingleLogout", method = {RequestMethod.GET}) public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Logger.debug("receive IDP SingleLogOut Request"); + Logger.debug("Receive IDP-initiated SingleLogOut"); String authURL = HTTPUtils.extractAuthURLFromRequest(req); try { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java index 4ed276814..4fcf166c9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java @@ -76,7 +76,7 @@ public class LogOutServlet { @RequestMapping(value = "/LogOut", method = {RequestMethod.POST, RequestMethod.GET}) public void performLogOut(HttpServletRequest req, HttpServletResponse resp) throws IOException { - Logger.debug("receive LogOut Request"); + Logger.debug("Receive simple LogOut Request"); String redirectUrl = (String) req.getParameter(REDIRECT_URL); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java index 55a56056d..2d84bf472 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationImpl.java @@ -40,16 +40,18 @@ public class SLOInformationImpl implements SLOInformationInterface, Serializable private String binding = null; private String serviceURL = null; private String authURL = null; + private String spEntityID = null; - public SLOInformationImpl(String authURL, String sessionID, String nameID, String nameIDFormat, String protocolType) { - new SLOInformationImpl(authURL, sessionID, nameID, nameIDFormat, protocolType, null); + public SLOInformationImpl(String authURL, String spEntityID, String sessionID, String nameID, String nameIDFormat, String protocolType) { + new SLOInformationImpl(authURL, spEntityID, sessionID, nameID, nameIDFormat, protocolType, null); } - public SLOInformationImpl(String authURL, String sessionID, String nameID, String nameIDFormat, String protocolType, SingleLogoutService sloService) { + public SLOInformationImpl(String authURL, String spEntityID, String sessionID, String nameID, String nameIDFormat, String protocolType, SingleLogoutService sloService) { this.sessionIndex = sessionID; this.nameID = nameID; this.nameIDFormat = nameIDFormat; this.protocolType = protocolType; + this.spEntityID = spEntityID; if (authURL.endsWith("/")) this.authURL = authURL.substring(0, authURL.length()-1); @@ -72,6 +74,14 @@ public class SLOInformationImpl implements SLOInformationInterface, Serializable } + + /** + * @return the spEntityID + */ + public String getSpEntityID() { + return spEntityID; + } + /* (non-Javadoc) * @see at.gv.egovernment.moa.id.data.SLOInformationInterface#getSessionIndex() */ @@ -161,6 +171,14 @@ public class SLOInformationImpl implements SLOInformationInterface, Serializable public String getAuthURL() { return authURL; } + + /** + * @param spEntityID the spEntityID to set + */ + public void setSpEntityID(String spEntityID) { + this.spEntityID = spEntityID; + } + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java index b2241f8ed..31fdaacfd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationInterface.java @@ -59,5 +59,12 @@ public interface SLOInformationInterface{ */ public String getUserNameIDFormat(); + /** + * Get the unique entityID of this Service-Provider + * + * @return unique identifier, but never null + */ + public String getSpEntityID(); + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index 22561e435..d76c6d526 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -115,7 +115,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { public void performOnlyIDPLogOut(HttpServletRequest request, HttpServletResponse response, String moaSessionID) { - Logger.info("Logout"); + Logger.info("Remove active user-session"); if(moaSessionID == null) { moaSessionID = (String) request.getParameter(PARAM_SESSIONID); @@ -440,6 +440,8 @@ public class AuthenticationManager extends MOAIDAuthConstants { String pvpSLOIssuer = null; String inboundRelayState = null; + Logger.debug("Start technical Single LogOut process ... "); + if (pvpReq != null) { MOARequest samlReq = (MOARequest) pvpReq.getRequest(); LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); @@ -455,18 +457,25 @@ public class AuthenticationManager extends MOAIDAuthConstants { sloContainer.setSloRequest(pvpReq); sloBuilder.parseActiveIDPs(sloContainer, dbIDPs, pvpSLOIssuer); sloBuilder.parseActiveOAs(sloContainer, dbOAs, pvpSLOIssuer); - + + Logger.debug("Active SSO Service-Provider: " + + " BackChannel:" + sloContainer.getActiveBackChannelOAs().size() + + " FrontChannel:" + sloContainer.getActiveFrontChannalOAs().size() + + " NO_SLO_Support:" + sloContainer.getSloFailedOAs().size()); + //terminate MOASession try { authenticatedSessionStore.destroySession(session.getSessionID()); - ssoManager.deleteSSOSessionID(httpReq, httpResp); - + ssoManager.deleteSSOSessionID(httpReq, httpResp); + Logger.debug("Active SSO Session on IDP is remove."); + } catch (MOADatabaseException e) { Logger.warn("Delete MOASession FAILED."); sloContainer.putFailedOA(pvpReq.getAuthURL()); } + Logger.trace("Starting Service-Provider logout process ... "); //start service provider back channel logout process Iterator nextOAInterator = sloContainer.getNextBackChannelOA(); while (nextOAInterator.hasNext()) { @@ -474,6 +483,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(sloDescr); try { + Logger.trace("Send backchannel SLO Request to " + sloDescr.getSpEntityID()); List soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); LogoutResponse sloResp = null; @@ -483,9 +493,9 @@ public class AuthenticationManager extends MOAIDAuthConstants { } if (sloResp == null) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + Logger.warn("Single LogOut for OA " + sloDescr.getSpEntityID() + " FAILED. NO LogOut response received."); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + sloContainer.putFailedOA(sloDescr.getSpEntityID()); } else { samlVerificationEngine.verifySLOResponse(sloResp, @@ -496,14 +506,14 @@ public class AuthenticationManager extends MOAIDAuthConstants { sloBuilder.checkStatusCode(sloContainer, sloResp); } catch (SOAPException e) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + Logger.warn("Single LogOut for OA " + sloDescr.getSpEntityID() + " FAILED.", e); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + sloContainer.putFailedOA(sloDescr.getSpEntityID()); } catch (SecurityException | InvalidProtocolRequestException e) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + Logger.warn("Single LogOut for OA " + sloDescr.getSpEntityID() + " FAILED.", e); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + sloContainer.putFailedOA(sloDescr.getSpEntityID()); } } @@ -516,6 +526,8 @@ public class AuthenticationManager extends MOAIDAuthConstants { Collection> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); List sloReqList = new ArrayList(); for (Entry el : sloDescr) { + Logger.trace("Build frontChannel SLO Request for " + el.getValue().getSpEntityID()); + LogoutRequest sloReq = sloBuilder.buildSLORequestMessage(el.getValue()); try { sloReqList.add(sloBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java index e6f08abd9..bf00cadaf 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/AbstractAuthProtocolModulController.java @@ -34,6 +34,7 @@ import at.gv.egovernment.moa.id.auth.builder.AuthenticationDataBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.servlet.AbstractController; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; import at.gv.egovernment.moa.id.data.IAuthData; import at.gv.egovernment.moa.id.data.SLOInformationInterface; @@ -99,9 +100,32 @@ public abstract class AbstractAuthProtocolModulController extends AbstractContro } catch (Exception e) { buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + removeUserSession(pendingReq, req, resp); + } } + + protected String createNewSSOSessionCookie(HttpServletRequest req, HttpServletResponse resp, + IRequest pendingReq, AuthenticationSession moaSession) { + Logger.debug("Add SSO information to MOASession."); + + //Store SSO information into database + String newSSOSessionId = ssomanager.createSSOSessionInformations(moaSession.getSessionID(), + pendingReq.getOAURL()); + + //set SSO cookie to response + if (MiscUtil.isNotEmpty(newSSOSessionId)) { + ssomanager.setSSOSessionID(req, resp, newSSOSessionId); + + } else { + ssomanager.deleteSSOSessionID(req, resp); + + } + + return newSSOSessionId; + } + /** * Finalize the requested protocol operation * @@ -118,21 +142,7 @@ public abstract class AbstractAuthProtocolModulController extends AbstractContro //if Single Sign-On functionality is enabled for this request if (pendingReq.needSingleSignOnFunctionality()) { - - Logger.debug("Add SSO information to MOASession."); - - //Store SSO information into database - newSSOSessionId = ssomanager.createSSOSessionInformations(moaSession.getSessionID(), - pendingReq.getOAURL()); - - //set SSO cookie to response - if (MiscUtil.isNotEmpty(newSSOSessionId)) { - ssomanager.setSSOSessionID(req, resp, newSSOSessionId); - - } else { - ssomanager.deleteSSOSessionID(req, resp); - - } + newSSOSessionId = createNewSSOSessionCookie(req, resp, pendingReq, moaSession); } @@ -202,6 +212,23 @@ public abstract class AbstractAuthProtocolModulController extends AbstractContro } + protected void removeUserSession(IRequest pendingReq, HttpServletRequest req, + HttpServletResponse resp) { + try { + AuthenticationSession moaSession = authenticatedSessionStorage.getSession( + pendingReq.getMOASessionIdentifier()); + + if (moaSession != null) + authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + } catch (MOADatabaseException e) { + Logger.error("Remove user-session FAILED." , e); + + } + + + } + protected void buildProtocolSpecificErrorResponse(Throwable throwable, HttpServletRequest req, HttpServletResponse resp, IRequest protocolRequest) throws IOException { try { @@ -226,12 +253,6 @@ public abstract class AbstractAuthProtocolModulController extends AbstractContro //log Error Message statisticLogger.logErrorOperation(throwable, protocolRequest); - //remove MOASession - AuthenticationSession moaSession = authenticatedSessionStorage.getSession( - protocolRequest.getMOASessionIdentifier()); - if (moaSession != null) - authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); - return; } else { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java index 009ef4b6d..a9fc994ec 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/ProtocolFinalizationController.java @@ -75,15 +75,9 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon //build protocol-specific error message if possible buildProtocolSpecificErrorResponse(throwable, req, resp, pendingReq); - - //get MOASession for this pendingRequest - AuthenticationSession moaSession = - authenticatedSessionStorage.getSession( - pendingReq.getMOASessionIdentifier()); - - //remove MOASession if someone is found - if (moaSession != null) - authmanager.performOnlyIDPLogOut(req, resp, moaSession.getSessionID()); + + //remove active user-session + removeUserSession(pendingReq, req, resp); return; @@ -135,9 +129,18 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon //check if pending-request has 'abortedByUser' flag set if (pendingReq.isAbortedByUser()) { + //send authentication aborted error to Service Provider buildProtocolSpecificErrorResponse( new AuthenticationException("auth.21", new Object[] {}), req, resp, pendingReq); + + //do not remove the full active SSO-Session + // in case of only one Service-Provider authentication request is aborted + if ( !(moaSession.isAuthenticated() + && pendingReq.needSingleSignOnFunctionality()) ) { + removeUserSession(pendingReq, req, resp); + + } //check if MOASession and pending-request are authenticated } else if (moaSession.isAuthenticated() && pendingReq.isAuthenticated()) { @@ -155,6 +158,8 @@ public class ProtocolFinalizationController extends AbstractAuthProtocolModulCon Logger.error("Finalize authentication protocol FAILED." , e); buildProtocolSpecificErrorResponse(e, req, resp, pendingReq); + removeUserSession(pendingReq, req, resp); + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java index 21f505bf1..2882f20e1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/AuthenticationAction.java @@ -76,6 +76,7 @@ public class AuthenticationAction implements IAction { DateTime date = new DateTime(); SLOInformationImpl sloInformation = new SLOInformationImpl(); + //build Assertion Assertion assertion = PVP2AssertionBuilder.buildAssertion(pvpRequest, authnRequest, authData, @@ -106,6 +107,7 @@ public class AuthenticationAction implements IAction { //set protocol type sloInformation.setProtocolType(req.requestedModule()); + sloInformation.setSpEntityID(req.getOnlineApplicationConfiguration().getPublicURLPrefix()); return sloInformation; } catch (MessageEncodingException e) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java index a7fc8295a..cffc9378a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java @@ -439,7 +439,7 @@ public class SingleLogOutBuilder { if (!oa.getOaurlprefix().equals(removeOAID)) { //Actually only PVP 2.1 support Single LogOut - if (PVP2XProtocol.PATH.equals(oa.getProtocolType())) { + if (PVP2XProtocol.NAME.equals(oa.getProtocolType())) { SingleLogoutService sloDesc; try { sloDesc = getRequestSLODescriptor(oa.getOaurlprefix()); @@ -447,7 +447,8 @@ public class SingleLogOutBuilder { if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) container.getActiveBackChannelOAs().put(oa.getOaurlprefix(), new SLOInformationImpl( - oa.getAuthURL(), + oa.getAuthURL(), + oa.getOaurlprefix(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), @@ -458,6 +459,7 @@ public class SingleLogOutBuilder { container.getActiveFrontChannalOAs().put(oa.getOaurlprefix(), new SLOInformationImpl( oa.getAuthURL(), + oa.getOaurlprefix(), oa.getAssertionSessionID(), oa.getUserNameID(), oa.getUserNameIDFormat(), @@ -498,6 +500,7 @@ public class SingleLogOutBuilder { container.getActiveFrontChannalOAs().put(el.getIdpurlprefix(), new SLOInformationImpl( el.getAuthURL(), + el.getIdpurlprefix(), el.getSessionIndex(), el.getUserNameID(), NameID.TRANSIENT, -- cgit v1.2.3