From 18f7c6609058ed5c3bfb59c625682f4f4a53d75d Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Fri, 19 Feb 2016 10:22:11 +0100 Subject: refactor Single Sign-On authentication consents evaluator to get executed by processEngine --- id/server/doc/handbook/protocol/protocol.html | 4 + .../id/auth/builder/SendAssertionFormBuilder.java | 78 ++- .../id/auth/modules/AbstractAuthServletTask.java | 20 + .../modules/SingleSignOnConsentsModuleImpl.java | 69 +++ .../tasks/EvaluateSSOConsentsTaskImpl.java | 115 +++++ .../internal/tasks/FinalizeAuthenticationTask.java | 16 +- .../GenerateSSOConsentEvaluatorFrameTask.java | 87 ++++ .../id/auth/servlet/SSOSendAssertionServlet.java | 177 ------- .../moa/id/moduls/AuthenticationManager.java | 550 ++++++++++----------- ...t.gv.egovernment.moa.id.auth.modules.AuthModule | 2 +- .../SingleSignOnConsentEvaluator.process.xml | 20 + .../main/resources/moaid.authentication.beans.xml | 6 + .../resources/properties/id_messages_de.properties | 3 +- .../protocol_response_statuscodes_de.properties | 1 + 14 files changed, 627 insertions(+), 521 deletions(-) create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java create mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java delete mode 100644 id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java create mode 100644 id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml diff --git a/id/server/doc/handbook/protocol/protocol.html b/id/server/doc/handbook/protocol/protocol.html index 6214c393c..a3a06bc6d 100644 --- a/id/server/doc/handbook/protocol/protocol.html +++ b/id/server/doc/handbook/protocol/protocol.html @@ -606,6 +606,10 @@ Redirect Binding 1109 Fehler beim Validieren der SZR-Gateway Response + + 1110 + Ungültige Single Sign-On Session +
1.3.1.3 STORK (12xxx)
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java index d14910319..7121935b0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/SendAssertionFormBuilder.java @@ -34,7 +34,8 @@ import java.net.URI; import org.apache.commons.io.IOUtils; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory; -import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.util.FormBuildUtils; import at.gv.egovernment.moa.logging.Logger; @@ -46,8 +47,6 @@ public class SendAssertionFormBuilder { private static final String TEMPLATEBGCOLOR = "style=\"background-color: #COLOR#\""; private static String URL = "#URL#"; - private static String MODUL = "#MODUL#"; - private static String ACTION = "#ACTION#"; private static String ID = "#ID#"; private static String OANAME = "#OAName#"; private static String CONTEXTPATH = "#CONTEXTPATH#"; @@ -56,8 +55,7 @@ public class SendAssertionFormBuilder { private static String SERVLET = CONTEXTPATH+"/SSOSendAssertionServlet"; - private static String getTemplate() { - + private static String getTemplate() { String pathLocation; InputStream input = null; try { @@ -68,12 +66,9 @@ public class SendAssertionFormBuilder { File file = new File(new URI(pathLocation)); input = new FileInputStream(file); - } catch (FileNotFoundException e) { - - Logger.warn("No LoginFormTempaltes found. Use Generic Templates from package."); - - pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; - + } catch (FileNotFoundException e) { + Logger.warn("No LoginFormTempaltes found. Use Generic Templates from package."); + pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; input = Thread.currentThread() .getContextClassLoader() .getResourceAsStream(pathLocation); @@ -82,48 +77,43 @@ public class SendAssertionFormBuilder { return getTemplate(input); - } catch (Exception e) { + } catch (Exception e) { + return null; + + } finally { try { - input.close(); + if (input != null) + input.close(); - } catch (IOException e1) { + } catch (IOException e) { Logger.warn("SendAssertionTemplate inputstream can not be closed.", e); + } - - return null; - } - + } } private static String getTemplate(InputStream input) { + String template = null; + try { - String template = null; - - try { - - StringWriter writer = new StringWriter(); - IOUtils.copy(input, writer); - template = writer.toString(); - template = template.replace(URL, SERVLET); - - } catch (Exception e) { - Logger.error("Failed to read template", e); - - } finally { - try { - input.close(); - - } catch (IOException e) { - Logger.warn("SendAssertionTemplate inputstream can not be closed.", e); - } - } + StringWriter writer = new StringWriter(); + IOUtils.copy(input, writer); + template = writer.toString(); + template = template.replace(URL, SERVLET); + + } catch (Exception e) { + Logger.error("Failed to read template", e); + } return template; } - public static String buildForm(String modul, String action, String id, OAAuthParameter oaParam, String contextpath) { + public static String buildForm(IRequest pendingReq) { String value = null; + String contextpath = pendingReq.getAuthURL(); + IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); + byte[] oatemplate = oaParam.getSendAssertionTemplate(); // OA specific template requires a size of 8 bits minimum if (oatemplate != null && oatemplate.length > 7) { @@ -137,15 +127,7 @@ public class SendAssertionFormBuilder { } if(value != null) { -// if(modul == null) { -// modul = SAML1Protocol.PATH; -// } -// if(action == null) { -// action = SAML1Protocol.GETARTIFACT; -// } - value = value.replace(MODUL, modul); - value = value.replace(ACTION, action); - value = value.replace(ID, id); + value = value.replace(ID, pendingReq.getRequestID()); value = value.replace(OANAME, oaParam.getFriendlyName()); if (contextpath.endsWith("/")) diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java index 68d5ae299..559d4fd4f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java @@ -12,6 +12,7 @@ import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; @@ -25,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; @@ -33,6 +35,7 @@ import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.IRequestStorage; import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.process.springweb.MoaIdTask; +import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; import at.gv.egovernment.moa.id.storage.IAuthenticationSessionStoreage; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -95,6 +98,23 @@ public abstract class AbstractAuthServletTask extends MoaIdTask { } + /** + * Redirect the authentication process to protocol specific finalization endpoint. + * + * @param pendingReq Actually processed protocol specific authentication request + * @param httpResp + */ + protected void performRedirectToProtocolFinialization(IRequest pendingReq, HttpServletResponse httpResp) { + String redirectURL = new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), + AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, pendingReq.getRequestID()); + + httpResp.setContentType("text/html"); + httpResp.setStatus(302); + httpResp.addHeader("Location", redirectURL); + Logger.debug("REDIRECT TO: " + redirectURL); + + } + /** * Parses the request input stream for parameters, assuming parameters are * encoded UTF-8 (no standard exists how browsers should encode them). diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java new file mode 100644 index 000000000..d64126de6 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/SingleSignOnConsentsModuleImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * @author tlenz + * + */ +public class SingleSignOnConsentsModuleImpl implements AuthModule { + + public static final String PARAM_SSO_CONSENTS_EVALUATION = "ssoconsentsevaluation"; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getPriority() + */ + @Override + public int getPriority() { + return 0; + + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#selectProcess(at.gv.egovernment.moa.id.process.api.ExecutionContext) + */ + @Override + public String selectProcess(ExecutionContext context) { + Object evaluationObj = context.get(PARAM_SSO_CONSENTS_EVALUATION); + if (evaluationObj != null && evaluationObj instanceof Boolean) { + boolean evaluateSSOConsents = (boolean) evaluationObj; + if (evaluateSSOConsents) { + return "SSOConsentsEvluationProcess"; + + } + } + + return null; + } + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.auth.modules.AuthModule#getProcessDefinitions() + */ + @Override + public String[] getProcessDefinitions() { + return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml" }; + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java new file mode 100644 index 000000000..8dcb63550 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/EvaluateSSOConsentsTaskImpl.java @@ -0,0 +1,115 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.beans.factory.annotation.Autowired; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * Evaluate the Single Sign-On user consent + * + * @author tlenz + * + */ +public class EvaluateSSOConsentsTaskImpl extends AbstractAuthServletTask { + + private static final String PARAM_SSO_CONSENTS = "value"; + + @Autowired private SSOManager ssoManager; + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //evaluate SSO consents flag + String ssoConsentsString = request.getParameter(PARAM_SSO_CONSENTS); + ssoConsentsString = StringEscapeUtils.escapeHtml(ssoConsentsString); + if (!ParamValidatorUtils.isValidUseMandate(ssoConsentsString)) + throw new WrongParametersException("EvaluateSSOConsentsTaskImpl", PARAM_SSO_CONSENTS, null); + + boolean ssoConsents = false; + if (MiscUtil.isNotEmpty(ssoConsentsString)) + ssoConsents = Boolean.parseBoolean(ssoConsentsString); + + //perform default task initialization + defaultTaskInitialization(request, executionContext); + + //check SSO session cookie and MOASession object + String ssoId = ssoManager.getSSOSessionID(request); + boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); + if (!(isValidSSOSession && moasession.isAuthenticated() )) { + Logger.info("Single Sign-On consents evaluator found NO valid SSO session. Stopping authentication process ..."); + throw new AuthenticationException("auth.30", null); + + } + + //Log consents evaluator event to revisionslog + revisionsLogger.logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_FINISHED, String.valueOf(ssoConsents)); + + //user allow single sign-on authentication + if (ssoConsents) { + //authenticate pending-request + pendingReq.setAuthenticated(true); + + //store pending-request + requestStoreage.storePendingRequest(pendingReq); + + //redirect to auth. protocol finalization + performRedirectToProtocolFinialization(pendingReq, response); + + } else { + //user deny single sign-on authentication + throw new AuthenticationException("auth.21", new Object[] {}); + + } + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java index 4fd43b6ba..d1d2cdca8 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/FinalizeAuthenticationTask.java @@ -28,14 +28,12 @@ import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Service; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.moduls.RequestImpl; import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; @@ -93,7 +91,6 @@ public class FinalizeAuthenticationTask extends AbstractAuthServletTask { } - //set MOASession to authenticated and store MOASession moasession.setAuthenticated(true); String newMOASessionID = authenticatedSessionStorage.changeSessionID(moasession); @@ -103,16 +100,9 @@ public class FinalizeAuthenticationTask extends AbstractAuthServletTask { pendingReq.setAuthenticated(true); requestStoreage.storePendingRequest(pendingReq); - Logger.info("AuthProcess finished. Redirect to Protocol Dispatcher."); - - String redirectURL = new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), - AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, pendingReq.getRequestID()); - - response.setContentType("text/html"); - response.setStatus(302); - response.addHeader("Location", redirectURL); - Logger.debug("REDIRECT TO: " + redirectURL); - + Logger.info("AuthProcess finished. Redirect to Protocol Dispatcher."); + performRedirectToProtocolFinialization(pendingReq, response); + } catch (MOAIDException e) { throw new TaskExecutionException(pendingReq, e.getMessage(), e); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java new file mode 100644 index 000000000..f9f121520 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GenerateSSOConsentEvaluatorFrameTask.java @@ -0,0 +1,87 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 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: + * http://www.osor.eu/eupl/ + * + * 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.egovernment.moa.id.auth.modules.internal.tasks; + +import java.io.PrintWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; +import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.logging.Logger; + +/** + * Build a Single Sign-On consents evaluator form + * + * @author tlenz + * + */ +public class GenerateSSOConsentEvaluatorFrameTask extends AbstractAuthServletTask { + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.process.springweb.MoaIdTask#execute(at.gv.egovernment.moa.id.process.api.ExecutionContext, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) + throws TaskExecutionException { + try { + //perform default task initialization + defaultTaskInitialization(request, executionContext); + + //set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + //build consents evaluator form + String form = SendAssertionFormBuilder.buildForm(pendingReq); + + //store pending request + requestStoreage.storePendingRequest(pendingReq); + + //Log consents evaluator event to revisionslog + revisionsLogger.logEvent(pendingReq.getOnlineApplicationConfiguration(), + pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); + + //write form to response object + response.setContentType("text/html;charset=UTF-8"); + PrintWriter out = new PrintWriter(response.getOutputStream()); + out.print(form); + out.flush(); + + + } catch (MOAIDException e) { + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } catch (Exception e) { + Logger.warn("FinalizeAuthenticationTask has an internal error", e); + throw new TaskExecutionException(pendingReq, e.getMessage(), e); + + } + + } + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java deleted file mode 100644 index 4c895e387..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/SSOSendAssertionServlet.java +++ /dev/null @@ -1,177 +0,0 @@ -///******************************************************************************* -// * Copyright 2014 Federal Chancellery Austria -// * MOA-ID has been developed in a cooperation between BRZ, the Federal -// * Chancellery Austria - ICT staff unit, and Graz University of Technology. -// * -// * Licensed under the EUPL, Version 1.1 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: -// * http://www.osor.eu/eupl/ -// * -// * 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.egovernment.moa.id.auth.servlet; -// -//import java.io.IOException; -// -//import javax.servlet.ServletException; -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -// -//import org.apache.commons.lang.StringEscapeUtils; -// -//import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants; -//import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger; -//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.exception.WrongParametersException; -//import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; -//import at.gv.egovernment.moa.id.moduls.IRequest; -//import at.gv.egovernment.moa.id.moduls.RequestStorage; -//import at.gv.egovernment.moa.id.moduls.SSOManager; -//import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -//import at.gv.egovernment.moa.id.util.ParamValidatorUtils; -//import at.gv.egovernment.moa.logging.Logger; -//import at.gv.egovernment.moa.util.MiscUtil; -// -//public class SSOSendAssertionServlet extends AuthServlet{ -// -// private static final long serialVersionUID = 1L; -// -// private static final String PARAM = "value"; -// private static final String MODULE = "mod"; -// private static final String ACTION = "action"; -// private static final String ID = "identifier"; -// -// protected void doPost(HttpServletRequest req, HttpServletResponse resp) -// throws ServletException, IOException { -// -// String id = null; -// Logger.debug("Receive " + SSOSendAssertionServlet.class + " Request"); -// try { -// -// Object idObject = req.getParameter(ID); -// -// if (idObject != null && (idObject instanceof String)) { -// id = (String) idObject; -// } -// -// String value = req.getParameter(PARAM); -// value = StringEscapeUtils.escapeHtml(value); -// if (!ParamValidatorUtils.isValidUseMandate(value)) -// throw new WrongParametersException("SSOSendAssertionServlet", PARAM, null); -// -// //get module and action -// Object moduleObject = req.getParameter(MODULE); -// String module = null; -// if (moduleObject != null && (moduleObject instanceof String)) { -// module = (String) moduleObject; -// } -// -// -// Object actionObject = req.getParameter(ACTION); -// String action = null; -// if (actionObject != null && (actionObject instanceof String)) { -// action = (String) actionObject; -// } -// -// if (MiscUtil.isEmpty(module) || MiscUtil.isEmpty(action) || MiscUtil.isEmpty(id)) { -// Logger.warn("No Moduel or Action parameter received!"); -// throw new WrongParametersException("Module or Action is empty", "", "auth.10"); -// } -// -// -// SSOManager ssomanager = SSOManager.getInstance(); -// //get SSO Cookie for Request -// String ssoId = ssomanager.getSSOSessionID(req); -// -// //check SSO session -// if (ssoId != null) { -// String correspondingMOASession = ssomanager.existsOldSSOSession(ssoId); -// -// if (correspondingMOASession != null) { -// Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + -// "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); -// -// -// AuthenticationSessionStoreage.destroySession(correspondingMOASession); -// -// ssomanager.deleteSSOSessionID(req, resp); -// } -// } -// -// boolean isValidSSOSession = ssomanager.isValidSSOSession(ssoId, null); -// -// String moaSessionID = null; -// -// if (isValidSSOSession) { -// -// -// //check UseMandate flag -// String valueString = null;; -// if ((value != null) && (value.compareTo("") != 0)) { -// valueString = value; -// } else { -// valueString = "false"; -// } -// -// if (valueString.compareToIgnoreCase("true") == 0) { -// moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoId); -// AuthenticationSession moasession = AuthenticationSessionStoreage.getSession(moaSessionID); -// AuthenticationSessionStoreage.setAuthenticated(moaSessionID, true); -// -// //log event -// //String pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(moaSessionID); -// IRequest pendingReq = RequestStorage.getPendingRequest(id); -// MOAReversionLogger.getInstance().logEvent(pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_FINISHED); -// -// //TODO: only for development!!!!!!! -//// String redirectURL = new DataURLBuilder().buildDataURL(moasession.getAuthURL(), -//// ModulUtils.buildAuthURL(module, action, id), ""); -// -// String redirectURL = "Remove commants in Class:SSOSendAssertionServlet Line:141"; -// -// resp.setContentType("text/html"); -// resp.setStatus(302); -// -// -// resp.addHeader("Location", redirectURL); -// Logger.debug("REDIRECT TO: " + redirectURL); -// -// } -// -// else { -// throw new AuthenticationException("auth.21", new Object[] {}); -// } -// -// } else { -// handleError("SSO Session is not valid", null, req, resp, id); -// } -// -// -// } catch (MOADatabaseException e) { -// handleError("SSO Session is not found", e, req, resp, id); -// -// } catch (WrongParametersException e) { -// handleError("Parameter is not valid", e, req, resp, id); -// -// } catch (AuthenticationException e) { -// handleError(e.getMessage(), e, req, resp, id); -// -// } catch (Exception e) { -// Logger.error("SSOSendAssertion has an interal Error.", e); -// } -// -// } -// -//} 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 4131e49fc..7863c684e 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 @@ -23,7 +23,6 @@ package at.gv.egovernment.moa.id.moduls; import java.io.IOException; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; @@ -53,6 +52,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions; import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.SingleSignOnConsentsModuleImpl; import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration; import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; @@ -101,52 +101,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { public AuthenticationManager() { } - - /** - * Checks if a authenticated MOASession already exists and if {protocolRequest} is authenticated - * - * @param protocolRequest Authentication request which is actually in process - * @param moaSession MOASession with authentication information or null if no MOASession exists - * - * @return true if session is already authenticated, otherwise false - * @throws MOAIDException - */ - private boolean tryPerformAuthentication(RequestImpl protocolRequest, AuthenticationSession moaSession) { - - //if no MOASession exist -> authentication is required - if (moaSession == null) { - return false; - } else { - //if MOASession is Found but not authenticated --> authentication is required - if (!moaSession.isAuthenticated()) { - return false; - } - - //if MOASession is already authenticated and protocol-request is authenticated - // --> no authentication is required any more - else if (moaSession.isAuthenticated() && protocolRequest.isAuthenticated()) { - return true; - - // if MOASession is authenticated and SSO is allowed --> authenticate pendingRequest - } else if (!protocolRequest.isAuthenticated() - && moaSession.isAuthenticated() && protocolRequest.needSingleSignOnFunctionality()) { - Logger.debug("Found active MOASession and SSO is allowed --> pendingRequest is authenticted"); - protocolRequest.setAuthenticated(true); - protocolRequest.setMOASessionIdentifier(moaSession.getSessionID()); - return true; - - } - - // force authentication as backup solution - else { - Logger.warn("Authentication-required check find an unsuspected state --> force authentication"); - return false; - - } - } - } - public void performSingleLogOut(HttpServletRequest httpReq, HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { performSingleLogOut(httpReq, httpResp, session, pvpReq, null); @@ -159,163 +114,6 @@ public class AuthenticationManager extends MOAIDAuthConstants { } - - private void performSingleLogOut(HttpServletRequest httpReq, - HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException { - String pvpSLOIssuer = null; - String inboundRelayState = null; - - if (pvpReq != null) { - MOARequest samlReq = (MOARequest) pvpReq.getRequest(); - LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); - pvpSLOIssuer = logOutReq.getIssuer().getValue(); - inboundRelayState = samlReq.getRelayState(); - - } - - //store active OAs to SLOContaine - List dbOAs = authenticatedSessionStore.getAllActiveOAFromMOASession(session); - List dbIDPs = authenticatedSessionStore.getAllActiveIDPsFromMOASession(session); - SLOInformationContainer sloContainer = new SLOInformationContainer(); - sloContainer.setSloRequest(pvpReq); - sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer); - sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer); - - //terminate MOASession - try { - authenticatedSessionStore.destroySession(session.getSessionID()); - ssoManager.deleteSSOSessionID(httpReq, httpResp); - - } catch (MOADatabaseException e) { - Logger.warn("Delete MOASession FAILED."); - sloContainer.putFailedOA(pvpReq.getAuthURL()); - - } - - //start service provider back channel logout process - Iterator nextOAInterator = sloContainer.getNextBackChannelOA(); - while (nextOAInterator.hasNext()) { - SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); - - try { - List soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); - - LogoutResponse sloResp = null; - for (XMLObject el : soapResp) { - if (el instanceof LogoutResponse) - sloResp = (LogoutResponse) el; - } - - if (sloResp == null) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() - + " FAILED. NO LogOut response received."); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); - - } else { - SAMLVerificationEngine engine = new SAMLVerificationEngine(); - engine.verifySLOResponse(sloResp, - TrustEngineFactory.getSignatureKnownKeysTrustEngine()); - - } - - SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); - - } catch (SOAPException e) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() - + " FAILED.", e); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); - - } catch (SecurityException | InvalidProtocolRequestException e) { - Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() - + " FAILED.", e); - sloContainer.putFailedOA(sloReq.getIssuer().getValue()); - - } - } - - //start service provider front channel logout process - try { - if (sloContainer.hasFrontChannelOA()) { - String relayState = Random.nextRandom(); - - Collection> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); - List sloReqList = new ArrayList(); - for (Entry el : sloDescr) { - LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue()); - try { - sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), - sloReq, httpReq, httpResp, relayState)); - - } catch (Exception e) { - Logger.warn("Failed to build SLO request for OA:" + el.getKey()); - sloContainer.putFailedOA(el.getKey()); - - } - } - - //put SLO process-information into transaction storage - transactionStorage.put(relayState, sloContainer); - - if (MiscUtil.isEmpty(authURL)) - authURL = pvpReq.getAuthURL(); - - String timeOutURL = authURL - + "/idpSingleLogout" - + "?restart=" + relayState; - - VelocityContext context = new VelocityContext(); - context.put("redirectURLs", sloReqList); - context.put("timeoutURL", timeOutURL); - context.put("timeout", SLOTIMEOUT); - ssoManager.printSingleLogOutInfo(context, httpResp); - - - } else { - if (pvpReq != null) { - //send SLO response to SLO request issuer - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); - - } else { - //print SLO information directly - VelocityContext context = new VelocityContext(); - if (sloContainer.getSloFailedOAs() == null || - sloContainer.getSloFailedOAs().size() == 0) - context.put("successMsg", - MOAIDMessageProvider.getInstance().getMessage("slo.00", null)); - else - context.put("errorMsg", - MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssoManager.printSingleLogOutInfo(context, httpResp); - - } - - } - - } catch (MOADatabaseException e) { - Logger.error("MOA AssertionDatabase ERROR", e); - if (pvpReq != null) { - SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); - LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); - SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); - - }else { - //print SLO information directly - VelocityContext context = new VelocityContext(); - context.put("errorMsg", - MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); - ssoManager.printSingleLogOutInfo(context, httpResp); - - } - - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - public void performOnlyIDPLogOut(HttpServletRequest request, HttpServletResponse response, String moaSessionID) { Logger.info("Logout"); @@ -387,7 +185,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { //check if interfederation IDP is requested ssoManager.checkInterfederationIsRequested(httpReq, httpResp, pendingReq); - //check SSO session + //check if SSO session cookie is already used if (ssoId != null) { String correspondingMOASession = ssoManager.existsOldSSOSession(ssoId); @@ -402,21 +200,22 @@ public class AuthenticationManager extends MOAIDAuthConstants { ssoManager.deleteSSOSessionID(httpReq, httpResp); } } - + + //check if SSO Session is valid + boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); + // check if Service-Provider allows SSO sessions IOAAuthParameters oaParam = pendingReq.getOnlineApplicationConfiguration(); - boolean useSSOOA = oaParam.useSSO() || oaParam.isInderfederationIDP(); + boolean useSSOOA = oaParam.useSSO() || oaParam.isInderfederationIDP(); revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_SERVICEPROVIDER, pendingReq.getOAURL()); //if a legacy request is used SSO should not be allowed in case of mandate authentication boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(httpReq); - - //check if SSO Session is valid - boolean isValidSSOSession = ssoManager.isValidSSOSession(ssoId, pendingReq); - + //check if SSO is allowed for the actually executed request + //INFO: Actually, useMandate disables SSO functionality!!!!! boolean isSSOAllowed = (useSSOOA && !isUseMandateRequested); pendingReq.setNeedSingleSignOnFunctionality(isSSOAllowed); @@ -428,6 +227,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { if (moaSession == null) Logger.info("No MOASession FOUND with provided SSO-Cookie."); + else { Logger.debug("Found authenticated MOASession with provided SSO-Cookie."); revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_SSO); @@ -436,25 +236,22 @@ public class AuthenticationManager extends MOAIDAuthConstants { } //check if session is already authenticated - boolean tryperform = tryPerformAuthentication((RequestImpl) pendingReq, moaSession); - - //perfom SSO-Consents question if it it required - if (tryperform && isSSOAllowed && oaParam.useSSOQuestion()) { - sendTransmitAssertionQuestion(httpReq, httpResp, pendingReq, oaParam); - return null; - - } - + boolean isSessionAuthenticated = tryPerformAuthentication((RequestImpl) pendingReq, moaSession); + //force new authentication authentication process if (pendingReq.forceAuth()) { startAuthenticationProcess(httpReq, httpResp, pendingReq); return null; - + + //perform SSO-Consents evaluation if it it required + } else if (isSessionAuthenticated && oaParam.useSSOQuestion()) { + sendSingleSignOnConsentsEvaluation(httpReq, httpResp, pendingReq); + return null; + } else if (pendingReq.isPassiv()) { - if (tryperform) { + if (isSessionAuthenticated) { // Passive authentication ok! - revisionsLogger.logEvent(oaParam, - pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); + revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); return moaSession; } else { @@ -462,7 +259,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { } } else { - if (tryperform) { + if (isSessionAuthenticated) { // Is authenticated .. proceed revisionsLogger.logEvent(oaParam, pendingReq, MOAIDEventConstants.AUTHPROCESS_FINISHED); @@ -476,6 +273,50 @@ public class AuthenticationManager extends MOAIDAuthConstants { } } + /** + * Checks if a authenticated MOASession already exists and if {protocolRequest} is authenticated + * + * @param protocolRequest Authentication request which is actually in process + * @param moaSession MOASession with authentication information or null if no active MOASession exists + * + * @return true if session is already authenticated, otherwise false + * @throws MOAIDException + */ + private boolean tryPerformAuthentication(RequestImpl protocolRequest, AuthenticationSession moaSession) { + + //if no MOASession exist -> authentication is required + if (moaSession == null) { + return false; + + } else { + //if MOASession is Found but not authenticated --> authentication is required + if (!moaSession.isAuthenticated()) { + return false; + } + + //if MOASession is already authenticated and protocol-request is authenticated + // --> no authentication is required any more + else if (moaSession.isAuthenticated() && protocolRequest.isAuthenticated()) { + return true; + + // if MOASession is authenticated and SSO is allowed --> authenticate pendingRequest + } else if (!protocolRequest.isAuthenticated() + && moaSession.isAuthenticated() && protocolRequest.needSingleSignOnFunctionality()) { + Logger.debug("Found active MOASession and SSO is allowed --> pendingRequest is authenticted"); + protocolRequest.setAuthenticated(true); + protocolRequest.setMOASessionIdentifier(moaSession.getSessionID()); + return true; + + } + + // force authentication as backup solution + else { + Logger.warn("Authentication-required check find an unsuspected state --> force authentication"); + return false; + + } + } + } private void startAuthenticationProcess(HttpServletRequest httpReq, HttpServletResponse httpResp, RequestImpl pendingReq) @@ -505,37 +346,64 @@ public class AuthenticationManager extends MOAIDAuthConstants { } //create authentication process execution context - try { - // create execution context + ExecutionContext executionContext = new ExecutionContextImpl(); + + executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_INTERFEDERATION_ENTITYID, + MiscUtil.isNotEmpty( + pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + boolean leagacyMode = (legacyallowed && legacyparamavail); + executionContext.put("isLegacyRequest", leagacyMode); + executionContext.put("performBKUSelection", !leagacyMode + && MiscUtil.isEmpty(pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + + //add leagcy parameters to context + if (leagacyMode) { + Enumeration reqParamNames = httpReq.getParameterNames(); + while(reqParamNames.hasMoreElements()) { + String paramName = reqParamNames.nextElement(); + if (MiscUtil.isNotEmpty(paramName) && + MOAIDAuthConstants.LEGACYPARAMETERWHITELIST.contains(paramName)) + executionContext.put(paramName, httpReq.getParameter(paramName)); + + } + } + + //start process engine + startProcessEngine(pendingReq, executionContext); + + } + + private void sendSingleSignOnConsentsEvaluation(HttpServletRequest request, + HttpServletResponse response, RequestImpl pendingReq) + throws ServletException, IOException, MOAIDException { + + Logger.info("Start SSO user-consents evaluation ..."); + + //set authenticated flag to false, because user consents is required + pendingReq.setAuthenticated(false); + + //create execution context ExecutionContext executionContext = new ExecutionContextImpl(); - executionContext.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); - executionContext.put(MOAIDAuthConstants.PROCESSCONTEXT_INTERFEDERATION_ENTITYID, - MiscUtil.isNotEmpty( - pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); + executionContext.put(SingleSignOnConsentsModuleImpl.PARAM_SSO_CONSENTS_EVALUATION, true); - boolean leagacyMode = (legacyallowed && legacyparamavail); - executionContext.put("isLegacyRequest", leagacyMode); - executionContext.put("performBKUSelection", !leagacyMode - && MiscUtil.isEmpty(pendingReq.getGenericData(RequestImpl.DATAID_INTERFEDERATIOIDP_URL, String.class))); - - //add leagcy parameters to context - if (leagacyMode) { - Enumeration reqParamNames = httpReq.getParameterNames(); - while(reqParamNames.hasMoreElements()) { - String paramName = reqParamNames.nextElement(); - if (MiscUtil.isNotEmpty(paramName) && - MOAIDAuthConstants.LEGACYPARAMETERWHITELIST.contains(paramName)) - executionContext.put(paramName, httpReq.getParameter(paramName)); - - } - } + //start process engine + startProcessEngine(pendingReq, executionContext); + + } + + private void startProcessEngine(RequestImpl pendingReq, ExecutionContext executionContext) throws MOAIDException { + try { + //put pending-request ID on execurtionContext + executionContext.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); + // create process instance String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); if (processDefinitionId == null) { - Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() ); + Logger.warn("No suitable process found for SessionID " + pendingReq.getRequestID() ); throw new MOAIDException("process.02",new Object[] { - moasession.getSessionID()}); + pendingReq.getRequestID()}); } String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); @@ -545,18 +413,7 @@ public class AuthenticationManager extends MOAIDAuthConstants { //store pending-request requestStoreage.storePendingRequest(pendingReq); - - - // make sure moa session has been persisted before running the process - try { - authenticatedSessionStore.storeSession(moasession); - - } catch (MOADatabaseException e) { - Logger.error("Database Error! MOASession is not stored!"); - throw new MOAIDException("init.04", new Object[] { - moasession.getSessionID()}); - } - + // start process processEngine.start(processInstanceId); @@ -572,32 +429,163 @@ public class AuthenticationManager extends MOAIDAuthConstants { } } - throw new MOAIDException("process.01", new Object[] { pendingReq.getProcessInstanceId(), moasession }, e); - } + throw new MOAIDException("process.01", new Object[] { pendingReq.getProcessInstanceId(), pendingReq.getRequestID() }, e); + } } - - private void sendTransmitAssertionQuestion(HttpServletRequest request, - HttpServletResponse response, IRequest target, IOAAuthParameters oaParam) - throws ServletException, IOException, MOAIDException { - - //TODO: change to process management version!!!! + + private void performSingleLogOut(HttpServletRequest httpReq, + HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException { + String pvpSLOIssuer = null; + String inboundRelayState = null; - //set authenticated flag to false, because user consents is required - target.setAuthenticated(false); + if (pvpReq != null) { + MOARequest samlReq = (MOARequest) pvpReq.getRequest(); + LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); + pvpSLOIssuer = logOutReq.getIssuer().getValue(); + inboundRelayState = samlReq.getRelayState(); + + } + //store active OAs to SLOContaine + List dbOAs = authenticatedSessionStore.getAllActiveOAFromMOASession(session); + List dbIDPs = authenticatedSessionStore.getAllActiveIDPsFromMOASession(session); + SLOInformationContainer sloContainer = new SLOInformationContainer(); + sloContainer.setSloRequest(pvpReq); + sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer); + sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer); + + //terminate MOASession + try { + authenticatedSessionStore.destroySession(session.getSessionID()); + ssoManager.deleteSSOSessionID(httpReq, httpResp); -// String form = SendAssertionFormBuilder.buildForm(target.requestedModule(), -// target.requestedAction(), target.getRequestID(), oaParam, -// target.getAuthURL()); - - String form =null; + } catch (MOADatabaseException e) { + Logger.warn("Delete MOASession FAILED."); + sloContainer.putFailedOA(pvpReq.getAuthURL()); - revisionsLogger.logEvent(target.getOnlineApplicationConfiguration(), - target, MOAIDEventConstants.AUTHPROCESS_SSO_ASK_USER_START); + } + + //start service provider back channel logout process + Iterator nextOAInterator = sloContainer.getNextBackChannelOA(); + while (nextOAInterator.hasNext()) { + SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); + LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); + + try { + List soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); + + LogoutResponse sloResp = null; + for (XMLObject el : soapResp) { + if (el instanceof LogoutResponse) + sloResp = (LogoutResponse) el; + } + + if (sloResp == null) { + Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + + " FAILED. NO LogOut response received."); + sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + + } else { + SAMLVerificationEngine engine = new SAMLVerificationEngine(); + engine.verifySLOResponse(sloResp, + TrustEngineFactory.getSignatureKnownKeysTrustEngine()); + + } + + SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); + + } catch (SOAPException e) { + Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + + " FAILED.", e); + sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + + } catch (SecurityException | InvalidProtocolRequestException e) { + Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() + + " FAILED.", e); + sloContainer.putFailedOA(sloReq.getIssuer().getValue()); + + } + } + + //start service provider front channel logout process + try { + if (sloContainer.hasFrontChannelOA()) { + String relayState = Random.nextRandom(); + + Collection> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); + List sloReqList = new ArrayList(); + for (Entry el : sloDescr) { + LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue()); + try { + sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(), + sloReq, httpReq, httpResp, relayState)); + + } catch (Exception e) { + Logger.warn("Failed to build SLO request for OA:" + el.getKey()); + sloContainer.putFailedOA(el.getKey()); + + } + } + + //put SLO process-information into transaction storage + transactionStorage.put(relayState, sloContainer); + + if (MiscUtil.isEmpty(authURL)) + authURL = pvpReq.getAuthURL(); + + String timeOutURL = authURL + + "/idpSingleLogout" + + "?restart=" + relayState; + + VelocityContext context = new VelocityContext(); + context.put("redirectURLs", sloReqList); + context.put("timeoutURL", timeOutURL); + context.put("timeout", SLOTIMEOUT); + ssoManager.printSingleLogOutInfo(context, httpResp); + + + } else { + if (pvpReq != null) { + //send SLO response to SLO request issuer + SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); + SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + + } else { + //print SLO information directly + VelocityContext context = new VelocityContext(); + if (sloContainer.getSloFailedOAs() == null || + sloContainer.getSloFailedOAs().size() == 0) + context.put("successMsg", + MOAIDMessageProvider.getInstance().getMessage("slo.00", null)); + else + context.put("errorMsg", + MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); + ssoManager.printSingleLogOutInfo(context, httpResp); + + } + + } + + } catch (MOADatabaseException e) { + Logger.error("MOA AssertionDatabase ERROR", e); + if (pvpReq != null) { + SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); + LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); + SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); + + }else { + //print SLO information directly + VelocityContext context = new VelocityContext(); + context.put("errorMsg", + MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); + ssoManager.printSingleLogOutInfo(context, httpResp); + + } - response.setContentType("text/html;charset=UTF-8"); - PrintWriter out = new PrintWriter(response.getOutputStream()); - out.print(form); - out.flush(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } } diff --git a/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule index 7e2315fd7..5116c2a08 100644 --- a/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule +++ b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule @@ -1,2 +1,2 @@ -# The default moaid process at.gv.egovernment.moa.id.auth.modules.BKUSelectionModuleImpl +at.gv.egovernment.moa.id.auth.modules.SingleSignOnConsentsModuleImpl \ No newline at end of file diff --git a/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml new file mode 100644 index 000000000..a58ad8ac4 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/SingleSignOnConsentEvaluator.process.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml b/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml index 82579977c..dcaeb42c3 100644 --- a/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml +++ b/id/server/idserverlib/src/main/resources/moaid.authentication.beans.xml @@ -61,4 +61,10 @@ + + + + \ No newline at end of file diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index 8329db941..92f4c1fa2 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -37,7 +37,7 @@ auth.16=Fehler bei Abarbeitung der Vollmacht in "{0}" auth.17=Vollmachtenmodus f\u00FCr nicht-\u00F6ffentlichen Bereich wird nicht unterst\u00FCtzt. auth.18=Keine MOASessionID vorhanden auth.19=Die Authentifizierung kann nicht passiv durchgef\u00FChrt werden. -auth.20=No valid MOA session found. Authentification process is abourted. +auth.20=No valid MOA session found. Authentication process is aborted. auth.21=Der Anmeldevorgang wurde durch den Benutzer abgebrochen. auth.22=Das Protokoll {0} ist deaktiviert. auth.23=Das BKU-Selektion Template entspricht nicht der Spezifikation von MOA-ID 2.x. @@ -47,6 +47,7 @@ auth.26=SessionID unbekannt. auth.27=Federated authentication FAILED! Assertion from {0} IDP is not valid. auth.28=Transaktion {0} kann nicht weitergef\u00FChrt werden. Wahrscheinlich wurde ein TimeOut erreicht. auth.29=Federated authentication FAILED! Can not build authentication request for IDP {0} +auth.30=No valid Single Sign-On session found. Authentication process is aborted. init.00=MOA ID Authentisierung wurde erfolgreich gestartet init.01=Fehler beim Aktivieren des IAIK-JCE/JSSE/JDK1.3 Workaround\: SSL ist m\u00F6glicherweise nicht verf\u00FCgbar diff --git a/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties index a8583d945..0b00b2d29 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/protocol_response_statuscodes_de.properties @@ -27,6 +27,7 @@ auth.26=1100 auth.27=4401 auth.28=1100 auth.29=4401 +auth.30=1110 init.00=9199 init.01=9199 -- cgit v1.2.3