aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lenz <tlenz@iaik.tugraz.at>2014-06-03 17:10:11 +0200
committerThomas Lenz <tlenz@iaik.tugraz.at>2014-06-03 17:10:11 +0200
commit78c78fc0045580d3456fcb9563209223cf425eb6 (patch)
tree740c5808173030046856879571ec721c241d72da
parentcc20e4171331f78a1bb188f2b885c9754da58a28 (diff)
downloadmoa-id-spss-78c78fc0045580d3456fcb9563209223cf425eb6.tar.gz
moa-id-spss-78c78fc0045580d3456fcb9563209223cf425eb6.tar.bz2
moa-id-spss-78c78fc0045580d3456fcb9563209223cf425eb6.zip
implement configuration tool single logout
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java9
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticatedUser.java28
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticationManager.java84
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/IActiveUserStorage.java35
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/MemoryActiveUserStorageImpl.java71
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVP2Utils.java232
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/Authenticate.java (renamed from id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/Authenticate.java)55
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/BuildMetadata.java (renamed from id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/BuildMetadata.java)21
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java159
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java271
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java287
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java8
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/PVP2Exception.java55
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/SLOException.java53
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/filter/AuthenticationFilter.java47
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/helper/FormDataHelper.java2
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/IndexAction.java95
-rw-r--r--id/ConfigWebTool/src/main/resources/applicationResources_de.properties3
-rw-r--r--id/ConfigWebTool/src/main/resources/applicationResources_en.properties3
-rw-r--r--id/ConfigWebTool/src/main/webapp/WEB-INF/web.xml26
20 files changed, 1427 insertions, 117 deletions
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java
index df1faa7c0..61880b0cb 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/Constants.java
@@ -35,6 +35,9 @@ public class Constants {
public static final String SERVLET_PVP2ASSERTION = "pvp2login.action";
public static final String SERVLET_ACCOUNTVERIFICATION = "mailAddressVerification.action";
+ public static final String SERVLET_LOGOUT = "logout.action";
+ public static final String SERVLET_SLO_FRONT = "servlet/sloFrontChannel";
+ public static final String SERVLET_SLO_BACK = "servlet/sloBackChannel";
public static final String STRUTS_SUCCESS = "success";
public static final String STRUTS_ERROR = "error";
@@ -58,6 +61,9 @@ public class Constants {
public static final String SESSION_SENDASSERTIONTEMPLATE = "sendAssertionTemplate";
public static final String SESSION_SLTRANSFORMATION = "slTransformation";
+ public static final String SESSION_SLOERROR = "sloerrormessage";
+ public static final String SESSION_SLOSUCCESS = "slosuccessmessage";
+
public static final String SESSION_I18n = "WW_TRANS_I18N_LOCALE";
@@ -69,6 +75,8 @@ public class Constants {
public static final String REQUEST_FORMCUSTOM_MODULE = "module";
public static final String REQUEST_FORMCUSTOM_VALUE = "value";
+ public static final String REQUEST_USERSLO = "userLogOut";
+
public static final String BKU_ONLINE = "bkuonline";
public static final String BKU_LOCAL = "bkulocal";
public static final String BKU_HANDY = "bkuhandy";
@@ -97,6 +105,7 @@ public class Constants {
public static final Map<String, String> BUSINESSSERVICENAMES;
+
static {
Hashtable<String, String> tmp = new Hashtable<String, String>();
tmp.put(IDENIFICATIONTYPE_FN, "Firmenbuchnummer");
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticatedUser.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticatedUser.java
index 330ed7036..036acf1f6 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticatedUser.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticatedUser.java
@@ -47,6 +47,9 @@ public class AuthenticatedUser {
private String businessServiceType;
private String businessServiceNumber;
+ private String nameID = null;
+ private String nameIDFormat = null;
+
private AuthenticatedUser() {
}
@@ -68,7 +71,8 @@ public class AuthenticatedUser {
return user;
}
- public static AuthenticatedUser generateUserRequestUser(UserDatabaseFrom form) {
+ public static AuthenticatedUser generateUserRequestUser(UserDatabaseFrom form,
+ String nameID, String nameIDFormat) {
AuthenticatedUser user = new AuthenticatedUser();
user.familyName = form.getFamilyName();
@@ -82,11 +86,14 @@ public class AuthenticatedUser {
user.isPVP2Login = form.isPVPGenerated();
user.lastLogin = new Date();
+ user.nameID = nameID;
+ user.nameIDFormat = nameIDFormat;
+
return user;
}
public AuthenticatedUser(UserDatabase userdb, boolean isAuthenticated, boolean isMandateUser,
- boolean isPVP2Login) {
+ boolean isPVP2Login, String nameID, String nameIDFormat) {
this.familyName = userdb.getFamilyname();
this.givenName = userdb.getGivenname();
@@ -99,6 +106,9 @@ public class AuthenticatedUser {
this.isPVP2Login = isPVP2Login;
this.lastLogin = new Date();
+ this.nameID = nameID;
+ this.nameIDFormat = nameIDFormat;
+
if (!this.isAdmin) generateUserSpecificConfigurationOptions(userdb);
}
@@ -226,6 +236,20 @@ public class AuthenticatedUser {
public void setLastLogin(Date lastLogin) {
this.lastLogin = lastLogin;
}
+
+ /**
+ * @return the nameID
+ */
+ public String getNameID() {
+ return nameID;
+ }
+
+ /**
+ * @return the nameIDFormat
+ */
+ public String getNameIDFormat() {
+ return nameIDFormat;
+ }
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticationManager.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticationManager.java
new file mode 100644
index 000000000..6d3afffc9
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/AuthenticationManager.java
@@ -0,0 +1,84 @@
+/*
+ * 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.configuration.auth;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * @author tlenz
+ *
+ */
+public class AuthenticationManager {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(AuthenticationManager.class);
+
+ private static AuthenticationManager instance = null;
+ private static IActiveUserStorage activeUsers = null;
+
+ public static AuthenticationManager getInstance() {
+ if (instance == null)
+ instance = new AuthenticationManager();
+
+ return instance;
+ }
+
+ private AuthenticationManager() {
+ activeUsers = new MemoryActiveUserStorageImpl();
+
+ }
+
+ public AuthenticatedUser getActiveUser(String nameID) {
+ return activeUsers.getUser(nameID);
+ }
+
+ public void setActiveUser(AuthenticatedUser authUser) {
+ log.debug("LogIn user with nameID:" + authUser.getNameID());
+ activeUsers.setUser(authUser.getNameID(), authUser);
+
+ }
+
+ public boolean isActiveUser(String nameID) {
+ AuthenticatedUser user = activeUsers.getUser(nameID);
+ if (user != null && user.isAuthenticated())
+ return true;
+ else
+ return false;
+ }
+
+ public boolean isActiveUser(AuthenticatedUser authUser) {
+ if (authUser != null)
+ return isActiveUser(authUser.getNameID());
+ else
+ return false;
+ }
+
+ public void removeActiveUser(AuthenticatedUser authUser) {
+ log.debug("LogOut active user " + authUser.getGivenName() + " " + authUser.getFamilyName()
+ + " dbID: " + authUser.getUserID() + " nameID:" + authUser.getNameID());
+ activeUsers.removeUser(authUser.getNameID());
+
+ }
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/IActiveUserStorage.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/IActiveUserStorage.java
new file mode 100644
index 000000000..c52fee140
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/IActiveUserStorage.java
@@ -0,0 +1,35 @@
+/*
+ * 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.configuration.auth;
+
+/**
+ * @author tlenz
+ *
+ */
+public interface IActiveUserStorage {
+
+ public AuthenticatedUser getUser(String nameID);
+ public void setUser(String nameID, AuthenticatedUser authUser);
+ public void removeUser(String nameID);
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/MemoryActiveUserStorageImpl.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/MemoryActiveUserStorageImpl.java
new file mode 100644
index 000000000..145da2c35
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/MemoryActiveUserStorageImpl.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.configuration.auth;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author tlenz
+ *
+ */
+public class MemoryActiveUserStorageImpl implements IActiveUserStorage {
+
+ private Map<String, AuthenticatedUser> store = null;
+
+ /**
+ *
+ */
+ public MemoryActiveUserStorageImpl() {
+ store = new HashMap<String, AuthenticatedUser>();
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.configuration.auth.IActiveUserStorage#getUser(java.lang.String)
+ */
+ @Override
+ public AuthenticatedUser getUser(String nameID) {
+ return store.get(nameID);
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.configuration.auth.IActiveUserStorage#setUser(java.lang.String, at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser)
+ */
+ @Override
+ public void setUser(String nameID, AuthenticatedUser authUser) {
+ store.put(nameID, authUser);
+
+ }
+
+ /* (non-Javadoc)
+ * @see at.gv.egovernment.moa.id.configuration.auth.IActiveUserStorage#removeUser(java.lang.String)
+ */
+ @Override
+ public void removeUser(String nameID) {
+ if (store.containsKey(nameID))
+ store.remove(nameID);
+
+ }
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVP2Utils.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVP2Utils.java
new file mode 100644
index 000000000..5032222d0
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVP2Utils.java
@@ -0,0 +1,232 @@
+/*
+ * 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.configuration.auth.pvp2;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.SignableSAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.binding.encoding.HTTPPostEncoder;
+import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder;
+import org.opensaml.saml2.core.RequestAbstractType;
+import org.opensaml.saml2.core.StatusResponseType;
+import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.SingleSignOnService;
+import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder;
+import org.opensaml.security.MetadataCredentialResolver;
+import org.opensaml.security.MetadataCredentialResolverFactory;
+import org.opensaml.security.MetadataCriteria;
+import org.opensaml.security.SAMLSignatureProfileValidator;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
+import org.opensaml.xml.security.CriteriaSet;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.credential.UsageType;
+import org.opensaml.xml.security.criteria.EntityIDCriteria;
+import org.opensaml.xml.security.criteria.UsageCriteria;
+import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver;
+import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
+import org.opensaml.xml.security.keyinfo.KeyInfoProvider;
+import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider;
+import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider;
+import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider;
+import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.AbstractSignableXMLObject;
+import org.opensaml.xml.signature.SignableXMLObject;
+import org.opensaml.xml.signature.Signature;
+import org.opensaml.xml.signature.SignatureConstants;
+import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;
+import org.opensaml.xml.validation.ValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
+import at.gv.egovernment.moa.id.configuration.exception.PVP2Exception;
+import at.gv.egovernment.moa.id.configuration.utils.SAML2Utils;
+
+/**
+ * @author tlenz
+ *
+ */
+public class PVP2Utils {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(PVP2Utils.class);
+
+ public static void postBindingEncoder(HttpServletRequest req, HttpServletResponse resp,
+ SignableSAMLObject pvp2Req, X509Credential authcredential, String targetLocation, String relayState) throws PVP2Exception {
+ try {
+ VelocityEngine engine = new VelocityEngine();
+ engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
+ engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
+ engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
+ engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
+ engine.setProperty("classpath.resource.loader.class",
+ "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
+ "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
+ engine.init();
+
+ HTTPPostEncoder encoder = new HTTPPostEncoder(engine,
+ "templates/pvp_postbinding_template.html");
+ HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
+ resp, true);
+ BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ SingleSignOnService service = new SingleSignOnServiceBuilder()
+ .buildObject();
+ service.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ service.setLocation(targetLocation);
+
+ context.setOutboundSAMLMessageSigningCredential(authcredential);
+ context.setPeerEntityEndpoint(service);
+ context.setOutboundSAMLMessage(pvp2Req);
+ context.setOutboundMessageTransport(responseAdapter);
+ context.setRelayState(relayState);
+
+ encoder.encode(context);
+
+ } catch (MessageEncodingException e) {
+ log.warn("Encode PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Encode PVP 2.1 message FAILED.", e);
+
+ }
+ }
+
+
+ /**
+ * @param request
+ * @param response
+ * @param sloReq
+ * @param authcredential
+ * @param location
+ * @param object
+ * @throws PVP2Exception
+ */
+ public static void redirectBindingEncoder(HttpServletRequest request,
+ HttpServletResponse response, SignableSAMLObject pvp2Req,
+ X509Credential authcredential, String location, String relayState) throws PVP2Exception {
+ try {
+ HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
+ HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
+ response
+ , true);
+ BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ SingleSignOnService service = new SingleSignOnServiceBuilder()
+ .buildObject();
+ service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ service.setLocation(location);
+ context.setOutboundSAMLMessageSigningCredential(authcredential);
+ context.setPeerEntityEndpoint(service);
+ context.setOutboundSAMLMessage(pvp2Req);
+ context.setOutboundMessageTransport(responseAdapter);
+ context.setRelayState(relayState);
+
+ encoder.encode(context);
+ } catch (MessageEncodingException e) {
+ log.warn("Encode PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Encode PVP 2.1 message FAILED.", e);
+
+ }
+ }
+
+ public static void validateSignature(SignableXMLObject msg, ConfigurationProvider configuration) throws SecurityException, ValidationException {
+ //Validate Signature
+ SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
+ profileValidator.validate(msg.getSignature());
+
+ //Verify Signature
+ List<KeyInfoProvider> keyInfoProvider = new ArrayList<KeyInfoProvider>();
+ keyInfoProvider.add(new DSAKeyValueProvider());
+ keyInfoProvider.add(new RSAKeyValueProvider());
+ keyInfoProvider.add(new InlineX509DataProvider());
+
+ KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver(
+ keyInfoProvider);
+
+ MetadataCredentialResolverFactory credentialResolverFactory = MetadataCredentialResolverFactory.getFactory();
+ MetadataCredentialResolver credentialResolver = credentialResolverFactory.getInstance(configuration.getMetaDataProvier());
+
+ CriteriaSet criteriaSet = new CriteriaSet();
+ criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS));
+ criteriaSet.add(new EntityIDCriteria(configuration.getPVP2IDPMetadataEntityName()));
+ criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
+
+ ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver);
+ trustEngine.validate(msg.getSignature(), criteriaSet);
+ }
+
+ public static X509Credential signMessage(AbstractSignableXMLObject msg, ConfigurationProvider config) throws PVP2Exception {
+ //sign authentication request
+ KeyStore keyStore;
+ try {
+ keyStore = config.getPVP2KeyStore();
+ X509Credential authcredential = new KeyStoreX509CredentialAdapter(
+ keyStore,
+ config.getPVP2KeystoreAuthRequestKeyAlias(),
+ config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray());
+
+ Signature signer = SAML2Utils.createSAMLObject(Signature.class);
+ signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
+ signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ signer.setSigningCredential(authcredential);
+ msg.setSignature(signer);
+
+ return authcredential;
+
+ } catch (NoSuchAlgorithmException e) {
+ log.warn("Sign PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Sign PVP 2.1 message FAILED.", e);
+
+ } catch (CertificateException e) {
+ log.warn("Sign PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Sign PVP 2.1 message FAILED.", e);
+
+ } catch (KeyStoreException e) {
+ log.warn("Sign PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Sign PVP 2.1 message FAILED.", e);
+
+ } catch (ConfigurationException e) {
+ log.warn("Sign PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Sign PVP 2.1 message FAILED.", e);
+
+ } catch (IOException e) {
+ log.warn("Sign PVP 2.1 message FAILED.", e);
+ throw new PVP2Exception("Sign PVP 2.1 message FAILED.", e);
+ }
+ }
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/Authenticate.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/Authenticate.java
index abcfd67e9..56f6d8827 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/Authenticate.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/Authenticate.java
@@ -20,7 +20,7 @@
* 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.configuration.auth.pvp2;
+package at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets;
import java.io.IOException;
import java.security.KeyStore;
@@ -64,6 +64,7 @@ import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter;
import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.AbstractSignableXMLObject;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureConstants;
import org.slf4j.Logger;
@@ -71,6 +72,7 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import at.gv.egovernment.moa.id.configuration.Constants;
+import at.gv.egovernment.moa.id.configuration.auth.pvp2.PVP2Utils;
import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
import at.gv.egovernment.moa.id.configuration.utils.SAML2Utils;
@@ -190,48 +192,17 @@ public class Authenticate extends HttpServlet {
authReq.setRequestedAuthnContext(reqAuthContext);
- KeyStore keyStore = config.getPVP2KeyStore();
-
- X509Credential authcredential = new KeyStoreX509CredentialAdapter(
- keyStore,
- config.getPVP2KeystoreAuthRequestKeyAlias(),
- config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray());
-
- Signature signer = SAML2Utils.createSAMLObject(Signature.class);
- signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
- signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
- signer.setSigningCredential(authcredential);
-
- authReq.setSignature(signer);
-
- VelocityEngine engine = new VelocityEngine();
- engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
- engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
- engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
- engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
- engine.setProperty("classpath.resource.loader.class",
- "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
- engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
- "org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
- engine.init();
-
- HTTPPostEncoder encoder = new HTTPPostEncoder(engine,
- "templates/pvp_postbinding_template.html");
- HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
- response, true);
- BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
- SingleSignOnService service = new SingleSignOnServiceBuilder()
- .buildObject();
- service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
- service.setLocation(redirectEndpoint.getLocation());;
+ //sign Message
+ X509Credential authcredential = PVP2Utils.signMessage((AbstractSignableXMLObject) authReq, config);
+
+ //encode message
+ PVP2Utils.postBindingEncoder(request,
+ response,
+ authReq,
+ authcredential,
+ redirectEndpoint.getLocation(),
+ null);
- context.setOutboundSAMLMessageSigningCredential(authcredential);
- context.setPeerEntityEndpoint(service);
- context.setOutboundSAMLMessage(authReq);
- context.setOutboundMessageTransport(responseAdapter);
-
- encoder.encode(context);
-
} catch (Exception e) {
log.warn("Authentication Request can not be generated", e);
throw new ServletException("Authentication Request can not be generated.", e);
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/BuildMetadata.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/BuildMetadata.java
index 9a0f73a1f..5265aed86 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/BuildMetadata.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/BuildMetadata.java
@@ -20,7 +20,7 @@
* 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.configuration.auth.pvp2;
+package at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets;
import java.io.IOException;
import java.io.StringWriter;
@@ -59,6 +59,7 @@ import org.opensaml.saml2.metadata.LocalizedString;
import org.opensaml.saml2.metadata.NameIDFormat;
import org.opensaml.saml2.metadata.SPSSODescriptor;
import org.opensaml.saml2.metadata.ServiceName;
+import org.opensaml.saml2.metadata.SingleLogoutService;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.SecurityException;
@@ -75,6 +76,7 @@ import org.opensaml.xml.signature.Signer;
import org.w3c.dom.Document;
import at.gv.egovernment.moa.id.configuration.Constants;
+import at.gv.egovernment.moa.id.configuration.auth.pvp2.AttributeListBuilder;
import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
import at.gv.egovernment.moa.id.configuration.utils.SAML2Utils;
@@ -228,6 +230,23 @@ public class BuildMetadata extends HttpServlet {
spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService);
+
+ //add SLO services
+ SingleLogoutService postBindingService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
+ postBindingService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);
+ postBindingService.setLocation(serviceURL + Constants.SERVLET_SLO_FRONT);
+ spSSODescriptor.getSingleLogoutServices().add(postBindingService);
+
+ SingleLogoutService redirectBindingService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
+ redirectBindingService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);
+ redirectBindingService.setLocation(serviceURL + Constants.SERVLET_SLO_FRONT);
+ spSSODescriptor.getSingleLogoutServices().add(redirectBindingService);
+
+ SingleLogoutService soapBindingService = SAML2Utils.createSAMLObject(SingleLogoutService.class);
+ soapBindingService.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI);
+ soapBindingService.setLocation(serviceURL + Constants.SERVLET_SLO_BACK);
+ spSSODescriptor.getSingleLogoutServices().add(soapBindingService);
+
spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);
spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor);
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java
new file mode 100644
index 000000000..4b23089c4
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBackChannelServlet.java
@@ -0,0 +1,159 @@
+/*
+ * 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.configuration.auth.pvp2.servlets;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.List;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.saml2.binding.encoding.HTTPSOAP11Encoder;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.LogoutResponse;
+import org.opensaml.ws.message.decoder.MessageDecodingException;
+import org.opensaml.ws.message.encoder.MessageEncodingException;
+import org.opensaml.ws.soap.soap11.Envelope;
+import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder;
+import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
+import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
+import org.opensaml.xml.XMLObject;
+import org.opensaml.xml.parse.BasicParserPool;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SLOBackChannelServlet extends SLOBasicServlet {
+
+ private static final long serialVersionUID = 1481623547633064922L;
+ private static final Logger log = LoggerFactory
+ .getLogger(SLOBackChannelServlet.class);
+
+ /**
+ * @throws ConfigurationException
+ */
+ public SLOBackChannelServlet() throws ConfigurationException {
+ super();
+ }
+
+
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+
+ try {
+ HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool());
+ BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =
+ new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ messageContext
+ .setInboundMessageTransport(new HttpServletRequestAdapter(
+ request));
+
+ soapDecoder.decode(messageContext);
+
+ Envelope inboundMessage = (Envelope) messageContext
+ .getInboundMessage();
+
+ if (inboundMessage.getBody() != null) {
+ List<XMLObject> xmlElemList = inboundMessage.getBody().getUnknownXMLObjects();
+
+ LogoutResponse sloResp;
+ if (!xmlElemList.isEmpty() && xmlElemList.get(0) instanceof LogoutRequest) {
+ LogoutRequest sloReq = (LogoutRequest) xmlElemList.get(0);
+ sloResp = processLogOutRequest(sloReq, request);
+
+ KeyStore keyStore = getConfig().getPVP2KeyStore();
+ X509Credential authcredential = new KeyStoreX509CredentialAdapter(
+ keyStore,
+ getConfig().getPVP2KeystoreAuthRequestKeyAlias(),
+ getConfig().getPVP2KeystoreAuthRequestKeyPassword().toCharArray());
+
+ HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
+ HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(
+ response, true);
+ BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ context.setOutboundSAMLMessageSigningCredential(authcredential);
+ context.setOutboundSAMLMessage(sloResp);
+ context.setOutboundMessageTransport(responseAdapter);
+
+ encoder.encode(context);
+
+ } else {
+ log.warn("Received request ist not of type LogOutRequest");
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+
+ }
+ }
+
+ } catch (MessageDecodingException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (SecurityException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (NoSuchAlgorithmException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (CertificateException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (KeyStoreException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (ConfigurationException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ } catch (MessageEncodingException e) {
+ log.error("SLO message processing FAILED." , e);
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+
+ }
+ }
+
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+
+ }
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java
new file mode 100644
index 000000000..69adcc661
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java
@@ -0,0 +1,271 @@
+/*
+ * 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.configuration.auth.pvp2.servlets;
+
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.joda.time.DateTime;
+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.NameIDType;
+import org.opensaml.saml2.core.Status;
+import org.opensaml.saml2.core.StatusCode;
+import org.opensaml.saml2.metadata.EntityDescriptor;
+import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider;
+import org.opensaml.saml2.metadata.provider.MetadataProviderException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.configuration.Constants;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticationManager;
+import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
+import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
+import at.gv.egovernment.moa.id.configuration.exception.PVP2Exception;
+import at.gv.egovernment.moa.id.configuration.exception.SLOException;
+import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper;
+import at.gv.egovernment.moa.id.configuration.utils.SAML2Utils;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SLOBasicServlet extends HttpServlet {
+ private static final long serialVersionUID = -4547240664871845098L;
+ private static final Logger log = LoggerFactory
+ .getLogger(SLOBasicServlet.class);
+
+ private ConfigurationProvider config;
+
+ public SLOBasicServlet() throws ConfigurationException {
+ config = ConfigurationProvider.getInstance();
+ config.initializePVP2Login();
+ }
+
+ protected LogoutRequest createLogOutRequest(String nameID, String nameIDFormat, HttpServletRequest request) throws SLOException {
+ try {
+ LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class);
+ SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator();
+ sloReq.setID(gen.generateIdentifier());
+ request.getSession().setAttribute(Constants.SESSION_PVP2REQUESTID, sloReq.getID());
+ sloReq.setIssueInstant(new DateTime());
+ NameID name = SAML2Utils.createSAMLObject(NameID.class);
+ Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
+
+ String serviceURL = config.getPublicUrlPreFix(request);
+ if (!serviceURL.endsWith("/"))
+ serviceURL = serviceURL + "/";
+ name.setValue(serviceURL);
+ issuer.setValue(serviceURL);
+ issuer.setFormat(NameIDType.ENTITY);
+ sloReq.setIssuer(issuer);
+
+ NameID userNameID = SAML2Utils.createSAMLObject(NameID.class);
+ sloReq.setNameID(userNameID);
+ userNameID.setFormat(nameIDFormat);
+ userNameID.setValue(nameID);
+
+ return sloReq;
+
+ } catch (NoSuchAlgorithmException e) {
+ log.warn("Single LogOut request createn FAILED. ", e);
+ throw new SLOException();
+
+ }
+
+ }
+
+ protected LogoutResponse processLogOutRequest(LogoutRequest sloReq, HttpServletRequest request) throws NoSuchAlgorithmException {
+ //check response destination
+ String serviceURL = config.getPublicUrlPreFix(request);
+ if (!serviceURL.endsWith("/"))
+ serviceURL = serviceURL + "/";
+
+ String responseDestination = sloReq.getDestination();
+ if (MiscUtil.isEmpty(responseDestination) ||
+ !responseDestination.startsWith(serviceURL)) {
+ log.warn("PVPResponse destination does not match requested destination");
+ return createSLOResponse(sloReq, StatusCode.REQUESTER_URI, request);
+ }
+
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ if (authManager.isActiveUser(sloReq.getNameID().getValue())) {
+ AuthenticatedUser authUser = authManager.getActiveUser(sloReq.getNameID().getValue());
+ log.info("User " + authUser.getGivenName() + " " + authUser.getFamilyName() + " with nameID:"
+ + authUser.getNameID() + " get logged out by Single LogOut request.");
+ authManager.removeActiveUser(authUser);
+ HttpSession session = request.getSession(false);
+ if (session != null)
+ session.invalidate();
+
+ return createSLOResponse(sloReq, StatusCode.SUCCESS_URI, request);
+
+ } else {
+ log.debug("Single LogOut not possible! User with nameID:" + sloReq.getNameID().getValue() + " is not found.");
+ return createSLOResponse(sloReq, StatusCode.PARTIAL_LOGOUT_URI, request);
+
+ }
+
+ }
+
+ private LogoutResponse createSLOResponse(LogoutRequest sloReq, String statusCodeURI, HttpServletRequest request) throws NoSuchAlgorithmException {
+ LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);
+ SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator();
+ sloResp.setID(gen.generateIdentifier());
+ sloResp.setInResponseTo(sloReq.getID());
+ sloResp.setIssueInstant(new DateTime());
+ NameID name = SAML2Utils.createSAMLObject(NameID.class);
+ Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);
+
+ String serviceURL = config.getPublicUrlPreFix(request);
+ if (!serviceURL.endsWith("/"))
+ serviceURL = serviceURL + "/";
+ name.setValue(serviceURL);
+ issuer.setValue(serviceURL);
+ issuer.setFormat(NameIDType.ENTITY);
+ sloResp.setIssuer(issuer);
+
+ Status status = SAML2Utils.createSAMLObject(Status.class);
+ sloResp.setStatus(status);
+ StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);
+ statusCode.setValue(statusCodeURI);
+ status.setStatusCode(statusCode );
+
+ return sloResp;
+ }
+
+ protected void validateLogOutResponse(LogoutResponse sloResp, String reqID, HttpServletRequest request, HttpServletResponse response) throws PVP2Exception {
+ //ckeck InResponseTo matchs requestID
+ if (MiscUtil.isEmpty(reqID)) {
+ log.info("NO Sigle LogOut request ID");
+ throw new PVP2Exception("NO Sigle LogOut request ID");
+ }
+
+ if (!reqID.equals(sloResp.getInResponseTo())) {
+ log.warn("SLORequestID does not match SLO Response ID!");
+ throw new PVP2Exception("SLORequestID does not match SLO Response ID!");
+
+ }
+
+ //check response destination
+ String serviceURL = config.getPublicUrlPreFix(request);
+ if (!serviceURL.endsWith("/"))
+ serviceURL = serviceURL + "/";
+
+ String responseDestination = sloResp.getDestination();
+ if (MiscUtil.isEmpty(responseDestination) ||
+ !responseDestination.startsWith(serviceURL)) {
+ log.warn("PVPResponse destination does not match requested destination");
+ throw new PVP2Exception("SLO response destination does not match requested destination");
+ }
+
+ request.getSession().invalidate();
+
+ if (sloResp.getStatus().getStatusCode().getValue().equals(StatusCode.PARTIAL_LOGOUT_URI)) {
+ log.warn("Single LogOut process is not completed.");
+ request.getSession().setAttribute(Constants.SESSION_SLOERROR,
+ LanguageHelper.getErrorString("webpages.slo.error", request));
+
+
+ } else if (sloResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
+ log.info("Single LogOut process complete.");
+ request.getSession().setAttribute(Constants.SESSION_SLOSUCCESS,
+ LanguageHelper.getErrorString("webpages.slo.success", request));
+
+
+ } else {
+ log.warn("Single LogOut response sends an unsupported statustype " + sloResp.getStatus().getStatusCode().getValue());
+ request.getSession().setAttribute(Constants.SESSION_SLOERROR,
+ LanguageHelper.getErrorString("webpages.slo.error", request));
+
+ }
+ String redirectURL = serviceURL + Constants.SERVLET_LOGOUT;
+ redirectURL = response.encodeRedirectURL(redirectURL);
+ response.setContentType("text/html");
+ response.setStatus(302);
+ response.addHeader("Location", redirectURL);
+
+ }
+
+ protected SingleLogoutService findIDPFrontChannelSLOService() throws
+ ConfigurationException, SLOException {
+
+ String entityname = config.getPVP2IDPMetadataEntityName();
+ if (MiscUtil.isEmpty(entityname)) {
+ log.info("No IDP EntityName configurated");
+ throw new ConfigurationException("No IDP EntityName configurated");
+ }
+
+ //get IDP metadata from metadataprovider
+ HTTPMetadataProvider idpmetadata = config.getMetaDataProvier();
+ try {
+ EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname);
+ if (idpEntity == null) {
+ log.info("IDP EntityName is not found in IDP Metadata");
+ throw new ConfigurationException("IDP EntityName is not found in IDP Metadata");
+
+ }
+
+ //select authentication-service url from metadata
+ SingleLogoutService redirectEndpoint = null;
+ for (SingleLogoutService sss :
+ idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleLogoutServices()) {
+
+ //Get the service address for the binding you wish to use
+ if (sss.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))
+ redirectEndpoint = sss;
+
+ else if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI) &&
+ redirectEndpoint == null)
+ redirectEndpoint = sss;
+ }
+
+ if (redirectEndpoint == null) {
+ log.warn("Single LogOut FAILED: IDP implements no frontchannel SLO service.");
+ throw new SLOException("Single LogOut FAILED: IDP implements no frontchannel SLO service.");
+ }
+
+ return redirectEndpoint;
+ } catch (MetadataProviderException e) {
+ log.info("IDP EntityName is not found in IDP Metadata", e);
+ throw new ConfigurationException("IDP EntityName is not found in IDP Metadata");
+
+ }
+ }
+
+ protected ConfigurationProvider getConfig() {
+ return config;
+ }
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java
new file mode 100644
index 000000000..eb5752982
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java
@@ -0,0 +1,287 @@
+/*
+ * 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.configuration.auth.pvp2.servlets;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.opensaml.common.SAMLObject;
+import org.opensaml.common.SignableSAMLObject;
+import org.opensaml.common.binding.BasicSAMLMessageContext;
+import org.opensaml.common.xml.SAMLConstants;
+import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
+import org.opensaml.saml2.binding.decoding.HTTPRedirectDeflateDecoder;
+import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule;
+import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule;
+import org.opensaml.saml2.core.LogoutRequest;
+import org.opensaml.saml2.core.LogoutResponse;
+import org.opensaml.saml2.core.RequestAbstractType;
+import org.opensaml.saml2.core.Response;
+import org.opensaml.saml2.core.StatusResponseType;
+import org.opensaml.saml2.metadata.IDPSSODescriptor;
+import org.opensaml.saml2.metadata.SingleLogoutService;
+import org.opensaml.ws.message.decoder.MessageDecodingException;
+import org.opensaml.ws.security.SecurityPolicyException;
+import org.opensaml.ws.security.SecurityPolicyResolver;
+import org.opensaml.ws.security.provider.BasicSecurityPolicy;
+import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;
+import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
+import org.opensaml.xml.XMLObject;
+import org.opensaml.xml.parse.BasicParserPool;
+import org.opensaml.xml.security.SecurityException;
+import org.opensaml.xml.security.x509.X509Credential;
+import org.opensaml.xml.signature.AbstractSignableXMLObject;
+import org.opensaml.xml.signature.SignableXMLObject;
+import org.opensaml.xml.validation.ValidationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.gv.egovernment.moa.id.configuration.Constants;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticationManager;
+import at.gv.egovernment.moa.id.configuration.auth.pvp2.PVP2Utils;
+import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
+import at.gv.egovernment.moa.id.configuration.exception.PVP2Exception;
+import at.gv.egovernment.moa.id.configuration.exception.SLOException;
+import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper;
+import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory;
+import at.gv.egovernment.moa.util.MiscUtil;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SLOFrontChannelServlet extends SLOBasicServlet {
+
+ private static final long serialVersionUID = -6280199681356977759L;
+ private static final Logger log = LoggerFactory
+ .getLogger(SLOFrontChannelServlet.class);
+
+ /**
+ * @throws ConfigurationException
+ */
+ public SLOFrontChannelServlet() throws ConfigurationException {
+ super();
+ }
+
+ /**
+ * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
+ * response)
+ */
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ try {
+ if (MiscUtil.isNotEmpty(request.getParameter(Constants.REQUEST_USERSLO))) {
+ //process user initiated single logout process
+ Object authUserObj = request.getSession().getAttribute(Constants.SESSION_AUTH);
+ AuthenticatedUser authUser = (AuthenticatedUser) authUserObj;
+
+ String nameIDFormat = authUser.getNameIDFormat();
+ String nameID = authUser.getNameID();
+
+ //remove user
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.removeActiveUser(authUser);
+
+ if (MiscUtil.isEmpty(nameID) || MiscUtil.isEmpty(nameIDFormat)) {
+ log.warn("No user information found. Single Log-Out not possible");
+ buildErrorMessage(request, response);
+
+ } else
+ log.info("Fount user information for user nameID: " + nameID
+ + " , nameIDFormat: " + nameIDFormat
+ + ". Build Single Log-Out request ...");
+
+ //build SLO request to IDP
+ LogoutRequest sloReq = createLogOutRequest(nameID, nameIDFormat, request);
+
+ //send message
+ sendMessage(request, response, sloReq, null);
+
+ } else {
+ //process PVP 2.1 single logout process
+ HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(
+ new BasicParserPool());
+ BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();
+ messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
+ messageContext.setMetadataProvider(getConfig().getMetaDataProvier());
+
+ SAML2HTTPRedirectDeflateSignatureRule signatureRule = new SAML2HTTPRedirectDeflateSignatureRule(
+ TrustEngineFactory.getSignatureKnownKeysTrustEngine());
+ SAML2AuthnRequestsSignedRule signedRole = new SAML2AuthnRequestsSignedRule();
+ BasicSecurityPolicy policy = new BasicSecurityPolicy();
+ policy.getPolicyRules().add(signatureRule);
+ policy.getPolicyRules().add(signedRole);
+ SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver(
+ policy);
+ messageContext.setSecurityPolicyResolver(resolver);
+ messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME);
+
+ signatureRule.evaluate(messageContext);
+ decode.decode(messageContext);
+
+ processMessage(request, response,
+ messageContext.getInboundMessage(), messageContext.getRelayState());
+
+ }
+
+ } catch (SLOException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (ConfigurationException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (PVP2Exception e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (SecurityPolicyException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (MessageDecodingException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (SecurityException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ }
+ }
+
+ /**
+ * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
+ * response)
+ */
+ protected void doPost(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ try {
+ HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool());
+ BasicSAMLMessageContext<Response, ?, ?> messageContext = new BasicSAMLMessageContext<Response, SAMLObject, SAMLObject>();
+ messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request));
+ decode.decode(messageContext);
+
+ PVP2Utils.validateSignature((SignableXMLObject) messageContext.getInboundMessage(), getConfig());
+
+ processMessage(request, response,
+ messageContext.getInboundMessage(), messageContext.getRelayState());
+
+
+ } catch (MessageDecodingException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (SecurityException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (ValidationException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (ConfigurationException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (PVP2Exception e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ } catch (NoSuchAlgorithmException e) {
+ log.error("Single LogOut processing error.", e);
+ buildErrorMessage(request, response);
+
+ }
+ }
+
+ private void buildErrorMessage(HttpServletRequest request, HttpServletResponse response) {
+
+ request.getSession().setAttribute(Constants.SESSION_SLOERROR,
+ LanguageHelper.getErrorString("webpages.slo.error", request));
+
+ //check response destination
+ String serviceURL = getConfig().getPublicUrlPreFix(request);
+ if (!serviceURL.endsWith("/"))
+ serviceURL = serviceURL + "/";
+
+ String redirectURL = serviceURL + Constants.SERVLET_LOGOUT;
+ redirectURL = response.encodeRedirectURL(redirectURL);
+ response.setContentType("text/html");
+ response.setStatus(302);
+ response.addHeader("Location", redirectURL);
+ }
+
+ private void processMessage(HttpServletRequest request, HttpServletResponse response,
+ XMLObject xmlObject, String relayState) throws ConfigurationException, PVP2Exception, NoSuchAlgorithmException {
+ if (xmlObject instanceof LogoutRequest) {
+ LogoutResponse sloResp =
+ processLogOutRequest((LogoutRequest) xmlObject, request);
+ sendMessage(request, response, sloResp, relayState);
+
+ } else if (xmlObject instanceof LogoutResponse) {
+ LogoutResponse sloResp = (LogoutResponse) xmlObject;
+
+ String reqID = (String) request.getSession().getAttribute(Constants.SESSION_PVP2REQUESTID);
+ request.getSession().setAttribute(Constants.SESSION_PVP2REQUESTID, null);
+ validateLogOutResponse(sloResp, reqID, request, response);
+
+ }
+ }
+
+ private void sendMessage(HttpServletRequest request, HttpServletResponse response,
+ RequestAbstractType sloReq, String relayState) throws ConfigurationException, PVP2Exception {
+ SingleLogoutService sloService = findIDPFrontChannelSLOService();
+ sloReq.setDestination(sloService.getLocation());
+ sendMessage(request, response, sloReq, sloService, relayState);
+ }
+
+ private void sendMessage(HttpServletRequest request, HttpServletResponse response,
+ StatusResponseType sloReq, String relayState) throws ConfigurationException, PVP2Exception {
+ SingleLogoutService sloService = findIDPFrontChannelSLOService();
+ sloReq.setDestination(sloService.getLocation());
+ sendMessage(request, response, sloReq, sloService, relayState);
+ }
+
+ private void sendMessage(HttpServletRequest request, HttpServletResponse response,
+ SignableSAMLObject sloReq, SingleLogoutService sloService, String relayState) throws ConfigurationException, PVP2Exception {
+ X509Credential authcredential = PVP2Utils.signMessage((AbstractSignableXMLObject) sloReq, getConfig());
+ if (sloService.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI))
+ PVP2Utils.postBindingEncoder(request, response, sloReq, authcredential, sloService.getLocation(), relayState);
+
+ else if (sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))
+ PVP2Utils.redirectBindingEncoder(request, response, sloReq, authcredential, sloService.getLocation(), relayState);
+ }
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java
index a2aa2a8a4..e176e5141 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/config/ConfigurationProvider.java
@@ -53,12 +53,10 @@ import at.gv.egovernment.moa.id.commons.db.dao.config.ChainingModeType;
import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException;
import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory;
-import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
import at.gv.egovernment.moa.id.configuration.Constants;
import at.gv.egovernment.moa.id.configuration.auth.pvp2.MetaDataVerificationFilter;
import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
import at.gv.egovernment.moa.id.configuration.utils.UserRequestCleaner;
-import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;
import at.gv.egovernment.moa.util.FileUtils;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -85,8 +83,12 @@ public class ConfigurationProvider {
private boolean pvp2logininitialzied = false;
public static ConfigurationProvider getInstance() throws ConfigurationException {
+
if (instance == null) {
- instance = new ConfigurationProvider();
+ synchronized (ConfigurationProvider.class) {
+ instance = new ConfigurationProvider();
+ }
+
}
return instance;
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/PVP2Exception.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/PVP2Exception.java
new file mode 100644
index 000000000..c941c4bbe
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/PVP2Exception.java
@@ -0,0 +1,55 @@
+/*
+ * 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.configuration.exception;
+
+/**
+ * @author tlenz
+ *
+ */
+public class PVP2Exception extends Exception {
+
+ private static final long serialVersionUID = -3887330440491843927L;
+
+ /**
+ * @param string
+ */
+ public PVP2Exception(String string) {
+ super(string);
+ }
+
+ /**
+ *
+ */
+ public PVP2Exception() {
+ super();
+ }
+
+ /**
+ * @param string
+ * @param e
+ */
+ public PVP2Exception(String string, Throwable e) {
+ super(string, e);
+ }
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/SLOException.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/SLOException.java
new file mode 100644
index 000000000..5d34397f4
--- /dev/null
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/exception/SLOException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.configuration.exception;
+
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * @author tlenz
+ *
+ */
+public class SLOException extends PVP2Exception {
+ /**
+ * @param string
+ */
+ public SLOException(String string) {
+ super(string);
+ }
+
+ public SLOException() {
+ super();
+ }
+
+ /**
+ * @param string
+ * @param e
+ */
+ public SLOException(String string, Throwable e) {
+ super(string, e);
+ }
+
+ private static final long serialVersionUID = 6443077827626969931L;
+
+}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/filter/AuthenticationFilter.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/filter/AuthenticationFilter.java
index 190773bf0..9ca1d08cc 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/filter/AuthenticationFilter.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/filter/AuthenticationFilter.java
@@ -43,6 +43,7 @@ import javax.servlet.http.HttpSession;
import at.gv.egovernment.moa.id.configuration.Constants;
import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticationManager;
import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException;
import at.gv.egovernment.moa.util.MiscUtil;
@@ -136,12 +137,26 @@ public class AuthenticationFilter implements Filter{
HttpSession session = httpServletRequest.getSession();
- Object authuser = session.getAttribute(Constants.SESSION_AUTH);
+ Object authuserobj = session.getAttribute(Constants.SESSION_AUTH);
+ AuthenticatedUser authuser = (AuthenticatedUser) authuserobj;
String requestURL = WebAppUtil.getRequestURLWithParameters(httpServletRequest, true);
log.trace("Request URL: " + requestURL);
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ if (!authManager.isActiveUser(authuser)) {
+ //user is not active anymore. Invalidate session and reauthenticate user
+ String authID = (String) session.getAttribute(Constants.SESSION_PVP2REQUESTID);
+ session.invalidate();
+ authuser = null;
+
+ //TODO: set infotext
+
+ session = httpServletRequest.getSession(true);
+ session.setAttribute(Constants.SESSION_PVP2REQUESTID, authID);
+ }
+
if (authuser == null && !this.isExcluded(requestURL)) {
if (config.isLoginDeaktivated()) {
@@ -151,6 +166,8 @@ public class AuthenticationFilter implements Filter{
if (authuser == null) {
authuser = AuthenticatedUser.generateDefaultUser();
+ authManager.setActiveUser(authuser);
+
//authuser = new AuthenticatedUser(1, "Max", "TestUser", true, false);
httpServletRequest.getSession().setAttribute(Constants.SESSION_AUTH, authuser);
}
@@ -188,23 +205,23 @@ public class AuthenticationFilter implements Filter{
return;
}
-
}
- }
- try {
- filterchain.doFilter(req, resp);
- } catch (Exception e) {
+ } else {
+ try {
+ filterchain.doFilter(req, resp);
+
+ } catch (Exception e) {
-// String redirectURL = "./index.action";
-// HttpServletResponse httpResp = (HttpServletResponse) resp;
-// redirectURL = httpResp.encodeRedirectURL(redirectURL);
-// resp.setContentType("text/html");
-// ((HttpServletResponse) resp).setStatus(302);
-// httpResp.addHeader("Location", redirectURL);
-// log.warn("A Filter Error occurs -> Redirect to Login-Form");
- }
-
+ //String redirectURL = "./index.action";
+ //HttpServletResponse httpResp = (HttpServletResponse) resp;
+ //redirectURL = httpResp.encodeRedirectURL(redirectURL);
+ //resp.setContentType("text/html");
+ //((HttpServletResponse) resp).setStatus(302);
+ //httpResp.addHeader("Location", redirectURL);
+ //log.warn("A Filter Error occurs -> Redirect to Login-Form");
+ }
+ }
}
public void init(FilterConfig filterConfig) throws ServletException {
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/helper/FormDataHelper.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/helper/FormDataHelper.java
index 24ee653f3..cd6c699b9 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/helper/FormDataHelper.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/helper/FormDataHelper.java
@@ -88,7 +88,7 @@ public class FormDataHelper {
userlist.add(new AuthenticatedUser(dbuser,
dbuser.isIsActive(),
ismandate,
- false));
+ false, null, null));
}
return userlist;
}
diff --git a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/IndexAction.java b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/IndexAction.java
index e019b70bb..980bb1e59 100644
--- a/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/IndexAction.java
+++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/struts/action/IndexAction.java
@@ -85,6 +85,8 @@ import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
import at.gv.egovernment.moa.id.commons.validation.ValidationHelper;
import at.gv.egovernment.moa.id.configuration.Constants;
import at.gv.egovernment.moa.id.configuration.auth.AuthenticatedUser;
+import at.gv.egovernment.moa.id.configuration.auth.AuthenticationManager;
+import at.gv.egovernment.moa.id.configuration.auth.pvp2.PVP2Utils;
import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider;
import at.gv.egovernment.moa.id.configuration.data.UserDatabaseFrom;
import at.gv.egovernment.moa.id.configuration.exception.BasicActionException;
@@ -216,8 +218,14 @@ public class IndexAction extends BasicAction {
AuthenticatedUser authuser = new AuthenticatedUser(dbuser,
true,
ismandateuser,
- false);
+ false,
+ dbuser.getHjid()+"dbID",
+ "username/password");
+ //store user as authenticated user
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.setActiveUser(authUser);
+
Date date = DateTimeHelper.parseDateTime(dbuser.getLastLogin());
if (date != null)
authuser.setLastLogin(date);;
@@ -308,31 +316,10 @@ public class IndexAction extends BasicAction {
addActionError(LanguageHelper.getErrorString("error.login", request));
return Constants.STRUTS_ERROR;
}
-
- //Validate Signature
- SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();
- profileValidator.validate(sign);
-
- //Verify Signature
- List<KeyInfoProvider> keyInfoProvider = new ArrayList<KeyInfoProvider>();
- keyInfoProvider.add(new DSAKeyValueProvider());
- keyInfoProvider.add(new RSAKeyValueProvider());
- keyInfoProvider.add(new InlineX509DataProvider());
- KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver(
- keyInfoProvider);
-
- MetadataCredentialResolverFactory credentialResolverFactory = MetadataCredentialResolverFactory.getFactory();
- MetadataCredentialResolver credentialResolver = credentialResolverFactory.getInstance(configuration.getMetaDataProvier());
-
- CriteriaSet criteriaSet = new CriteriaSet();
- criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS));
- criteriaSet.add(new EntityIDCriteria(configuration.getPVP2IDPMetadataEntityName()));
- criteriaSet.add(new UsageCriteria(UsageType.SIGNING));
-
- ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver);
- trustEngine.validate(sign, criteriaSet);
-
+ //validate signature
+ PVP2Utils.validateSignature(samlResponse, configuration);
+
log.info("PVP2 Assertion is valid");
if (samlResponse.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) {
@@ -444,7 +431,14 @@ public class IndexAction extends BasicAction {
}
}
- authUser = AuthenticatedUser.generateUserRequestUser(user);
+ //create AuthUser data element
+ authUser = AuthenticatedUser.generateUserRequestUser(user,
+ nameID.getValue(),
+ nameID.getFormat());
+
+ //store user as authenticated user
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.setActiveUser(authUser);
//set Random value
formID = Random.nextRandom();
@@ -468,7 +462,14 @@ public class IndexAction extends BasicAction {
authUser = new AuthenticatedUser(dbuser,
false,
dbuser.isIsMandateUser(),
- true);
+ true,
+ nameID.getValue(),
+ nameID.getFormat());
+
+ //store user as authenticated user
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.setActiveUser(authUser);
+
session.setAttribute(Constants.SESSION_FORM, user);
session.setAttribute(Constants.SESSION_AUTH, authUser);
@@ -488,7 +489,13 @@ public class IndexAction extends BasicAction {
authUser = new AuthenticatedUser(dbuser, true,
ismandateuser,
- true);
+ true,
+ nameID.getValue(),
+ nameID.getFormat());
+
+ //store user as authenticated user
+ AuthenticationManager authManager = AuthenticationManager.getInstance();
+ authManager.setActiveUser(authUser);
Date date = DateTimeHelper.parseDateTime(dbuser.getLastLogin());
if (date != null)
@@ -507,7 +514,7 @@ public class IndexAction extends BasicAction {
finally {
ConfigurationDBUtils.closeSession();
}
-
+
HttpSession newsession = generateNewJSession(request);
newsession.setAttribute(Constants.SESSION_AUTH, authUser);
return Constants.STRUTS_SUCCESS;
@@ -785,33 +792,19 @@ public class IndexAction extends BasicAction {
}
public String logout() {
-
- try {
- populateBasicInformations();
+ HttpSession session = request.getSession(false);
+
+ if (session != null) {
+ if (MiscUtil.isNotEmpty((String)session.getAttribute(Constants.SESSION_SLOSUCCESS)))
+ addActionMessage((String)session.getAttribute(Constants.SESSION_SLOSUCCESS));
- } catch (BasicActionException e) {
- return Constants.STRUTS_ERROR;
+ if (MiscUtil.isNotEmpty((String)session.getAttribute(Constants.SESSION_SLOERROR)))
+ addActionError((String)session.getAttribute(Constants.SESSION_SLOERROR));
- }
-
- if (session != null)
session.invalidate();
-
- try {
- ConfigurationProvider config = ConfigurationProvider.getInstance();
- String ssologout = config.getSSOLogOutURL();
- if (MiscUtil.isNotEmpty(ssologout) && authUser != null && authUser.isPVP2Login()) {
- ssologouturl = ssologout + config.getPublicUrlPreFix(request) + "/index.action";
- return Constants.STRUTS_SSOLOGOUT;
+ }
- }
-
- } catch (ConfigurationException e) {
- log.warn("Configuration can not be loaded.", e);
-
- }
-
return Constants.STRUTS_SUCCESS;
}
diff --git a/id/ConfigWebTool/src/main/resources/applicationResources_de.properties b/id/ConfigWebTool/src/main/resources/applicationResources_de.properties
index 1f0819edf..f379a7a34 100644
--- a/id/ConfigWebTool/src/main/resources/applicationResources_de.properties
+++ b/id/ConfigWebTool/src/main/resources/applicationResources_de.properties
@@ -35,8 +35,11 @@ error.oa.oauth.clientSecret=Client-Secret darf nicht leer sein
error.oa.oauth.keyname=Key-Name darf nicht leer sein
error.oa.oauth.keystore=Keystore darf nicht leer sein und muss eine richtige URL sein.
+
mail.userrequest.subject=Accountanforderung MOA-ID 2.x Konfigurationstool
+webpages.slo.error=Der Abmeldevorgang bei allen Online-Applikationen war nicht erfolgreich. Bitte schlie \u00dfen Sie aus Sicherheitsgr\u00FCnden ihren Browser.
+webpages.slo.success=Sie wurden erfolgreich bei allen Online-Applikationen abgemeldet.
webpages.error.header=Es ist ein Fehler aufgetreten
webpages.index.header=Willkommen bei der MOA-ID 2.x Konfigurationsapplikation
diff --git a/id/ConfigWebTool/src/main/resources/applicationResources_en.properties b/id/ConfigWebTool/src/main/resources/applicationResources_en.properties
index 7733be5d0..398df94a5 100644
--- a/id/ConfigWebTool/src/main/resources/applicationResources_en.properties
+++ b/id/ConfigWebTool/src/main/resources/applicationResources_en.properties
@@ -38,6 +38,9 @@ error.oa.oauth.keystore=Keystore cannot be blank and has to be provided in the f
mail.userrequest.subject=Requesting accounts - MOA-ID 2.x Config Tool
+webpages.slo.error=LogOut process finished with an error. For security reasons, please close your browser.
+webpages.slo.success=LogOut process finished successful
+
webpages.error.header=The error occured
webpages.index.header=Welcome to MOA-ID 2.x Configuration
webpages.index.desciption.head=In order to use this service you should log in
diff --git a/id/ConfigWebTool/src/main/webapp/WEB-INF/web.xml b/id/ConfigWebTool/src/main/webapp/WEB-INF/web.xml
index 3919d3ff3..a6fe50269 100644
--- a/id/ConfigWebTool/src/main/webapp/WEB-INF/web.xml
+++ b/id/ConfigWebTool/src/main/webapp/WEB-INF/web.xml
@@ -64,15 +64,27 @@
<servlet>
<servlet-name>pvp2login</servlet-name>
<display-name>pvp2login</display-name>
- <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.Authenticate</servlet-class>
+ <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets.Authenticate</servlet-class>
</servlet>
<servlet>
<servlet-name>buildmetadata</servlet-name>
<display-name>buildmetadata</display-name>
- <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.BuildMetadata</servlet-class>
+ <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets.BuildMetadata</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>slofrontchannel</servlet-name>
+ <display-name>Single LogOut FrontChannel Service</display-name>
+ <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets.SLOFrontChannelServlet</servlet-class>
+ </servlet>
+
+ <servlet>
+ <servlet-name>slobackchannel</servlet-name>
+ <display-name>Single LogOut BackChannel Service</display-name>
+ <servlet-class>at.gv.egovernment.moa.id.configuration.auth.pvp2.servlets.SLOBackChannelServlet</servlet-class>
+ </servlet>
+
<servlet-mapping>
<servlet-name>buildmetadata</servlet-name>
<url-pattern>/servlet/metadata</url-pattern>
@@ -83,6 +95,16 @@
<url-pattern>/servlet/pvp2login</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>slofrontchannel</servlet-name>
+ <url-pattern>/servlet/sloFrontChannel</url-pattern>
+ </servlet-mapping>
+
+ <servlet-mapping>
+ <servlet-name>slobackchannel</servlet-name>
+ <url-pattern>/servlet/sloBackChannel</url-pattern>
+ </servlet-mapping>
+
<!-- <filter-mapping>
<filter-name>sitemash</filter-name>
<url-pattern>/*</url-pattern>