diff options
author | Bojan Suzic <bojan.suzic@iaik.tugraz.at> | 2014-06-05 18:28:01 +0200 |
---|---|---|
committer | Bojan Suzic <bojan.suzic@iaik.tugraz.at> | 2014-06-05 18:28:01 +0200 |
commit | c7c87f61be0358786c563817d56a92434f0ece1d (patch) | |
tree | d12dd1349375ecf732ae3f0bf424ae3286964963 | |
parent | 509702fe127404554451857e49a0493e3d24b150 (diff) | |
parent | 6f814ec50badeacbb22ac2556c894b996ddc3959 (diff) | |
download | moa-id-spss-c7c87f61be0358786c563817d56a92434f0ece1d.tar.gz moa-id-spss-c7c87f61be0358786c563817d56a92434f0ece1d.tar.bz2 moa-id-spss-c7c87f61be0358786c563817d56a92434f0ece1d.zip |
Merge branch 'moa-2.1-Snapshot' of gitlab.iaik.tugraz.at:afitzek/moa-idspss into moa-2.1-Snapshot
42 files changed, 2301 insertions, 272 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> diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java index af1dd84be..d6d2b32da 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java @@ -28,4 +28,10 @@ public class Constants { public static final String SERVLET_PVP2ASSERTION = "demoapplication"; public static final String SESSION_PVP2REQUESTID = "pvp2requestid"; + + public static final String SERVLET_PVPSINGLELOGOUT = "singlelogout"; + + public static final String SESSION_NAMEID = "pvp2nameID"; + + public static final String SESSION_NAMEIDFORMAT = "pvp2nameIDFormat"; } diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java index 4c9bc6d76..24ba26a59 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java @@ -56,6 +56,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.saml2.metadata.impl.EncryptionMethodBuilder; import org.opensaml.xml.encryption.EncryptionConstants; import org.opensaml.xml.encryption.OAEPparams; @@ -238,10 +239,15 @@ public class BuildMetadata extends HttpServlet { postassertionConsumerService.setIndex(0); postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); - postassertionConsumerService.setLocation(serviceURL + Constants.SERVLET_PVP2ASSERTION); - + postassertionConsumerService.setLocation(serviceURL + Constants.SERVLET_PVP2ASSERTION); spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); + //set Single Log-Out service + SingleLogoutService sloService = SAML2Utils.createSAMLObject(SingleLogoutService.class); + sloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + sloService.setLocation(serviceURL + Constants.SERVLET_PVPSINGLELOGOUT); + spSSODescriptor.getSingleLogoutServices().add(sloService); + spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor); diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java index dcd478864..cde9451a4 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java @@ -73,6 +73,7 @@ import org.opensaml.xml.signature.Signature; import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants; import at.gv.egovernment.moa.id.demoOA.PVPConstants; import at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean; import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; @@ -223,14 +224,19 @@ public class DemoApplication extends HttpServlet { birthday = attributes.get(x).getAttributeValues().get(0).getDOM().getTextContent(); } } - } + } + request.getSession().setAttribute(Constants.SESSION_NAMEIDFORMAT, + saml2assertion.getSubject().getNameID().getFormat()); + request.getSession().setAttribute(Constants.SESSION_NAMEID, + saml2assertion.getSubject().getNameID().getValue()); + } - + bean.setDateOfBirth(birthday); bean.setFamilyName(familyName); bean.setGivenName(givenName); bean.setLogin(true); - + setAnser(request, response, bean); return; diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java new file mode 100644 index 000000000..c68ea9b1f --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java @@ -0,0 +1,335 @@ +/******************************************************************************* + * 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.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +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.binding.decoding.HTTPPostDecoder; +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; +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.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusResponseType; +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.impl.SingleSignOnServiceBuilder; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.security.MetadataCredentialResolver; +import org.opensaml.security.MetadataCredentialResolverFactory; +import org.opensaml.security.MetadataCriteria; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.ws.transport.http.HttpServletRequestAdapter; +import org.opensaml.ws.transport.http.HttpServletResponseAdapter; +import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.security.CriteriaSet; +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.SignableXMLObject; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.gv.egovernment.moa.util.DOMUtils; +import at.iaik.commons.util.MiscUtil; + + +public class Index extends HttpServlet { + + private static final long serialVersionUID = -2129228304760706063L; + private static final Logger log = LoggerFactory + .getLogger(Index.class); + + + private void process(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + + ApplicationBean bean = new ApplicationBean(); + + + String method = request.getMethod(); + HttpSession session = request.getSession(); + if (session == null) { + log.info("NO HTTP Session"); + bean.setErrorMessage("NO HTTP session"); + setAnser(request, response, bean); + return; + } + + if (method.equals("POST")) { + try { + Configuration config = Configuration.getInstance(); + + //Decode with HttpPost Binding + HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool()); + BasicSAMLMessageContext<Response, ?, ?> messageContext = new BasicSAMLMessageContext<Response, SAMLObject, SAMLObject>(); + messageContext + .setInboundMessageTransport(new HttpServletRequestAdapter( + request)); + decode.decode(messageContext); + + SignableXMLObject samlResponse = (SignableXMLObject) messageContext.getInboundMessage(); + + Signature sign = samlResponse.getSignature(); + if (sign == null) { + log.info("Only http POST Requests can be used"); + bean.setErrorMessage("Only http POST Requests can be used"); + setAnser(request, response, bean); + return; + } + + //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(config.getMetaDataProvier()); + + CriteriaSet criteriaSet = new CriteriaSet(); + criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS)); + criteriaSet.add(new EntityIDCriteria(config.getPVP2IDPMetadataEntityName())); + criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); + + ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver); + trustEngine.validate(sign, criteriaSet); + + log.info("PVP2 statusrequest or statusresponse is valid"); + + + if (samlResponse instanceof LogoutResponse) { + + LogoutResponse sloResp = (LogoutResponse) samlResponse; + + //set assertion + org.w3c.dom.Document doc = SAML2Utils.asDOMDocument(samlResponse); + String assertion = DOMUtils.serializeNode(doc); + bean.setAssertion(assertion); + + if (sloResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { + + bean.setSuccessMessage("Der Single Log-Out Vorgang konnte erfolgreich durchgeführt werden."); + + setAnser(request, response, bean); + return; + + } else { + bean.setErrorMessage("Der Single Log-Out Vorgang war nicht erfolgreich.<br>Bitte schließen Sie aus sicherheitsgründen den Browser!"); + setAnser(request, response, bean); + return; + + } + + } else if (samlResponse instanceof LogoutRequest) { + //invalidate user session + request.getSession().invalidate(); + + //build LogOutResponse + LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class); + SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + sloResp.setID(gen.generateIdentifier()); + 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(StatusCode.SUCCESS_URI); + status.setStatusCode(statusCode ); + + 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(); + 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_POST_BINDING_URI)) { + redirectEndpoint = sss; + } + } + sloResp.setDestination(redirectEndpoint.getLocation()); + + //sign authentication request + 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); + sloResp.setSignature(signer); + + //generate Http-POST Binding message + 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());; + + context.setOutboundSAMLMessageSigningCredential(authcredential); + context.setPeerEntityEndpoint(service); + context.setOutboundSAMLMessage(sloResp); + context.setOutboundMessageTransport(responseAdapter); + context.setRelayState(messageContext.getRelayState()); + + encoder.encode(context); + + } else { + bean.setErrorMessage("Kein gültiger LogOut Request oder LogOut Response"); + setAnser(request, response, bean); + return; + + } + + + } catch (Exception e) { + log.warn("Internal error", e); + bean.setErrorMessage("Internal Error: " + e.getMessage()); + setAnser(request, response, bean); + return; + } + + } else { + bean.setErrorMessage("Die Demoapplikation unterstützt nur SAML2 POST-Binding."); + setAnser(request, response, bean); + return; + + } + } + + private void setAnser(HttpServletRequest request, HttpServletResponse response, ApplicationBean answersBean) throws ServletException, IOException { + // store bean in session + request.setAttribute("answers", answersBean); + + // you now can forward to some view, for example some results.jsp + request.getRequestDispatcher("demoapp.jsp").forward(request, response); + + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + process(request, response); + } + + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + process(request, response); + } +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java new file mode 100644 index 000000000..11cc020ff --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * 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.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +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.binding.encoding.HTTPPostEncoder; +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.NameID; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.ws.transport.http.HttpServletResponseAdapter; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.iaik.commons.util.MiscUtil; + + +/** + * Servlet implementation class Authenticate + */ +public class SingleLogOut extends HttpServlet { + private static final long serialVersionUID = 1L; + + private static final Logger log = LoggerFactory + .getLogger(SingleLogOut.class); + + /** + * @see HttpServlet#HttpServlet() + */ + public SingleLogOut() { + super(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + builder = factory.newDocumentBuilder(); + + } catch (ParserConfigurationException e) { + log.warn("PVP2 AuthenticationServlet can not be initialized.", e); + } + } + + DocumentBuilder builder; + + + //generate AuthenticationRequest + protected void process(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + try { + + Configuration config = Configuration.getInstance(); + config.initializePVP2Login(); + + String nameIDFormat = (String) request.getSession().getAttribute(Constants.SESSION_NAMEIDFORMAT); + String nameID = (String) request.getSession().getAttribute(Constants.SESSION_NAMEID); + + if (MiscUtil.isEmpty(nameID) || MiscUtil.isEmpty(nameIDFormat)) { + log.warn("No user information found. Single Log-Out not possible"); + throw new ServletException("No user information found. Single Log-Out not possible"); + + } else + log.info("Fount user information for user nameID: " + nameID + + " , nameIDFormat: " + nameIDFormat + + ". Build Single Log-Out request ..."); + + //invalidate local session + request.getSession().invalidate(); + + //build Single LogOut request + LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class); + SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); + sloReq.setID(gen.generateIdentifier()); + 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); + + 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(); + 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_POST_BINDING_URI)) { + redirectEndpoint = sss; + } + } + sloReq.setDestination(redirectEndpoint.getLocation()); + + //sign authentication request + 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); + sloReq.setSignature(signer); + + //generate Http-POST Binding message + 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());; + + context.setOutboundSAMLMessageSigningCredential(authcredential); + context.setPeerEntityEndpoint(service); + context.setOutboundSAMLMessage(sloReq); + 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); + } + } + + /** + * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + process(request, response); + } + + /** + * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse + * response) + */ + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + process(request, response); + } + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java index 832993604..05c253b6e 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java @@ -36,6 +36,7 @@ public class ApplicationBean implements Serializable { private boolean isLogin = false; private String errorMessage; + private String successMessage; /** * @return the familyName @@ -109,6 +110,18 @@ public class ApplicationBean implements Serializable { public void setLogin(boolean isLogin) { this.isLogin = isLogin; } + /** + * @return the successMessage + */ + public String getSuccessMessage() { + return successMessage; + } + /** + * @param successMessage the successMessage to set + */ + public void setSuccessMessage(String successMessage) { + this.successMessage = successMessage; + } diff --git a/id/oa/src/main/webapp/WEB-INF/web.xml b/id/oa/src/main/webapp/WEB-INF/web.xml index 85a1bbaeb..d40f156cd 100644 --- a/id/oa/src/main/webapp/WEB-INF/web.xml +++ b/id/oa/src/main/webapp/WEB-INF/web.xml @@ -8,7 +8,7 @@ <servlet> <servlet-name>pvp2login</servlet-name> - <display-name>pvp2login</display-name> + <display-name>PVP 2.1 Authentication request builder</display-name> <servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.Authenticate</servlet-class> </servlet> @@ -17,6 +17,17 @@ <url-pattern>/servlet/pvp2login</url-pattern> </servlet-mapping> + <servlet> + <servlet-name>pvp2slo</servlet-name> + <display-name>PVP 2.1 Single Log-Out request builder</display-name> + <servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.SingleLogOut</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>pvp2slo</servlet-name> + <url-pattern>/servlet/startpvp2slo</url-pattern> + </servlet-mapping> + <servlet> <servlet-name>pvp2metadata</servlet-name> <display-name>Metadata</display-name> @@ -39,5 +50,16 @@ <url-pattern>/demoapplication</url-pattern> </servlet-mapping> + <servlet> + <servlet-name>index</servlet-name> + <display-name>Mainpage</display-name> + <servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.Index</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>index</servlet-name> + <url-pattern>/singlelogout</url-pattern> + </servlet-mapping> + </web-app> diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java index 632227d79..c0e1dd3ca 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java @@ -27,6 +27,8 @@ import iaik.x509.X509Certificate; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import javax.naming.ldap.LdapName; @@ -445,6 +447,9 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants { authData.setSsoSession(true); + if (assertion.getConditions() != null && assertion.getConditions().getNotOnOrAfter() != null) + authData.setSsoSessionValidTo(assertion.getConditions().getNotOnOrAfter().toDate()); + //only for SAML1 if (PVPConstants.STORK_QAA_1_4.equals(authData.getQAALevel())) authData.setQualifiedCertificate(true); @@ -454,7 +459,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants { } private static void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session, - IOAAuthParameters oaParam) throws BuildException { + IOAAuthParameters oaParam) throws BuildException, ConfigurationException { String target = oaParam.getTarget(); @@ -465,7 +470,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants { boolean businessService = oaParam.getBusinessService(); authData.setIssuer(session.getAuthURL()); - + //baseID or wbpk in case of BusinessService without SSO or BusinessService SSO authData.setIdentificationValue(identityLink.getIdentificationValue()); authData.setIdentificationType(identityLink.getIdentificationType()); @@ -529,6 +534,19 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants { authData.setSsoSession(AuthenticationSessionStoreage.isSSOSession(session.getSessionID())); + //set max. SSO session time + if (authData.isSsoSession()) { + long maxSSOSessionTime = AuthConfigurationProvider.getInstance().getTimeOuts().getMOASessionCreated().longValue() * 1000; + Date ssoSessionValidTo = new Date(session.getSessionCreated().getTime() + maxSSOSessionTime); + authData.setSsoSessionValidTo(ssoSessionValidTo); + + } else { + //set valid to 5 min + Date ssoSessionValidTo = new Date(new Date().getTime() + 5 * 60 * 1000); + authData.setSsoSessionValidTo(ssoSessionValidTo); + + } + /* TODO: Support SSO Mandate MODE! * Insert functionality to translate mandates in case of SSO diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index c5ba49b2e..8726c1618 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -42,6 +42,7 @@ import java.io.Serializable; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.util.ArrayList; +import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Vector; @@ -78,6 +79,9 @@ public class AuthenticationSession implements Serializable { * session ID */ private String sessionID; + + private Date sessionCreated = null; + /** * "Geschäftsbereich" the online application belongs to; maybe <code>null</code> if the * online application is a business application @@ -344,8 +348,9 @@ public class AuthenticationSession implements Serializable { * @param id * Session ID */ - public AuthenticationSession(String id) { + public AuthenticationSession(String id, Date created) { sessionID = id; + sessionCreated = created; // setTimestampStart(); // infoboxValidators = new ArrayList(); } @@ -1050,6 +1055,13 @@ public class AuthenticationSession implements Serializable { this.storkAuthnResponse = storkAuthnResponse; } + /** + * @return the sessionCreated + */ + public Date getSessionCreated() { + return sessionCreated; + } + diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java index 33e62d3d0..5685977bc 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java @@ -135,6 +135,7 @@ public class AuthenticationData implements IAuthData, Serializable { private String QAALevel = null; private boolean ssoSession = false; + private Date ssoSessionValidTo = null; private boolean interfederatedSSOSession = false; private String interfederatedIDP = null; @@ -656,7 +657,23 @@ public class AuthenticationData implements IAuthData, Serializable { public void setInterfederatedIDP(String interfederatedIDP) { this.interfederatedIDP = interfederatedIDP; } + + /** + * @return the ssoSessionValidTo + */ + public Date getSsoSessionValidTo() { + return ssoSessionValidTo; + } + + /** + * @param ssoSessionValidTo the ssoSessionValidTo to set + */ + public void setSsoSessionValidTo(Date ssoSessionValidTo) { + this.ssoSessionValidTo = ssoSessionValidTo; + } + + } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java index 4ea81f134..7e421da0f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java @@ -53,6 +53,8 @@ public interface IAuthData { String getBPK(); String getBPKType(); + Date getSsoSessionValidTo(); + String getInterfederatedIDP(); String getIdentificationValue(); 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 a0f3dd309..df195c0de 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 @@ -29,8 +29,10 @@ import java.util.LinkedHashMap; import java.util.List; import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.metadata.SingleLogoutService; +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.protocols.pvp2x.PVP2XProtocol; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; @@ -52,47 +54,87 @@ public class SLOInformationContainer implements Serializable { public void parseActiveOAs(List<OASessionStore> dbOAs, String removeOAID) { - activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); - activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>(); + if (activeBackChannelOAs == null) + activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>(); + if (activeFrontChannalOAs == null) + activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); if (dbOAs != null) { for (OASessionStore oa : dbOAs) { - //Actually only PVP 2.1 support Single LogOut - if (PVP2XProtocol.NAME.equals(oa.getProtocolType()) && - !oa.getOaurlprefix().equals(removeOAID)) { + if (!oa.getOaurlprefix().equals(removeOAID)) { + + //Actually only PVP 2.1 support Single LogOut + if (PVP2XProtocol.PATH.equals(oa.getProtocolType())) { + SingleLogoutService sloDesc; + try { + sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(oa.getOaurlprefix()); + + if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) + activeBackChannelOAs.put(oa.getOaurlprefix(), + new SLOInformationImpl( + oa.getAssertionSessionID(), + oa.getUserNameID(), + oa.getUserNameIDFormat(), + oa.getProtocolType(), + sloDesc)); + + else + activeFrontChannalOAs.put(oa.getOaurlprefix(), + new SLOInformationImpl( + oa.getAssertionSessionID(), + oa.getUserNameID(), + oa.getUserNameIDFormat(), + oa.getProtocolType(), + sloDesc)); + + } catch (NOSLOServiceDescriptorException e) { + putFailedOA(oa.getOaurlprefix()); + + } + + } else + putFailedOA(oa.getOaurlprefix()); + } + } + } + } + + /** + * @param dbIDPs + * @param value + */ + public void parseActiveIDPs(List<InterfederationSessionStore> dbIDPs, + String removeIDP) { + if (activeBackChannelOAs == null) + activeBackChannelOAs = new LinkedHashMap<String, SLOInformationImpl>(); + if (activeFrontChannalOAs == null) + activeFrontChannalOAs = new LinkedHashMap<String, SLOInformationImpl>(); + + if (dbIDPs != null) { + for (InterfederationSessionStore el : dbIDPs) { + if (!el.getIdpurlprefix().equals(removeIDP)) { + SingleLogoutService sloDesc; try { - sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(oa.getOaurlprefix()); - - if (sloDesc.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) - activeBackChannelOAs.put(oa.getOaurlprefix(), - new SLOInformationImpl( - oa.getAssertionSessionID(), - oa.getUserNameID(), - oa.getUserNameIDFormat(), - oa.getProtocolType(), - sloDesc)); + sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(el.getIdpurlprefix()); - else - activeFrontChannalOAs.put(oa.getOaurlprefix(), - new SLOInformationImpl( - oa.getAssertionSessionID(), - oa.getUserNameID(), - oa.getUserNameIDFormat(), - oa.getProtocolType(), + activeFrontChannalOAs.put(el.getIdpurlprefix(), + new SLOInformationImpl( + el.getSessionIndex(), + el.getUserNameID(), + NameID.TRANSIENT, + PVP2XProtocol.PATH, sloDesc)); } catch (NOSLOServiceDescriptorException e) { - putFailedOA(oa.getOaurlprefix()); + putFailedOA(el.getIdpurlprefix()); } - - } else - putFailedOA(oa.getOaurlprefix()); + } } } } - + public String getNextFrontChannelOA() { Iterator<String> interator = activeFrontChannalOAs.keySet().iterator(); if (interator.hasNext()) @@ -147,9 +189,5 @@ public class SLOInformationContainer implements Serializable { if (sloFailedOAs == null) sloFailedOAs = new ArrayList<String>(); sloFailedOAs.add(oaID); - } - - - - + } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java index 01f7e18ba..c60e69df6 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java @@ -258,21 +258,21 @@ public class MetadataAction implements IAction { //add SLO descriptor -// SingleLogoutService postSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// postSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// postSLOService -// .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); -// spSSODescriptor.getSingleLogoutServices().add(postSLOService); -// -// SingleLogoutService redirectSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// redirectSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// redirectSLOService -// .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); -// spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); + SingleLogoutService postSLOService = + SAML2Utils.createSAMLObject(SingleLogoutService.class); + postSLOService.setLocation(PVPConfiguration + .getInstance().getIDPSSOPostService()); + postSLOService + .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + spSSODescriptor.getSingleLogoutServices().add(postSLOService); + + SingleLogoutService redirectSLOService = + SAML2Utils.createSAMLObject(SingleLogoutService.class); + redirectSLOService.setLocation(PVPConfiguration + .getInstance().getIDPSSOPostService()); + redirectSLOService + .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + spSSODescriptor.getSingleLogoutServices().add(redirectSLOService); spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); @@ -333,13 +333,13 @@ public class MetadataAction implements IAction { postSingleSignOnService); //add SLO descriptor -// SingleLogoutService postSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// postSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// postSLOService -// .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); -// idpSSODescriptor.getSingleLogoutServices().add(postSLOService); + SingleLogoutService postSLOService = + SAML2Utils.createSAMLObject(SingleLogoutService.class); + postSLOService.setLocation(PVPConfiguration + .getInstance().getIDPSSOPostService()); + postSLOService + .setBinding(SAMLConstants.SAML2_POST_BINDING_URI); + idpSSODescriptor.getSingleLogoutServices().add(postSLOService); } @@ -355,13 +355,13 @@ public class MetadataAction implements IAction { redirectSingleSignOnService); //add SLO descriptor -// SingleLogoutService redirectSLOService = -// SAML2Utils.createSAMLObject(SingleLogoutService.class); -// redirectSLOService.setLocation(PVPConfiguration -// .getInstance().getIDPSSOPostService()); -// redirectSLOService -// .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); -// idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); + SingleLogoutService redirectSLOService = + SAML2Utils.createSAMLObject(SingleLogoutService.class); + redirectSLOService.setLocation(PVPConfiguration + .getInstance().getIDPSSORedirectService()); + redirectSLOService + .setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); + idpSSODescriptor.getSingleLogoutServices().add(redirectSLOService); } /*if (PVPConfiguration.getInstance().getIDPResolveSOAPService() != null) { 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 c67d10ab7..92441e663 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 @@ -42,6 +42,7 @@ import org.opensaml.xml.security.SecurityException; 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.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.auth.AuthConfigurationProvider; @@ -124,9 +125,11 @@ public class SingleLogOutAction implements IAction { } //store active OAs to SLOContaine - List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session); + 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 @@ -247,10 +250,13 @@ public class SingleLogOutAction implements IAction { private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) { Status status = logOutResp.getStatus(); - if (!status.getStatusCode().equals(StatusCode.SUCCESS_URI)) { + 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: " + status.getStatusMessage().getMessage() + ")"); + + message + ")"); sloContainer.putFailedOA(logOutResp.getIssuer().getValue()); } else 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 04d374e93..7aa860c5c 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 @@ -35,6 +35,7 @@ import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.core.StatusMessage; 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.provider.MetadataProviderException; @@ -125,7 +126,7 @@ public class SingleLogOutBuilder { public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException { try { EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID); - SPSSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + SSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); SingleLogoutService sloService = null; for (SingleLogoutService el : spsso.getSingleLogoutServices()) { @@ -173,14 +174,18 @@ public class SingleLogOutBuilder { if (el.getBinding().equals(spRequest.getBinding())) sloService = el; } - if (sloService == null && spsso.getSingleLogoutServices().size() != 0) - sloService = spsso.getSingleLogoutServices().get(0); - else { - Logger.error("Found no SLO ServiceDescriptor in Metadata"); - throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); + if (sloService == null) { + if (spsso.getSingleLogoutServices().size() != 0) + sloService = spsso.getSingleLogoutServices().get(0); + + else { + Logger.error("Found no SLO ServiceDescriptor in Metadata"); + throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); + } } - return sloService; + + return sloService; } } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java index 4d6343fce..fa5d252bd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java @@ -135,7 +135,8 @@ public class PVP2AssertionBuilder implements PVPConstants { SubjectConfirmationData subjectConfirmationData = null; return buildGenericAssertion(attrQuery.getIssuer().getValue(), date, - authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex); + authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, + new DateTime(authData.getSsoSessionValidTo().getTime())); } public static Assertion buildAssertion(AuthnRequest authnRequest, @@ -393,8 +394,8 @@ public class PVP2AssertionBuilder implements PVPConstants { SubjectConfirmationData subjectConfirmationData = SAML2Utils .createSAMLObject(SubjectConfirmationData.class); subjectConfirmationData.setInResponseTo(authnRequest.getID()); - subjectConfirmationData.setNotOnOrAfter(date.plusMinutes(5)); - + subjectConfirmationData.setNotOnOrAfter(new DateTime(authData.getSsoSessionValidTo().getTime())); + subjectConfirmationData.setRecipient(assertionConsumerService.getLocation()); //set SLO information @@ -402,13 +403,13 @@ public class PVP2AssertionBuilder implements PVPConstants { sloInformation.setNameIDFormat(subjectNameID.getFormat()); sloInformation.setSessionIndex(sessionIndex); - return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex); + return buildGenericAssertion(peerEntity.getEntityID(), date, authnContextClassRef, attrList, subjectNameID, subjectConfirmationData, sessionIndex, subjectConfirmationData.getNotOnOrAfter()); } private static Assertion buildGenericAssertion(String entityID, DateTime date, AuthnContextClassRef authnContextClassRef, List<Attribute> attrList, NameID subjectNameID, SubjectConfirmationData subjectConfirmationData, - String sessionIndex) throws ConfigurationException { + String sessionIndex, DateTime isValidTo) throws ConfigurationException { Assertion assertion = SAML2Utils.createSAMLObject(Assertion.class); AuthnContext authnContext = SAML2Utils @@ -448,10 +449,9 @@ public class PVP2AssertionBuilder implements PVPConstants { audience.setAudienceURI(entityID); audienceRestriction.getAudiences().add(audience); - conditions.setNotBefore(date); - - conditions.setNotOnOrAfter(date.plusMinutes(5)); - + conditions.setNotBefore(date); + conditions.setNotOnOrAfter(isValidTo); + conditions.getAudienceRestrictions().add(audienceRestriction); assertion.setConditions(conditions); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java index 6c2900752..1c74aea55 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java @@ -64,7 +64,7 @@ public class AuthenticationSessionStoreage { AuthenticatedSessionStore session; try { - session = searchInDatabase(moaSessionID); + session = searchInDatabase(moaSessionID, true); return session.isAuthenticated(); } catch (MOADatabaseException e) { @@ -72,19 +72,20 @@ public class AuthenticationSessionStoreage { } } - public static AuthenticationSession createSession() throws MOADatabaseException { + public static AuthenticationSession createSession() throws MOADatabaseException, BuildException { String id = Random.nextRandom(); - AuthenticationSession session = new AuthenticationSession(id); - + AuthenticatedSessionStore dbsession = new AuthenticatedSessionStore(); dbsession.setSessionid(id); dbsession.setAuthenticated(false); - //set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 - dbsession.setCreated(new Date()); - dbsession.setUpdated(new Date()); + //set Timestamp in this state, because automated timestamp generation is buggy in Hibernate 4.2.1 + Date now = new Date(); + dbsession.setCreated(now); + dbsession.setUpdated(now); - dbsession.setSession(SerializationUtils.serialize(session)); + AuthenticationSession session = new AuthenticationSession(id, now); + encryptSession(session, dbsession); //store AssertionStore element to Database try { @@ -102,7 +103,7 @@ public class AuthenticationSessionStoreage { public static AuthenticationSession getSession(String sessionID) throws MOADatabaseException { try { - AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); + AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); return decryptSession(dbsession); } catch (MOADatabaseException e) { @@ -122,7 +123,7 @@ public class AuthenticationSessionStoreage { public static void storeSession(AuthenticationSession session, String pendingRequestID) throws MOADatabaseException, BuildException { try { - AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID()); + AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true); if (MiscUtil.isNotEmpty(pendingRequestID)) dbsession.setPendingRequestID(pendingRequestID); @@ -175,7 +176,7 @@ public class AuthenticationSessionStoreage { throws AuthenticationException, BuildException { try { - AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID()); + AuthenticatedSessionStore dbsession = searchInDatabase(session.getSessionID(), true); String id = Random.nextRandom(); @@ -207,7 +208,7 @@ public class AuthenticationSessionStoreage { AuthenticatedSessionStore session; try { - session = searchInDatabase(moaSessionID); + session = searchInDatabase(moaSessionID, true); session.setAuthenticated(value); MOASessionDBUtils.saveOrUpdate(session); @@ -249,7 +250,7 @@ public class AuthenticationSessionStoreage { public static boolean isSSOSession(String sessionID) throws MOADatabaseException { try { - AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); + AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); return dbsession.isSSOSession(); } catch (MOADatabaseException e) { @@ -391,8 +392,36 @@ public class AuthenticationSessionStoreage { MiscUtil.assertNotNull(moaSession, "MOASession"); try { - AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID()); - return dbsession.getActiveOAsessions(); + List<OASessionStore> oas = new ArrayList<OASessionStore>(); + + AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID(), false); + oas.addAll(dbsession.getActiveOAsessions()); + + Session session = MOASessionDBUtils.getCurrentSession(); + session.getTransaction().commit(); + + return oas; + + } catch (MOADatabaseException e) { + Logger.warn("NO session information found for sessionID " + moaSession.getSessionID(), e); + + } + + return null; + } + + public static List<InterfederationSessionStore> getAllActiveIDPsFromMOASession(AuthenticationSession moaSession) { + MiscUtil.assertNotNull(moaSession, "MOASession"); + + try { + List<InterfederationSessionStore> idps = new ArrayList<InterfederationSessionStore>(); + AuthenticatedSessionStore dbsession = searchInDatabase(moaSession.getSessionID(), false); + idps.addAll(dbsession.getInderfederation()); + + Session session = MOASessionDBUtils.getCurrentSession(); + session.getTransaction().commit(); + + return idps; } catch (MOADatabaseException e) { Logger.warn("NO session information found for sessionID " + moaSession.getSessionID(), e); @@ -475,7 +504,7 @@ public class AuthenticationSessionStoreage { public static String getPendingRequestID(String sessionID) { try { - AuthenticatedSessionStore dbsession = searchInDatabase(sessionID); + AuthenticatedSessionStore dbsession = searchInDatabase(sessionID, true); return dbsession.getPendingRequestID(); } catch (MOADatabaseException e) { @@ -646,7 +675,7 @@ public class AuthenticationSessionStoreage { return result.get(0).getInderfederation().get(0); } - public static String createInterfederatedSession(IRequest req, boolean isAuthenticated, String ssoID) throws MOADatabaseException, AssertionAttributeExtractorExeption { + public static String createInterfederatedSession(IRequest req, boolean isAuthenticated, String ssoID) throws MOADatabaseException, AssertionAttributeExtractorExeption, BuildException { AuthenticatedSessionStore dbsession = null; //search for active SSO session @@ -654,7 +683,7 @@ public class AuthenticationSessionStoreage { String moaSession = getMOASessionSSOID(ssoID); if (MiscUtil.isNotEmpty(moaSession)) { try { - dbsession = searchInDatabase(moaSession); + dbsession = searchInDatabase(moaSession, true); }catch (MOADatabaseException e) { @@ -664,28 +693,28 @@ public class AuthenticationSessionStoreage { String id = null; Date now = new Date(); - //create new MOASession if any exists + AuthenticationSession session = null; if (dbsession == null) { id = Random.nextRandom(); dbsession = new AuthenticatedSessionStore(); dbsession.setSessionid(id); dbsession.setCreated(now); - + session = new AuthenticationSession(id, now); + } else { id = dbsession.getSessionid(); - + session = decryptSession(dbsession); + } - + dbsession.setInterfederatedSSOSession(true); dbsession.setAuthenticated(isAuthenticated); - dbsession.setUpdated(now); - - AuthenticationSession session = new AuthenticationSession(id); + dbsession.setUpdated(now); session.setAuthenticated(true); - session.setAuthenticatedUsed(false); - dbsession.setSession(SerializationUtils.serialize(session)); - + session.setAuthenticatedUsed(false); + encryptSession(session, dbsession); + //add interfederation information List<InterfederationSessionStore> idpList = dbsession.getInderfederation(); InterfederationSessionStore idp = null; @@ -889,7 +918,7 @@ public class AuthenticationSessionStoreage { } @SuppressWarnings("rawtypes") - private static AuthenticatedSessionStore searchInDatabase(String sessionID) throws MOADatabaseException { + private static AuthenticatedSessionStore searchInDatabase(String sessionID, boolean commit) throws MOADatabaseException { MiscUtil.assertNotNull(sessionID, "moasessionID"); Logger.trace("Get authenticated session with sessionID " + sessionID + " from database."); Session session = MOASessionDBUtils.getCurrentSession(); @@ -903,7 +932,8 @@ public class AuthenticationSessionStoreage { result = query.list(); //send transaction - session.getTransaction().commit(); + if (commit) + session.getTransaction().commit(); } Logger.trace("Found entries: " + result.size()); diff --git a/spss/server/serverws/.settings/.jsdtscope b/spss/server/serverws/.settings/.jsdtscope deleted file mode 100644 index f40dd98e2..000000000 --- a/spss/server/serverws/.settings/.jsdtscope +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
- <attributes>
- <attribute name="hide" value="true"/>
- </attributes>
- </classpathentry>
- <classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
- <classpathentry kind="output" path=""/>
-</classpath>
diff --git a/spss/server/serverws/.settings/org.eclipse.wst.common.component b/spss/server/serverws/.settings/org.eclipse.wst.common.component deleted file mode 100644 index ffe4d38a0..000000000 --- a/spss/server/serverws/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
- <wb-module deploy-name="moa-spss-ws">
- <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
- <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
- <dependent-module archiveName="moa-spss-lib-2.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/moa-spss-lib/moa-spss-lib">
- <dependency-type>uses</dependency-type>
- </dependent-module>
- <dependent-module archiveName="moa-common-2.0.0.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/moa-common/moa-common">
- <dependency-type>uses</dependency-type>
- </dependent-module>
- <property name="java-output-path" value="/target/classes"/>
- <property name="context-root" value="moa-spss"/>
- </wb-module>
-</project-modules>
diff --git a/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.container b/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a48..000000000 --- a/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file diff --git a/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.name b/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6e..000000000 --- a/spss/server/serverws/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window
\ No newline at end of file diff --git a/spss/server/serverws/.settings/org.maven.ide.eclipse.prefs b/spss/server/serverws/.settings/org.maven.ide.eclipse.prefs deleted file mode 100644 index 9203b873b..000000000 --- a/spss/server/serverws/.settings/org.maven.ide.eclipse.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Tue Jul 07 16:06:51 CEST 2009
-activeProfiles=
-eclipse.preferences.version=1
-fullBuildGoals=process-test-resources
-includeModules=false
-resolveWorkspaceProjects=true
-resourceFilterGoals=process-resources resources\:testResources
-skipCompilerPlugin=true
-version=1
|