aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2014-06-06 13:49:25 +0200
committerThomas Lenz <tlenz@iaik.tugraz.at>2014-06-06 13:49:25 +0200
commitf54870a55c9830caa2862d95e2e7f8f3cd6e0243 (patch)
treefb25a52c2f8afad1adafa3d92696aa21ad9e81ed
parent0334cd30ddd9719b0801a274250be8476e0e95be (diff)
downloadmoa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.tar.gz
moa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.tar.bz2
moa-id-spss-f54870a55c9830caa2862d95e2e7f8f3cd6e0243.zip
final betaversion if MOA-ID-Auth Single LogOut
-rw-r--r--id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml17
-rw-r--r--id/server/auth/src/main/webapp/WEB-INF/web.xml13
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java4
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java122
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java2
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java22
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java16
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java6
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java170
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java26
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java71
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java380
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java228
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java8
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java12
-rw-r--r--id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java3
-rw-r--r--id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties7
-rw-r--r--id/server/idserverlib/src/main/resources/resources/templates/slo_template.html57
18 files changed, 888 insertions, 276 deletions
diff --git a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml
index 6da7396a1..23737452a 100644
--- a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml
+++ b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml
@@ -41,20 +41,29 @@
</rule>
<rule match-type="regex">
<from>^/pvp2/redirect$</from>
- <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Redirect&amp;%{query-string}</to>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Redirect&amp;endpointtype=idp&amp;%{query-string}</to>
</rule>
<rule match-type="regex">
<from>^/pvp2/post$</from>
- <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Post&amp;%{query-string}</to>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Post&amp;endpointtype=idp&amp;%{query-string}</to>
</rule>
<rule match-type="regex">
<from>^/pvp2/Soap$</from>
- <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Soap</to>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Soap&amp;endpointtype=idp</to>
</rule>
<rule match-type="regex">
<from>^/pvp2/attributequery$</from>
- <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=AttributeQuery</to>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=AttributeQuery&amp;endpointtype=idp</to>
</rule>
+ <rule match-type="regex">
+ <from>^/pvp2/sp/redirect$</from>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Redirect&amp;endpointtype=sp&amp;%{query-string}</to>
+ </rule>
+ <rule match-type="regex">
+ <from>^/pvp2/sp/post$</from>
+ <to type="forward">/dispatcher?mod=id_pvp2x&amp;action=Post&amp;endpointtype=sp&amp;%{query-string}</to>
+ </rule>
+
<rule match-type="regex">
<from>^/stork2/StartAuthentication$</from>
diff --git a/id/server/auth/src/main/webapp/WEB-INF/web.xml b/id/server/auth/src/main/webapp/WEB-INF/web.xml
index 0ef8a568c..d60d73fd2 100644
--- a/id/server/auth/src/main/webapp/WEB-INF/web.xml
+++ b/id/server/auth/src/main/webapp/WEB-INF/web.xml
@@ -35,8 +35,15 @@
<display-name>LogOut</display-name>
<description>SSO LogOut</description>
<servlet-class>at.gv.egovernment.moa.id.auth.servlet.LogOutServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
</servlet>
+
+ <servlet>
+ <servlet-name>IDPSLO</servlet-name>
+ <display-name>IDP-SLO</display-name>
+ <description>IDP Single LogOut Service</description>
+ <servlet-class>at.gv.egovernment.moa.id.auth.servlet.IDPSingleLogOutServlet</servlet-class>
+ </servlet>
+
<servlet>
<servlet-name>VerifyIdentityLink</servlet-name>
<display-name>VerifyIdentityLink</display-name>
@@ -171,6 +178,10 @@
<url-pattern>/LogOut</url-pattern>
</servlet-mapping>
<servlet-mapping>
+ <servlet-name>IDPSLO</servlet-name>
+ <url-pattern>/idpSingleLogout</url-pattern>
+ </servlet-mapping>
+ <servlet-mapping>
<servlet-name>VerifyIdentityLink</servlet-name>
<url-pattern>/VerifyIdentityLink</url-pattern>
</servlet-mapping>
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
index 6f83da367..e2c0c1f18 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java
@@ -33,6 +33,10 @@ public interface MOAIDAuthConstants {
public static final String PARAM_SSO = "SSO";
public static final String INTERFEDERATION_IDP = "interIDP";
+ public static final String PARAM_SLOSTATUS = "status";
+ public static final String SLOSTATUS_SUCCESS = "success";
+ public static final String SLOSTATUS_ERROR = "error";
+
/** servlet parameter &quot;sourceID&quot; */
public static final String PARAM_SOURCEID = "sourceID";
/** servlet parameter &quot;BKUSelectionTemplate&quot; */
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
new file mode 100644
index 000000000..ac4e56023
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java
@@ -0,0 +1,122 @@
+/*
+ * 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.velocity.VelocityContext;
+
+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;
+import at.gv.egovernment.moa.id.moduls.AuthenticationManager;
+import at.gv.egovernment.moa.id.moduls.SSOManager;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
+import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
+import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
+import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * @author tlenz
+ *
+ */
+public class IDPSingleLogOutServlet extends AuthServlet {
+
+ private static final long serialVersionUID = -1301786072691577221L;
+
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ Logger.debug("receive IDP SingleLogOut Request");
+ SSOManager ssomanager = SSOManager.getInstance();
+ String ssoid = ssomanager.getSSOSessionID(req);
+
+ Object tokkenObj = req.getParameter(PARAM_SLOSTATUS);
+ String tokken = null;
+ String status = null;
+ if (tokkenObj != null && tokkenObj instanceof String) {
+ tokken = (String) tokkenObj;
+ try {
+ status = AssertionStorage.getInstance().get(tokken, String.class);
+ if (MiscUtil.isNotEmpty(status)) {
+ AssertionStorage.getInstance().remove(tokken);
+
+ }
+ VelocityContext context = new VelocityContext();
+ if (SLOSTATUS_SUCCESS.equals(status))
+ context.put("successMsg",
+ MOAIDMessageProvider.getInstance().getMessage("slo.00", null));
+ else
+ context.put("errorMsg",
+ MOAIDMessageProvider.getInstance().getMessage("slo.01", null));
+
+ ssomanager.printSingleLogOutInfo(context, resp);
+
+ } catch (MOAIDException e) {
+ handleErrorNoRedirect(e.getMessage(), e, req, resp);
+
+ } catch (MOADatabaseException e) {
+ handleErrorNoRedirect(e.getMessage(), e, req, resp);
+
+ }
+
+ }
+
+ if (MiscUtil.isNotEmpty(status)) {
+ //print status information
+
+
+ } else if (MiscUtil.isNotEmpty(ssoid)) {
+ if (ssomanager.isValidSSOSession(ssoid, null)) {
+
+ AuthenticationManager authmanager = AuthenticationManager.getInstance();
+ String moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoid);
+
+ if (MiscUtil.isNotEmpty(moaSessionID)) {
+ AuthenticationSession authSession;
+ try {
+ authSession = AuthenticationSessionStoreage
+ .getSession(moaSessionID);
+ if(authSession != null) {
+ authmanager.performSingleLogOut(req, resp, authSession, null);
+
+ }
+
+ } catch (MOADatabaseException e) {
+ //TODO: insert error Handling
+
+ } catch (MOAIDException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ }
+
+}
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 9b300578a..d7de985a4 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
@@ -109,7 +109,7 @@ public class LogOutServlet extends AuthServlet {
RequestStorage.removePendingRequest(AuthenticationSessionStoreage.getPendingRequestID(moasessionid));
- authmanager.logout(req, resp, moasessionid);
+ authmanager.performOnlyIDPLogOut(req, resp, moasessionid);
Logger.info("User with SSO Id " + ssoid + " is logged out and get redirect to "+ redirectUrl);
} else {
Logger.info("No active SSO session found. User is maybe logout already and get redirect to "+ redirectUrl);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
index 57755ca9f..6e1811c8b 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java
@@ -46,6 +46,8 @@ public class RedirectServlet extends AuthServlet{
public static final String REDIRCT_PARAM_URL = "redirecturl";
+ private static final String DEFAULT_REDIRECTTARGET = "_parent";
+
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
@@ -55,16 +57,10 @@ public class RedirectServlet extends AuthServlet{
String target = req.getParameter(PARAM_TARGET);
String artifact = req.getParameter(PARAM_SAMLARTIFACT);
String interIDP = req.getParameter(INTERFEDERATION_IDP);
-
- if (MiscUtil.isEmpty(artifact) && MiscUtil.isEmpty(interIDP)) {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid");
- return;
- }
-
Logger.debug("Check URL against online-applications");
OnlineApplication oa = null;
- String redirectTarget = "_parent";
+ String redirectTarget = DEFAULT_REDIRECTTARGET;
try {
oa = ConfigurationDBRead.getActiveOnlineApplication(url);
if (oa == null) {
@@ -118,10 +114,16 @@ public class RedirectServlet extends AuthServlet{
resp.addHeader("Location", url);
- } else {
- resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid");
- return;
+ } else {
+ Logger.debug("Redirect to " + url);
+ String redirect_form = RedirectFormBuilder.buildLoginForm(url, DEFAULT_REDIRECTTARGET);
+ resp.setContentType("text/html;charset=UTF-8");
+ resp.setStatus(HttpServletResponse.SC_OK);
+ PrintWriter out = new PrintWriter(resp.getOutputStream());
+ out.write(redirect_form);
+ out.flush();
+
}
}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
index df195c0de..d1e04e107 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java
@@ -24,9 +24,12 @@ package at.gv.egovernment.moa.id.data;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.NameID;
@@ -135,17 +138,12 @@ public class SLOInformationContainer implements Serializable {
}
}
- public String getNextFrontChannelOA() {
- Iterator<String> interator = activeFrontChannalOAs.keySet().iterator();
- if (interator.hasNext())
- return interator.next();
-
- else
- return null;
+ public boolean hasFrontChannelOA() {
+ return !activeFrontChannalOAs.isEmpty();
}
- public SLOInformationImpl getFrontChannelOASessionDescripten(String oaID) {
- return activeFrontChannalOAs.get(oaID);
+ public Set<Entry<String, SLOInformationImpl>> getFrontChannelOASessionDescriptions() {
+ return activeFrontChannalOAs.entrySet();
}
public void removeFrontChannelOA(String oaID) {
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
index a3827ab73..0cbe749e0 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java
@@ -143,7 +143,7 @@ public class DispatcherServlet extends AuthServlet{
//remove MOASession
AuthenticationSession moaSession = AuthenticationSessionStoreage.getSessionWithPendingRequestID(pendingRequestID);
- AuthenticationManager.getInstance().logout(req, resp, moaSession.getSessionID());
+ AuthenticationManager.getInstance().performOnlyIDPLogOut(req, resp, moaSession.getSessionID());
return;
}
@@ -468,12 +468,12 @@ public class DispatcherServlet extends AuthServlet{
} catch (AuthenticationException e) {
Logger.warn("SSO Session information can not be stored -> SSO is not enabled!");
- authmanager.logout(req, resp, moasessionID);
+ authmanager.performOnlyIDPLogOut(req, resp, moasessionID);
isSSOSession = false;
}
} else {
- authmanager.logout(req, resp, moasessionID);
+ authmanager.performOnlyIDPLogOut(req, resp, moasessionID);
}
//Advanced statistic logging
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 5a06b3ecd..ee26d9223 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
@@ -24,13 +24,21 @@ package at.gv.egovernment.moa.id.moduls;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
import org.joda.time.DateTime;
import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.opensaml.common.xml.SAMLConstants;
@@ -38,6 +46,8 @@ import org.opensaml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.Issuer;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.LogoutResponse;
import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.NameIDPolicy;
import org.opensaml.saml2.core.NameIDType;
@@ -45,12 +55,15 @@ import org.opensaml.saml2.core.RequestedAuthnContext;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.SingleLogoutService;
import org.opensaml.saml2.metadata.SingleSignOnService;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.security.MetadataCredentialResolver;
import org.opensaml.security.MetadataCredentialResolverFactory;
import org.opensaml.security.MetadataCriteria;
import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.ws.soap.common.SOAPException;
+import org.opensaml.xml.XMLObject;
import org.opensaml.xml.security.CriteriaSet;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.security.criteria.EntityIDCriteria;
@@ -64,19 +77,32 @@ import at.gv.egovernment.moa.id.auth.exception.BuildException;
import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;
import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
+import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
+import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
+import at.gv.egovernment.moa.id.config.ConfigurationException;
import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
+import at.gv.egovernment.moa.id.data.SLOInformationContainer;
+import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.ArtifactBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
+import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;
+import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
+import at.gv.egovernment.moa.id.storage.AssertionStorage;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
+import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MessageProvider;
import at.gv.egovernment.moa.util.MiscUtil;
import at.gv.egovernment.moa.util.StringUtils;
@@ -138,7 +164,149 @@ public class AuthenticationManager extends AuthServlet {
return false;
}
- public void logout(HttpServletRequest request,
+ public void performSingleLogOut(HttpServletRequest httpReq,
+ HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) 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();
+ }
+
+ SSOManager ssomanager = SSOManager.getInstance();
+
+ //store active OAs to SLOContaine
+ List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);
+ List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session);
+ SLOInformationContainer sloContainer = new SLOInformationContainer();
+ sloContainer.setSloRequest(pvpReq);
+ sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer);
+ sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer);
+
+ //terminate MOASession
+ try {
+ AuthenticationSessionStoreage.destroySession(session.getSessionID());
+ ssomanager.deleteSSOSessionID(httpReq, httpResp);
+
+ } catch (MOADatabaseException e) {
+ Logger.warn("Delete MOASession FAILED.");
+ sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix());
+
+ }
+
+ //start service provider back channel logout process
+ Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();
+ while (nextOAInterator.hasNext()) {
+ SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next());
+ LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
+
+ try {
+ List<XMLObject> 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());
+
+ }
+
+ 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 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<Entry<String, SLOInformationImpl>> sloDescr = sloContainer.getFrontChannelOASessionDescriptions();
+ List<String> sloReqList = new ArrayList<String>();
+ for (Entry<String, SLOInformationImpl> 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());
+
+ }
+ }
+
+ AssertionStorage.getInstance().put(relayState, sloContainer);
+
+ VelocityContext context = new VelocityContext();
+ context.put("redirectURLs", sloReqList);
+ 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",
+ MessageProvider.getInstance().getMessage("slo.00", null));
+ else
+ context.put("errorMsg",
+ MessageProvider.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);
+ SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState);
+
+ }else {
+ //print SLO information directly
+ VelocityContext context = new VelocityContext();
+ context.put("errorMsg",
+ MessageProvider.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");
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
index f4f89a4ba..02e252412 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java
@@ -22,17 +22,22 @@
*******************************************************************************/
package at.gv.egovernment.moa.id.moduls;
+import java.io.StringWriter;
import java.util.List;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
import org.hibernate.Query;
import org.hibernate.Session;
import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
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.MOASessionDBUtils;
import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
@@ -42,6 +47,7 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -267,6 +273,26 @@ public class SSOManager {
}
+ public void printSingleLogOutInfo(VelocityContext context, HttpServletResponse httpResp) throws MOAIDException {
+ try {
+ Logger.trace("Initialize VelocityEngine...");
+ VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
+ Template template = velocityEngine.getTemplate("/resources/templates/slo_template.html");
+
+ StringWriter writer = new StringWriter();
+ template.merge(context, writer);
+
+ httpResp.setContentType("text/html;charset=UTF-8");
+ httpResp.getOutputStream().write(writer.toString().getBytes());
+
+ } catch (Exception e) {
+ Logger.error("Single LogOut from can not created.", e);
+ throw new MOAIDException("Create Single LogOut information FAILED.", null, e);
+ }
+
+ }
+
+
private String getValueFromCookie(HttpServletRequest httpReq, String cookieName) {
Cookie[] cookies = httpReq.getCookies();
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java
new file mode 100644
index 000000000..ece1a805d
--- /dev/null
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java
@@ -0,0 +1,71 @@
+/*
+ * 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.opemsaml;
+
+import org.opensaml.common.binding.SAMLMessageContext;
+import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
+import org.opensaml.ws.message.MessageContext;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+
+import at.gv.egovernment.moa.logging.Logger;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MOAStringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder {
+
+ private String redirectURL = null;
+
+ public void encode(MessageContext messageContext)
+ throws MessageEncodingException {
+ if (!(messageContext instanceof SAMLMessageContext)) {
+ Logger.error("Invalid message context type, this encoder only support SAMLMessageContext");
+ throw new MessageEncodingException(
+ "Invalid message context type, this encoder only support SAMLMessageContext");
+ }
+
+ SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
+
+ String endpointURL = getEndpointURL(samlMsgCtx).buildURL();
+
+ setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL);
+
+ removeSignature(samlMsgCtx);
+
+ String encodedMessage = deflateAndBase64Encode(samlMsgCtx
+ .getOutboundSAMLMessage());
+
+ redirectURL = buildRedirectURL(samlMsgCtx, endpointURL,
+ encodedMessage);
+ }
+
+ /**
+ * @return the redirectURL
+ */
+ public String getRedirectURL() {
+ return redirectURL;
+ }
+
+
+}
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
index 92441e663..46e02d048 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java
@@ -22,26 +22,50 @@
*/
package at.gv.egovernment.moa.id.protocols.pvp2x;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang.SerializationUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Transaction;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.LogoutRequest;
import org.opensaml.saml2.core.LogoutResponse;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.Status;
import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.ws.soap.common.SOAPException;
import org.opensaml.xml.XMLObject;
import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.X509Credential;
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.MOAIDException;
+import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet;
+import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
+import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;
import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
@@ -50,9 +74,11 @@ import at.gv.egovernment.moa.id.data.IAuthData;
import at.gv.egovernment.moa.id.data.SLOInformationContainer;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
import at.gv.egovernment.moa.id.data.SLOInformationInterface;
+import at.gv.egovernment.moa.id.moduls.AuthenticationManager;
import at.gv.egovernment.moa.id.moduls.IAction;
import at.gv.egovernment.moa.id.moduls.IRequest;
import at.gv.egovernment.moa.id.moduls.SSOManager;
+import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
@@ -60,12 +86,17 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
+import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;
import at.gv.egovernment.moa.id.storage.AssertionStorage;
import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
import at.gv.egovernment.moa.id.util.Random;
+import at.gv.egovernment.moa.id.util.VelocityProvider;
import at.gv.egovernment.moa.logging.Logger;
+import at.gv.egovernment.moa.util.MessageProvider;
import at.gv.egovernment.moa.util.MiscUtil;
+import at.gv.egovernment.moa.util.URLEncoder;
/**
* @author tlenz
@@ -83,16 +114,16 @@ public class SingleLogOutAction implements IAction {
PVPTargetConfiguration pvpReq = (PVPTargetConfiguration) req;
- if (pvpReq.getRequest() instanceof MOARequest) {
+ if (pvpReq.getRequest() instanceof MOARequest &&
+ ((MOARequest)pvpReq.getRequest()).getSamlRequest() instanceof LogoutRequest) {
+ Logger.debug("Process Single LogOut request");
MOARequest samlReq = (MOARequest) pvpReq.getRequest();
- if (samlReq.getSamlRequest() instanceof LogoutRequest) {
- Logger.debug("Process Single LogOut request");
- LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
+ LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();
- AuthenticationSession session =
- AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID(
- logOutReq.getIssuer().getValue(),
- logOutReq.getNameID().getValue());
+ AuthenticationSession session =
+ AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID(
+ logOutReq.getIssuer().getValue(),
+ logOutReq.getNameID().getValue());
if (session == null) {
Logger.warn("Can not find active SSO session with nameID "
@@ -105,7 +136,7 @@ public class SingleLogOutAction implements IAction {
Logger.warn("Can not find active Session. Single LogOut not possible!");
SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
- sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
+ SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
return null;
} else {
@@ -117,103 +148,150 @@ public class SingleLogOutAction implements IAction {
Logger.warn("Can not find active Session. Single LogOut not possible!");
SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
- sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
+ SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
return null;
}
}
}
- //store active OAs to SLOContaine
- List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);
- List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session);
- SLOInformationContainer sloContainer = new SLOInformationContainer();
- sloContainer.setSloRequest(pvpReq);
- sloContainer.parseActiveIDPs(dbIDPs, logOutReq.getIssuer().getValue());
- sloContainer.parseActiveOAs(dbOAs, logOutReq.getIssuer().getValue());
-
- //terminate MOASession
- try {
- AuthenticationSessionStoreage.destroySession(session.getSessionID());
-
- } catch (MOADatabaseException e) {
- Logger.warn("Delete MOASession FAILED.");
- sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix());
-
- }
-
- //start service provider back channel logout process
- Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();
- while (nextOAInterator.hasNext()) {
- SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next());
- LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
-
- try {
- List<XMLObject> 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());
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq);
- }
-
- checkStatusCode(sloContainer, sloResp);
-
- } catch (SOAPException e) {
- Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()
- + " FAILED.", e);
- sloContainer.putFailedOA(sloReq.getIssuer().getValue());
-
- } catch (SecurityException 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 {
- doFrontChannelLogOut(sloContainer, httpReq, httpResp);
-
- } catch (MOADatabaseException e) {
- Logger.error("MOA AssertionDatabase ERROR", e);
- SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
- LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq);
- sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
- return null;
-
- }
-
- } else if (samlReq.getSamlRequest() instanceof LogoutResponse) {
+ } else if (pvpReq.getRequest() instanceof MOAResponse &&
+ ((MOAResponse)pvpReq.getRequest()).getResponse() instanceof LogoutResponse) {
Logger.debug("Process Single LogOut response");
- LogoutResponse logOutResp = (LogoutResponse) samlReq.getSamlRequest();
+ LogoutResponse logOutResp = (LogoutResponse) ((MOAResponse)pvpReq.getRequest()).getResponse();
- try {
- if (MiscUtil.isEmpty(samlReq.getRelayState())) {
+ try {
+ String relayState = pvpReq.getRequest().getRelayState();
+ if (MiscUtil.isEmpty(relayState)) {
Logger.warn("SLO Response from " + logOutResp.getIssuer().getValue()
+ " has no SAML2 RelayState.");
throw new SLOException("pvp2.19", null);
}
- SLOInformationContainer sloContainer =
- AssertionStorage.getInstance().get(samlReq.getRelayState(), SLOInformationContainer.class);
- checkStatusCode(sloContainer, logOutResp);
- sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue());
- doFrontChannelLogOut(sloContainer, httpReq, httpResp);
+ Session session = MOASessionDBUtils.getCurrentSession();
+ boolean storageSuccess = false;
+ int counter = 0;
+
+ //TODO: add counter to prevent deadlock
+
+ while (!storageSuccess) {
+ Transaction tx = session.beginTransaction();
+
+ List result;
+ Query query = session.getNamedQuery("getAssertionWithArtifact");
+ query.setParameter("artifact", relayState);
+ result = query.list();
+ Logger.trace("Found entries: " + result.size());
+
+ //Assertion requires an unique artifact
+ if (result.size() != 1) {
+ Logger.trace("No entries found.");
+ throw new MOADatabaseException("No sessioninformation found with this ID");
+ }
+
+ AssertionStore element = (AssertionStore) result.get(0);
+ Object data = SerializationUtils.deserialize(element.getAssertion());
+
+ if (data instanceof SLOInformationContainer) {
+ SLOInformationContainer sloContainer = (SLOInformationContainer) data;
+
+ //check status
+ SingleLogOutBuilder.checkStatusCode(sloContainer, logOutResp);
+
+ if (sloContainer.hasFrontChannelOA()) {
+ try {
+ //some response are open
+ byte[] serializedSLOContainer = SerializationUtils.serialize((Serializable) sloContainer);
+ element.setAssertion(serializedSLOContainer);
+ element.setType(sloContainer.getClass().getName());
+
+ session.saveOrUpdate(element);
+ tx.commit();
+
+ //sloContainer could be stored to database
+ storageSuccess = true;
+
+ } catch(HibernateException e) {
+ tx.rollback();
+
+ counter++;
+ Logger.debug("SLOContainter could not stored to database. Wait some time and restart storage process ... ");
+ java.util.Random rand = new java.util.Random();
+
+ try {
+ Thread.sleep(rand.nextInt(20)*10);
+
+ } catch (InterruptedException e1) {
+ Logger.warn("Thread could not stopped. ReStart storage process immediately", e1);
+ }
+ }
+
+ } else {
+ //last response received.
+ try {
+ session.delete(element);
+ tx.commit();
+
+ } catch(HibernateException e) {
+ tx.rollback();
+ Logger.error("SLOContainter could not deleted from database. ");
+
+ }
+
+ storageSuccess = true;
+ String redirectURL = null;
+ if (sloContainer.getSloRequest() != null) {
+ //send SLO response to SLO request issuer
+ SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(sloContainer.getSloRequest());
+ LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs());
+ redirectURL = SingleLogOutBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState());
+
+ } else {
+ //print SLO information directly
+ redirectURL = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/idpSingleLogout";
+
+ String artifact = Random.nextRandom();
+
+ String statusCode = null;
+ if (sloContainer.getSloFailedOAs() == null ||
+ sloContainer.getSloFailedOAs().size() == 0)
+ statusCode = SLOSTATUS_SUCCESS;
+ else
+ statusCode = SLOSTATUS_ERROR;
+
+ AssertionStorage.getInstance().put(artifact, statusCode);
+ redirectURL = addURLParameter(redirectURL, PARAM_SLOSTATUS, artifact);
+
+ }
+ //redirect to Redirect Servlet
+ String url = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/RedirectServlet";
+ url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8"));
+ url = httpResp.encodeRedirectURL(url);
+
+ httpResp.setContentType("text/html");
+ httpResp.setStatus(302);
+ httpResp.addHeader("Location", url);
+
+ }
+ } else {
+ Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + relayState);
+ throw new MOADatabaseException("Sessioninformation Cast-Exception");
+
+ }
+ }
} catch (MOADatabaseException e) {
Logger.error("MOA AssertionDatabase ERROR", e);
throw new SLOException("pvp2.19", null);
+ } catch (UnsupportedEncodingException e) {
+ Logger.error("Finale SLO redirct not possible.", e);
+ throw new AuthenticationException("pvp2.13", new Object[]{});
+
}
} else {
@@ -221,13 +299,7 @@ public class SingleLogOutAction implements IAction {
throw new MOAIDException("pvp2.13", null);
}
-
- } else {
- Logger.error("Process SingleLogOutAction but request is NOT of type MOARequest.");
- throw new MOAIDException("pvp2.13", null);
-
- }
-
+
return null;
}
@@ -248,120 +320,12 @@ public class SingleLogOutAction implements IAction {
return PVP2XProtocol.SINGLELOGOUT;
}
- private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) {
- Status status = logOutResp.getStatus();
- if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
- String message = " Message: ";
- if (status.getStatusMessage() != null)
- message += status.getStatusMessage().getMessage();
- Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue()
- + " FAILED. (ResponseCode: " + status.getStatusCode().getValue()
- + message + ")");
- sloContainer.putFailedOA(logOutResp.getIssuer().getValue());
-
- } else
- Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS");
-
+ protected static String addURLParameter(String url, String paramname,
+ String paramvalue) {
+ String param = paramname + "=" + paramvalue;
+ if (url.indexOf("?") < 0)
+ return url + "?" + param;
+ else
+ return url + "&" + param;
}
-
- private void doFrontChannelLogOut(SLOInformationContainer sloContainer,
- HttpServletRequest httpReq, HttpServletResponse httpResp
- ) throws MOAIDException, MOADatabaseException {
- String nextOA = sloContainer.getNextFrontChannelOA();
- if (MiscUtil.isNotEmpty(nextOA)) {
- SLOInformationImpl sloDescr = sloContainer.getFrontChannelOASessionDescripten(nextOA);
- LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr);
- String relayState = Random.nextRandom();
-
- AssertionStorage.getInstance().put(relayState, sloContainer);
-
- sendFrontChannelSLOMessage(sloDescr.getServiceURL(), sloDescr.getBinding(),
- sloReq, httpReq, httpResp, relayState);
-
- } else {
- //send SLO response to SLO request issuer
- PVPTargetConfiguration pvpReq = sloContainer.getSloRequest();
- MOARequest samlReq = (MOARequest) pvpReq.getRequest();
- SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);
- LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs());
- sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());
-
- }
- }
-
- /**
- * @param serviceURL
- * @param binding
- * @param sloReq
- * @param httpReq
- * @param httpResp
- * @param relayState
- */
- private void sendFrontChannelSLOMessage(String serviceURL, String bindingType,
- RequestAbstractType sloReq, HttpServletRequest httpReq,
- HttpServletResponse httpResp, String relayState) throws MOAIDException {
- IEncoder binding = null;
- if (bindingType.equals(
- SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
- binding = new RedirectBinding();
-
- } else if (bindingType.equals(
- SAMLConstants.SAML2_POST_BINDING_URI)) {
- binding = new PostBinding();
-
- }
-
- if (binding == null) {
- throw new BindingNotSupportedException(bindingType);
- }
-
- try {
- binding.encodeRequest(httpReq, httpResp, sloReq,
- serviceURL, relayState);
-
- } catch (MessageEncodingException e) {
- Logger.error("Message Encoding exception", e);
- throw new MOAIDException("pvp2.01", null, e);
-
- } catch (SecurityException e) {
- Logger.error("Security exception", e);
- throw new MOAIDException("pvp2.01", null, e);
-
- }
-
- }
-
- private void sendFrontChannelSLOMessage(SingleLogoutService consumerService,
- LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp,
- String relayState) throws MOAIDException {
- IEncoder binding = null;
- if (consumerService.getBinding().equals(
- SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
- binding = new RedirectBinding();
-
- } else if (consumerService.getBinding().equals(
- SAMLConstants.SAML2_POST_BINDING_URI)) {
- binding = new PostBinding();
-
- }
-
- if (binding == null) {
- throw new BindingNotSupportedException(consumerService.getBinding());
- }
-
- try {
- binding.encodeRespone(req, resp, sloResp,
- consumerService.getLocation(), relayState);
-
- } catch (MessageEncodingException e) {
- Logger.error("Message Encoding exception", e);
- throw new MOAIDException("pvp2.01", null, e);
-
- } catch (SecurityException e) {
- Logger.error("Security exception", e);
- throw new MOAIDException("pvp2.01", null, 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 7aa860c5c..eeb1dd104 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
@@ -22,31 +22,53 @@
*/
package at.gv.egovernment.moa.id.protocols.pvp2x.builder;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
import org.joda.time.DateTime;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.common.impl.SecureRandomIdentifierGenerator;
import org.opensaml.common.xml.SAMLConstants;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.LogoutRequest;
import org.opensaml.saml2.core.LogoutResponse;
import org.opensaml.saml2.core.NameID;
+import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.Status;
import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusMessage;
+import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.SSODescriptor;
import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.X509Credential;
+import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
+import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
import at.gv.egovernment.moa.id.config.ConfigurationException;
+import at.gv.egovernment.moa.id.data.SLOInformationContainer;
import at.gv.egovernment.moa.id.data.SLOInformationImpl;
+import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;
import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;
+import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;
import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
+import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;
import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;
import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;
+import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;
import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;
import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;
import at.gv.egovernment.moa.logging.Logger;
@@ -57,9 +79,141 @@ import at.gv.egovernment.moa.logging.Logger;
*/
public class SingleLogOutBuilder {
- public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException {
+ public static void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) {
+ Status status = logOutResp.getStatus();
+ if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
+ String message = " Message: ";
+ if (status.getStatusMessage() != null)
+ message += status.getStatusMessage().getMessage();
+ Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue()
+ + " FAILED. (ResponseCode: " + status.getStatusCode().getValue()
+ + message + ")");
+ sloContainer.putFailedOA(logOutResp.getIssuer().getValue());
+
+ } else
+ sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue());
+ Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS");
+
+ }
+
+ /**
+ * @param serviceURL
+ * @param binding
+ * @param sloReq
+ * @param httpReq
+ * @param httpResp
+ * @param relayState
+ * @return
+ */
+ public static String getFrontChannelSLOMessageURL(String serviceURL, String bindingType,
+ RequestAbstractType sloReq, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, String relayState) throws MOAIDException {
+
+ try {
+ X509Credential credentials = CredentialProvider
+ .getIDPAssertionSigningCredential();
+
+ Logger.debug("create SAML RedirectBinding response");
+
+ MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();
+ BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ SingleLogoutService service = new SingleLogoutServiceBuilder()
+ .buildObject();
+ service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ service.setLocation(serviceURL);
+ context.setOutboundSAMLMessageSigningCredential(credentials);
+ context.setPeerEntityEndpoint(service);
+ context.setOutboundSAMLMessage(sloReq);
+ context.setRelayState(relayState);
+
+ encoder.encode(context);
+
+ return encoder.getRedirectURL();
+
+ } catch (MessageEncodingException e) {
+ Logger.error("Message Encoding exception", e);
+ throw new MOAIDException("pvp2.01", null, e);
+
+ }
+ }
+
+ public static String getFrontChannelSLOMessageURL(SingleLogoutService service,
+ StatusResponseType sloResp, HttpServletRequest httpReq,
+ HttpServletResponse httpResp, String relayState) throws MOAIDException {
+
+ try {
+ X509Credential credentials = CredentialProvider
+ .getIDPAssertionSigningCredential();
+
+ Logger.debug("create SAML RedirectBinding response");
+
+ MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();
+ BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ context.setOutboundSAMLMessageSigningCredential(credentials);
+ context.setPeerEntityEndpoint(service);
+ context.setOutboundSAMLMessage(sloResp);
+ context.setRelayState(relayState);
+
+ encoder.encode(context);
+
+ return encoder.getRedirectURL();
+
+ } catch (MessageEncodingException e) {
+ Logger.error("Message Encoding exception", e);
+ throw new MOAIDException("pvp2.01", null, e);
+
+ }
+ }
+
+ public static void sendFrontChannelSLOMessage(SingleLogoutService consumerService,
+ LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp,
+ String relayState) throws MOAIDException {
+ IEncoder binding = null;
+ if (consumerService.getBinding().equals(
+ SAMLConstants.SAML2_REDIRECT_BINDING_URI)) {
+ binding = new RedirectBinding();
+
+ } else if (consumerService.getBinding().equals(
+ SAMLConstants.SAML2_POST_BINDING_URI)) {
+ binding = new PostBinding();
+
+ }
+
+ if (binding == null) {
+ throw new BindingNotSupportedException(consumerService.getBinding());
+ }
+
+ try {
+ binding.encodeRespone(req, resp, sloResp,
+ consumerService.getLocation(), relayState);
+
+ } catch (MessageEncodingException e) {
+ Logger.error("Message Encoding exception", e);
+ throw new MOAIDException("pvp2.01", null, e);
+
+ } catch (SecurityException e) {
+ Logger.error("Security exception", e);
+ throw new MOAIDException("pvp2.01", null, e);
+
+ }
+ }
+
+
+ public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException, MOAIDException {
LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class);
+ SecureRandomIdentifierGenerator gen;
+ try {
+ gen = new SecureRandomIdentifierGenerator();
+ sloReq.setID(gen.generateIdentifier());
+
+ } catch (NoSuchAlgorithmException e) {
+ Logger.error("Internal server error", e);
+ throw new AuthenticationException("pvp2.13", new Object[]{});
+
+ }
+
+
Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
issuer.setFormat(NameID.ENTITY);
@@ -76,14 +230,9 @@ public class SingleLogOutBuilder {
return sloReq;
}
- public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException {
- LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);
- Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
- issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
- issuer.setFormat(NameID.ENTITY);
- sloResp.setIssuer(issuer);
- sloResp.setIssueInstant(new DateTime());
- sloResp.setDestination(sloService.getLocation());
+ public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException {
+ LogoutResponse sloResp = buildBasicResponse(sloService, spRequest);
+
Status status = SAML2Utils.createSAMLObject(Status.class);
StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class);
@@ -95,14 +244,8 @@ public class SingleLogOutBuilder {
return sloResp;
}
- public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws ConfigurationException {
- LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);
- Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
- issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
- issuer.setFormat(NameID.ENTITY);
- sloResp.setIssuer(issuer);
- sloResp.setIssueInstant(new DateTime());
- sloResp.setDestination(sloService.getLocation());
+ public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws MOAIDException {
+ LogoutResponse sloResp = buildBasicResponse(sloService, spRequest);
Status status;
if (failedOAs == null || failedOAs.size() == 0) {
@@ -123,6 +266,37 @@ public class SingleLogOutBuilder {
}
+ private static LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException {
+ LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);
+ Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
+ issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());
+ issuer.setFormat(NameID.ENTITY);
+ sloResp.setIssuer(issuer);
+ sloResp.setIssueInstant(new DateTime());
+ sloResp.setDestination(sloService.getLocation());
+
+ SecureRandomIdentifierGenerator gen;
+ try {
+ gen = new SecureRandomIdentifierGenerator();
+ sloResp.setID(gen.generateIdentifier());
+
+ } catch (NoSuchAlgorithmException e) {
+ Logger.error("Internal server error", e);
+ throw new AuthenticationException("pvp2.13", new Object[]{});
+
+ }
+
+ if (spRequest.getRequest() instanceof MOARequest &&
+ ((MOARequest)spRequest.getRequest()).getSamlRequest() instanceof LogoutRequest) {
+ LogoutRequest sloReq = (LogoutRequest) ((MOARequest)spRequest.getRequest()).getSamlRequest();
+ sloResp.setInResponseTo(sloReq.getID());
+
+ }
+
+ return sloResp;
+
+ }
+
public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException {
try {
EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID);
@@ -140,19 +314,19 @@ public class SingleLogOutBuilder {
)
sloService = el;
- else if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)
- && (
- (sloService != null
- && !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)
- && !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))
- || sloService == null)
- )
- sloService = el;
+// else if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)
+// && (
+// (sloService != null
+// && !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)
+// && !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))
+// || sloService == null)
+// )
+// sloService = el;
}
if (sloService == null) {
- Logger.error("Found no SLO ServiceDescriptor in Metadata");
- throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null);
+ Logger.error("Found no valid SLO ServiceDescriptor in Metadata");
+ throw new NOSLOServiceDescriptorException("NO valid SLO ServiceDescriptor", null);
}
return sloService;
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
index 870273cf3..f2512b122 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java
@@ -23,7 +23,7 @@
package at.gv.egovernment.moa.id.protocols.pvp2x.messages;
import org.opensaml.Configuration;
-import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.xml.io.Unmarshaller;
import org.opensaml.xml.io.UnmarshallerFactory;
import org.opensaml.xml.io.UnmarshallingException;
@@ -35,16 +35,16 @@ public class MOAResponse extends InboundMessage {
private static final long serialVersionUID = -1133012928130138501L;
- public MOAResponse(Response response) {
+ public MOAResponse(StatusResponseType response) {
setSAMLMessage(response.getDOM());
}
- public Response getResponse() {
+ public StatusResponseType getResponse() {
UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();
Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());
try {
- return (Response) unmashaller.unmarshall(getInboundMessage());
+ return (StatusResponseType) unmashaller.unmarshall(getInboundMessage());
} catch (UnmarshallingException e) {
Logger.warn("AuthnResponse Unmarshaller error", e);
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
index 61b481447..ee0088576 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java
@@ -28,6 +28,7 @@ import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml2.core.AuthnStatement;
import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.core.Subject;
import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;
@@ -38,15 +39,16 @@ public class AssertionAttributeExtractor {
private Assertion assertion = null;
- public AssertionAttributeExtractor(Response samlResponse) throws AssertionAttributeExtractorExeption {
- if (samlResponse != null) {
- if (samlResponse.getAssertions().size() == 0)
+ public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption {
+ if (samlResponse != null && samlResponse instanceof Response) {
+ List<Assertion> assertions = ((Response) samlResponse).getAssertions();
+ if (assertions.size() == 0)
throw new AssertionAttributeExtractorExeption("Assertion");
- else if (samlResponse.getAssertions().size() > 1)
+ else if (assertions.size() > 1)
Logger.warn("Found more then ONE PVP2.1 assertions. Only the First is used.");
- assertion = samlResponse.getAssertions().get(0);
+ assertion = assertions.get(0);
} else
throw new AssertionAttributeExtractorExeption();
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
index 6388042d9..3be5df917 100644
--- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
+++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java
@@ -32,6 +32,7 @@ import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.RequestAbstractType;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.core.StatusResponseType;
import org.opensaml.saml2.encryption.Decrypter;
import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;
import org.opensaml.saml2.metadata.IDPSSODescriptor;
@@ -76,7 +77,7 @@ public class SAMLVerificationEngine {
}
- public void verifyResponse(Response samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
+ public void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {
SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
try {
profileValidator.validate(samlObj.getSignature());
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 c8cca157d..9aab22ef5 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
@@ -243,9 +243,9 @@ pvp2.16=Fehler beim verschl\u00FCsseln der PVP2 Assertion
pvp2.17=Der QAA Level {0} entspricht nicht dem angeforderten QAA Level {1}
pvp2.18=Es konnten nicht alle Single Sign-On Sessions beendet werden.
pvp2.19=Der Single LogOut Vorgang musste wegen eines unkorregierbaren Fehler abgebrochen werden.
-pvp2.20=Für die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
+pvp2.20=F\u00FCr die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
pvp2.21=Die Signature des Requests konnte nicht g\u00FCltig validiert werden.
-pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler={0}).
+pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler\={0}).
oauth20.01=Fehlerhafte redirect url
oauth20.02=Fehlender Parameter "{0}"
@@ -256,3 +256,6 @@ oauth20.06=Die angegebene OA kann nicht verwendet werden
oauth20.07=Angeforderter grant_type ist nicht erlaubt
oauth20.08=Nicht berechtigt f\u00FCr Token-Request
oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{0}"
+
+slo.00=Sie konnten erfolgreich von allen Online-Applikation abgemeldet werden.
+slo.01=Sie konnten NICHT erfolgreich von allen Online-Applikationen abgemeldet werden\!<BR>Bitte schlie\u00DFen Sie aus sicherheitsgr\u00FCnden Ihren Browser.
diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
new file mode 100644
index 000000000..16c9e87eb
--- /dev/null
+++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html
@@ -0,0 +1,57 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+
+<body>
+ <noscript>
+ <p>
+ <strong>Note:</strong> Since your browser does not support
+ JavaScript, you must press the Continue button once to proceed.
+ </p>
+ </noscript>
+
+ <h1>MOA-ID Single LogOut Information</h1>
+
+ <style type="text/css">
+
+ #alert {
+ margin: 100px 250px;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 14px;
+ font-weight: normal;
+ color: red;
+ }
+
+ #reqFrame {
+ display: none;
+
+ }
+
+</style>
+
+ #if($errorMsg)
+ <div class="alert">
+ <p>$errorMsg</p>
+ </div>
+ #end
+
+ #if($successMsg)
+ <div>
+ <p>$successMsg</p>
+ </div>
+ #end
+
+ #if($redirectURLs)
+ <div>
+ <p>
+ Sie werden von allen Online-Applikationen abgemeldet. <br>
+ Dieser Vorgang kann einige Zeit in Anspruch nehmen.
+ </p>
+ </div>
+ #end
+
+ #foreach( $el in $redirectURLs )
+ <iframe src=$el class="reqFrame"></iframe>
+ #end
+
+
+</body>
+</html> \ No newline at end of file