diff options
| author | Alexander Marsalek <amarsalek@iaik.tugraz.at> | 2014-06-10 11:08:32 +0200 | 
|---|---|---|
| committer | Alexander Marsalek <amarsalek@iaik.tugraz.at> | 2014-06-10 11:08:32 +0200 | 
| commit | c553525294ffe87bc05a5b1b100f86ddf0aa2d84 (patch) | |
| tree | 714bfe6587fafc3e27122371d1324aa9497c9b36 | |
| parent | c1ee833c415bcce3d7173f0beec0c1ffcd6c6529 (diff) | |
| parent | 8dcf7e74a19986c234888b8b93eda5cbddf8ac76 (diff) | |
| download | moa-id-spss-c553525294ffe87bc05a5b1b100f86ddf0aa2d84.tar.gz moa-id-spss-c553525294ffe87bc05a5b1b100f86ddf0aa2d84.tar.bz2 moa-id-spss-c553525294ffe87bc05a5b1b100f86ddf0aa2d84.zip | |
Merge branch 'moa-2.1-Snapshot' into dokumentservice
74 files changed, 4798 insertions, 596 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..3d66a4b19 --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/PVP2Utils.java @@ -0,0 +1,238 @@ +/* + * 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.trust.TrustedCredentialTrustEngine; +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 ExplicitKeySignatureTrustEngine getTrustEngine(ConfigurationProvider configuration) { +		//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());   +			  			  				 +				return new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver); +		 +	} +	 +	public static void validateSignature(SignableXMLObject msg, ConfigurationProvider configuration) throws SecurityException, ValidationException { +		//Validate Signature +		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); +		profileValidator.validate(msg.getSignature()); +			 +		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 = getTrustEngine(configuration); +		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..f121babc6 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..38c858918 --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOBasicServlet.java @@ -0,0 +1,270 @@ +/* + * 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()); +			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..67921c689 --- /dev/null +++ b/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java @@ -0,0 +1,291 @@ +/* + * 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);			 +				 +				request.getSession().setAttribute(Constants.SESSION_PVP2REQUESTID, sloReq.getID()); +				 +				//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( +						PVP2Utils.getTrustEngine(getConfig())); +				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); + +				decode.decode(messageContext); +				 +				signatureRule.evaluate(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..65a4ab2a7 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_REDIRECT_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..666ecaeee --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java @@ -0,0 +1,336 @@ +/******************************************************************************* + * 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.decoding.HTTPRedirectDeflateDecoder; +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; +import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; +import org.opensaml.saml2.binding.security.SAML2AuthnRequestsSignedRule; +import org.opensaml.saml2.binding.security.SAML2HTTPRedirectDeflateSignatureRule; +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.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.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("GET")) {					 +			try { +				Configuration config = Configuration.getInstance(); +				 +				//Decode with HttpPost Binding +				HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder( +						new BasicParserPool()); +				BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); +				messageContext +						.setInboundMessageTransport(new HttpServletRequestAdapter(request)); + +				decode.decode(messageContext); +				 +				messageContext.setMetadataProvider(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)); +				  				 +				MetadataCredentialResolverFactory credentialResolverFactory = MetadataCredentialResolverFactory.getFactory();     +				MetadataCredentialResolver credentialResolver = credentialResolverFactory.getInstance(config.getMetaDataProvier()); +				 +				//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); +				 +				 +				ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver); +				 +				 +				SAML2HTTPRedirectDeflateSignatureRule signatureRule = new SAML2HTTPRedirectDeflateSignatureRule( +						trustEngine); +				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);	 +											 +				SignableXMLObject samlResponse = (SignableXMLObject) messageContext.getInboundMessage(); +			 + +							 +				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_REDIRECT_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); + +					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("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/auth/pom.xml b/id/server/auth/pom.xml index f18f0e1b0..20c45b096 100644 --- a/id/server/auth/pom.xml +++ b/id/server/auth/pom.xml @@ -88,7 +88,9 @@  	</build>  	<dependencies> -		<!-- we need Axis 1.1 here, 1.0 is included in SPSS --> + + +        <!-- we need Axis 1.1 here, 1.0 is included in SPSS -->  		<dependency>  			<groupId>axis</groupId>  			<artifactId>axis</artifactId> diff --git a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml index 6da7396a1..23737452a 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/urlrewrite.xml @@ -41,20 +41,29 @@  	</rule>  	<rule match-type="regex">  		<from>^/pvp2/redirect$</from> -		<to type="forward">/dispatcher?mod=id_pvp2x&action=Redirect&%{query-string}</to> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=Redirect&endpointtype=idp&%{query-string}</to>  	</rule>  	<rule match-type="regex">  		<from>^/pvp2/post$</from> -		<to type="forward">/dispatcher?mod=id_pvp2x&action=Post&%{query-string}</to> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=Post&endpointtype=idp&%{query-string}</to>  	</rule>  	<rule match-type="regex">  		<from>^/pvp2/Soap$</from> -		<to type="forward">/dispatcher?mod=id_pvp2x&action=Soap</to> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=Soap&endpointtype=idp</to>  	</rule>  	<rule match-type="regex">  		<from>^/pvp2/attributequery$</from> -		<to type="forward">/dispatcher?mod=id_pvp2x&action=AttributeQuery</to> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=AttributeQuery&endpointtype=idp</to>  	</rule> +	<rule match-type="regex"> +		<from>^/pvp2/sp/redirect$</from> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=Redirect&endpointtype=sp&%{query-string}</to> +	</rule> +	<rule match-type="regex"> +		<from>^/pvp2/sp/post$</from> +		<to type="forward">/dispatcher?mod=id_pvp2x&action=Post&endpointtype=sp&%{query-string}</to> +	</rule> +      <rule match-type="regex">          <from>^/stork2/StartAuthentication$</from> diff --git a/id/server/auth/src/main/webapp/WEB-INF/web.xml b/id/server/auth/src/main/webapp/WEB-INF/web.xml index 0ef8a568c..d60d73fd2 100644 --- a/id/server/auth/src/main/webapp/WEB-INF/web.xml +++ b/id/server/auth/src/main/webapp/WEB-INF/web.xml @@ -35,8 +35,15 @@  		<display-name>LogOut</display-name>  		<description>SSO LogOut</description>  		<servlet-class>at.gv.egovernment.moa.id.auth.servlet.LogOutServlet</servlet-class> -		<load-on-startup>1</load-on-startup>  	</servlet> +	 +	<servlet> +		<servlet-name>IDPSLO</servlet-name> +		<display-name>IDP-SLO</display-name> +		<description>IDP Single LogOut Service</description> +		<servlet-class>at.gv.egovernment.moa.id.auth.servlet.IDPSingleLogOutServlet</servlet-class> +	</servlet> +	  	<servlet>  		<servlet-name>VerifyIdentityLink</servlet-name>  		<display-name>VerifyIdentityLink</display-name> @@ -171,6 +178,10 @@  		<url-pattern>/LogOut</url-pattern>  	</servlet-mapping>  	<servlet-mapping> +		<servlet-name>IDPSLO</servlet-name> +		<url-pattern>/idpSingleLogout</url-pattern> +	</servlet-mapping>	 +	<servlet-mapping>  		<servlet-name>VerifyIdentityLink</servlet-name>  		<url-pattern>/VerifyIdentityLink</url-pattern>  	</servlet-mapping> diff --git a/id/server/data/deploy/conf/moa-id/htmlTemplates/slo_template.html b/id/server/data/deploy/conf/moa-id/htmlTemplates/slo_template.html new file mode 100644 index 000000000..a652855c4 --- /dev/null +++ b/id/server/data/deploy/conf/moa-id/htmlTemplates/slo_template.html @@ -0,0 +1,438 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +  <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> +   +   <!-- MOA-ID 2.x BKUSelection Layout CSS -->                +    <style type="text/css"> +			@media screen and (min-width: 650px) { +			 +				body { +					margin:0; +					padding:0; +					color : #000; +					background-color : #fff; +			  	text-align: center; +			  	background-color: #6B7B8B; +				} +   +			  #page { +			    display: block; +			    border: 2px solid rgb(0,0,0); +			    width: 650px; +			    height: 460px; +			    margin: 0 auto; +			    margin-top: 5%; +			    position: relative; +			    border-radius: 25px; +			    background: rgb(255,255,255); +			  } +			   +			  #page1 { +			    text-align: center; +			  } +			   +			  #main { +			    /*	clear:both; */ +				  position:relative; +			    margin: 0 auto; +			    width: 250px; +			    text-align: center; +			  } +			   +			  .OA_header { +			/*	  background-color: white;*/ +			    font-size: 20pt; +			    margin-bottom: 25px; +			    margin-top: 25px; +			  } +			 +			  #leftcontent { +			    /*float:left; */ +				  width:250px; +				  margin-bottom: 25px; +			    text-align: left; +			    /*border: 1px solid rgb(0,0,0);*/ +			  } +			 +			  #leftcontent { +				 width: 300px; +				 margin-top: 30px; +			  } +       +        h2#tabheader{ +				  font-size: 1.1em;  +          padding-left: 2%; +          padding-right: 2%; +          position: relative; +			  } +        		   +			  .setAssertionButton_full { +			  	background: #efefef; +				  cursor: pointer; +				  margin-top: 15px; +			    width: 100px; +			    height: 30px +			  } +			 +			  #leftbutton  { +				 width: 30%;  +				 float:left;  +				 margin-left: 40px; +			  } +			 +			  #rightbutton { +				 width: 30%;  +				 float:right;  +				 margin-right: 45px;  +				 text-align: right; +			  } +         +        button { +          height: 25px; +          width: 75px; +          margin-bottom: 10px; +        } +         +       #validation { +        position: absolute; +        bottom: 0px; +        margin-left: 270px; +        padding-bottom: 10px; +      } +			 +			} + +      @media screen and (max-width: 205px) { +        #localBKU p { +          font-size: 0.6em; +        }  +         +        #localBKU input { +          font-size: 0.6em; +          min-width: 60px; +         /* max-width: 65px; */ +          min-height: 1.0em; +         /* border-radius: 5px; */ +        } +         +      } + +      @media screen and (max-width: 249px) and (min-width: 206px) { +        #localBKU p { +          font-size: 0.7em; +        }  +         +        #localBKU input { +          font-size: 0.7em; +          min-width: 70px; +       /*    max-width: 75px;    */ +          min-height: 0.95em; +        /*  border-radius: 6px;    */ +        } +          +      } + +      @media screen and (max-width: 299px) and (min-width: 250px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +       /*    max-width: 75px;      */ +      /*    border-radius: 6px;  */ +        } + +      } + +      @media screen and (max-width: 399px) and (min-width: 300px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 75px;     */ +      /*    border-radius: 6px;       */ +        } + +      } +       +      @media screen and (max-width: 649px) and (min-width: 400px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 80px;       */ +     /*     border-radius: 6px;          */ +        } + +      } + + +			 +			@media screen and (max-width: 649px) { +				 +        body { +					margin:0; +					padding:0; +					color : #000; +			  	text-align: center; +          font-size: 100%; +			  	background-color: #MAIN_BACKGOUNDCOLOR#; +				} +        				 +			  #page { +			     visibility: hidden; +			     margin-top: 0%; +			  } +			   +			  #page1 { +			    visibility: hidden; +			  } +			   +			  #main { +			    visibility: hidden; +			  } +         +        #validation { +          visibility: hidden; +          display: none; +        } +			   +			  .OA_header { +			    margin-bottom: 0px; +			    margin-top: 0px; +			    font-size: 0pt; +			    visibility: hidden; +			  } +			 +			  #leftcontent { +			    visibility: visible; +			    margin-bottom: 0px; +			    text-align: left; +			    border:none; +          vertical-align: middle; +          min-height: 173px; +          min-width: 204px; +           +			  } +         +        input[type=button] { +/*          height: 11%;  */ +          width: 70%; +        } +			} +			       +			* { +				margin: 0; +				padding: 0; +        font-family: #FONTTYPE#; +			} +							      			 +			#selectArea { +				padding-top: 10px; +				padding-bottom: 55px; +				padding-left: 10px; +			} +			 +			.setAssertionButton { +				background: #efefef; +				cursor: pointer; +				margin-top: 15px; +			  width: 70px; +			  height: 25px; +			} +			 +			#leftbutton  { +				width: 35%;  +				float:left;  +				margin-left: 15px; +			} +			 +			#rightbutton { +				width: 35%;  +				float:right;  +				margin-right: 25px;  +				text-align: right; +			} + +/*		input[type=button], .sendButton { +				background: #BUTTON_BACKGROUNDCOLOR#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;  */ +/*				cursor: pointer; +/*        box-shadow: 3px 3px 3px #222222;  */ +/*			} +			 +/*      button:hover, button:focus, button:active,  +      .sendButton:hover , .sendButton:focus, .sendButton:active, +      #mandateCheckBox:hover, #mandateCheckBox:focus, #mandateCheckBox:active { +				background: #BUTTON_BACKGROUNDCOLOR_FOCUS#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;                */ +/*				cursor: pointer; +/*        box-shadow: -1px -1px 3px #222222;  */ +/*			} +       +*/       +			input { +				/*border:1px solid #000;*/ +				cursor: pointer; +			} +       +      #localBKU input { +/*        color: #BUTTON_COLOR#;  */ +        border: 0px; +        display: inline-block; +         +      } +			 +      #localBKU input:hover, #localBKU input:focus, #localBKU input:active { +        text-decoration: underline; +      } +       +			#installJava, #BrowserNOK { +				clear:both; +				font-size:0.8em; +				padding:4px; +			} +						 +			.selectText{ +			 +			} +			 +			.selectTextHeader{ +			 +			} +			 +			.sendButton { +        width: 30%; +        margin-bottom: 1%;	 +			} +			 +			#leftcontent a { +				text-decoration:none;  +				color: #000; +			/*	display:block;*/ +				padding:4px;	 +			} +			 +			#leftcontent a:hover, #leftcontent a:focus, #leftcontent a:active { +				text-decoration:underline; +				color: #000;	 +			} +						 +			.infobutton { +				background-color: #005a00; +				color: white; +				font-family: serif; +				text-decoration: none; +				padding-top: 2px; +				padding-right: 4px; +				padding-bottom: 2px; +				padding-left: 4px; +				font-weight: bold; +			} +			 +			.hell { +				background-color : #MAIN_BACKGOUNDCOLOR#; +        color: #MAIN_COLOR#;	 +			} +			 +			.dunkel { +				background-color: #HEADER_BACKGROUNDCOLOR#; +        color: #HEADER_COLOR#; +			} +			       +			.main_header { +			   color: black; +			    font-size: 32pt; +			    position: absolute; +			    right: 10%; +			    top: 40px; +				 +			} +       +     	#alert { +		    margin: 100px 250px; +		    font-family: Verdana, Arial, Helvetica, sans-serif; +		    font-size: 14px; +		    font-weight: normal; +		    color: red; +	    } +	 +	    .reqframe { +		    /*display: none;*/ +        visibility: hidden; +		   +	    } +      			                         +    </style>  + + +  <title>Single LogOut Vorgang ... </title> +</head> + +<body> +  <noscript> +		<p> +			<strong>Note:</strong> Since your browser does not support +			JavaScript, you must press the Continue button once to proceed. +		</p> +	</noscript> + +  <div id="page"> +		<div id="page1" class="case selected-case" role="main"> +			<h2 class="OA_header" role="heading">MOA-ID Single LogOut Information</h2> +			<div id="main"> +				<div id="leftcontent" class="hell" role="application"> +           +          #if($errorMsg) +	         <div class="alert"> +		        <p>$errorMsg</p>  +	         </div>	 +	        #end + +	        #if($successMsg) +	         <div> +		        <p>$successMsg</p>  +	         </div>	 +	        #end + +	        #if($redirectURLs) +		        <div> +			       <p> +				        Sie werden von allen Online-Applikationen abgemeldet. <br> +				        Dieser Vorgang kann einige Zeit in Anspruch nehmen. +			       </p> +		       </div> +	       #end +           +				</div> +			</div> +		</div> +		<div id="validation"> +			<a href="http://validator.w3.org/check?uri="> <img +				style="border: 0; width: 88px; height: 31px" +				src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" /> +			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img +				style="border: 0; width: 88px; height: 31px" +				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				alt="CSS ist valide!" /> +			</a> +		</div> +	</div> + + +  #foreach( $el in $redirectURLs ) +	   <iframe src=$el class="reqframe"></iframe> +  #end +   +</body> +</html>
\ No newline at end of file diff --git a/id/server/doc/conf/moa-id/htmlTemplates/slo_template.html b/id/server/doc/conf/moa-id/htmlTemplates/slo_template.html new file mode 100644 index 000000000..a652855c4 --- /dev/null +++ b/id/server/doc/conf/moa-id/htmlTemplates/slo_template.html @@ -0,0 +1,438 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +  <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> +   +   <!-- MOA-ID 2.x BKUSelection Layout CSS -->                +    <style type="text/css"> +			@media screen and (min-width: 650px) { +			 +				body { +					margin:0; +					padding:0; +					color : #000; +					background-color : #fff; +			  	text-align: center; +			  	background-color: #6B7B8B; +				} +   +			  #page { +			    display: block; +			    border: 2px solid rgb(0,0,0); +			    width: 650px; +			    height: 460px; +			    margin: 0 auto; +			    margin-top: 5%; +			    position: relative; +			    border-radius: 25px; +			    background: rgb(255,255,255); +			  } +			   +			  #page1 { +			    text-align: center; +			  } +			   +			  #main { +			    /*	clear:both; */ +				  position:relative; +			    margin: 0 auto; +			    width: 250px; +			    text-align: center; +			  } +			   +			  .OA_header { +			/*	  background-color: white;*/ +			    font-size: 20pt; +			    margin-bottom: 25px; +			    margin-top: 25px; +			  } +			 +			  #leftcontent { +			    /*float:left; */ +				  width:250px; +				  margin-bottom: 25px; +			    text-align: left; +			    /*border: 1px solid rgb(0,0,0);*/ +			  } +			 +			  #leftcontent { +				 width: 300px; +				 margin-top: 30px; +			  } +       +        h2#tabheader{ +				  font-size: 1.1em;  +          padding-left: 2%; +          padding-right: 2%; +          position: relative; +			  } +        		   +			  .setAssertionButton_full { +			  	background: #efefef; +				  cursor: pointer; +				  margin-top: 15px; +			    width: 100px; +			    height: 30px +			  } +			 +			  #leftbutton  { +				 width: 30%;  +				 float:left;  +				 margin-left: 40px; +			  } +			 +			  #rightbutton { +				 width: 30%;  +				 float:right;  +				 margin-right: 45px;  +				 text-align: right; +			  } +         +        button { +          height: 25px; +          width: 75px; +          margin-bottom: 10px; +        } +         +       #validation { +        position: absolute; +        bottom: 0px; +        margin-left: 270px; +        padding-bottom: 10px; +      } +			 +			} + +      @media screen and (max-width: 205px) { +        #localBKU p { +          font-size: 0.6em; +        }  +         +        #localBKU input { +          font-size: 0.6em; +          min-width: 60px; +         /* max-width: 65px; */ +          min-height: 1.0em; +         /* border-radius: 5px; */ +        } +         +      } + +      @media screen and (max-width: 249px) and (min-width: 206px) { +        #localBKU p { +          font-size: 0.7em; +        }  +         +        #localBKU input { +          font-size: 0.7em; +          min-width: 70px; +       /*    max-width: 75px;    */ +          min-height: 0.95em; +        /*  border-radius: 6px;    */ +        } +          +      } + +      @media screen and (max-width: 299px) and (min-width: 250px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +       /*    max-width: 75px;      */ +      /*    border-radius: 6px;  */ +        } + +      } + +      @media screen and (max-width: 399px) and (min-width: 300px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 75px;     */ +      /*    border-radius: 6px;       */ +        } + +      } +       +      @media screen and (max-width: 649px) and (min-width: 400px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 80px;       */ +     /*     border-radius: 6px;          */ +        } + +      } + + +			 +			@media screen and (max-width: 649px) { +				 +        body { +					margin:0; +					padding:0; +					color : #000; +			  	text-align: center; +          font-size: 100%; +			  	background-color: #MAIN_BACKGOUNDCOLOR#; +				} +        				 +			  #page { +			     visibility: hidden; +			     margin-top: 0%; +			  } +			   +			  #page1 { +			    visibility: hidden; +			  } +			   +			  #main { +			    visibility: hidden; +			  } +         +        #validation { +          visibility: hidden; +          display: none; +        } +			   +			  .OA_header { +			    margin-bottom: 0px; +			    margin-top: 0px; +			    font-size: 0pt; +			    visibility: hidden; +			  } +			 +			  #leftcontent { +			    visibility: visible; +			    margin-bottom: 0px; +			    text-align: left; +			    border:none; +          vertical-align: middle; +          min-height: 173px; +          min-width: 204px; +           +			  } +         +        input[type=button] { +/*          height: 11%;  */ +          width: 70%; +        } +			} +			       +			* { +				margin: 0; +				padding: 0; +        font-family: #FONTTYPE#; +			} +							      			 +			#selectArea { +				padding-top: 10px; +				padding-bottom: 55px; +				padding-left: 10px; +			} +			 +			.setAssertionButton { +				background: #efefef; +				cursor: pointer; +				margin-top: 15px; +			  width: 70px; +			  height: 25px; +			} +			 +			#leftbutton  { +				width: 35%;  +				float:left;  +				margin-left: 15px; +			} +			 +			#rightbutton { +				width: 35%;  +				float:right;  +				margin-right: 25px;  +				text-align: right; +			} + +/*		input[type=button], .sendButton { +				background: #BUTTON_BACKGROUNDCOLOR#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;  */ +/*				cursor: pointer; +/*        box-shadow: 3px 3px 3px #222222;  */ +/*			} +			 +/*      button:hover, button:focus, button:active,  +      .sendButton:hover , .sendButton:focus, .sendButton:active, +      #mandateCheckBox:hover, #mandateCheckBox:focus, #mandateCheckBox:active { +				background: #BUTTON_BACKGROUNDCOLOR_FOCUS#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;                */ +/*				cursor: pointer; +/*        box-shadow: -1px -1px 3px #222222;  */ +/*			} +       +*/       +			input { +				/*border:1px solid #000;*/ +				cursor: pointer; +			} +       +      #localBKU input { +/*        color: #BUTTON_COLOR#;  */ +        border: 0px; +        display: inline-block; +         +      } +			 +      #localBKU input:hover, #localBKU input:focus, #localBKU input:active { +        text-decoration: underline; +      } +       +			#installJava, #BrowserNOK { +				clear:both; +				font-size:0.8em; +				padding:4px; +			} +						 +			.selectText{ +			 +			} +			 +			.selectTextHeader{ +			 +			} +			 +			.sendButton { +        width: 30%; +        margin-bottom: 1%;	 +			} +			 +			#leftcontent a { +				text-decoration:none;  +				color: #000; +			/*	display:block;*/ +				padding:4px;	 +			} +			 +			#leftcontent a:hover, #leftcontent a:focus, #leftcontent a:active { +				text-decoration:underline; +				color: #000;	 +			} +						 +			.infobutton { +				background-color: #005a00; +				color: white; +				font-family: serif; +				text-decoration: none; +				padding-top: 2px; +				padding-right: 4px; +				padding-bottom: 2px; +				padding-left: 4px; +				font-weight: bold; +			} +			 +			.hell { +				background-color : #MAIN_BACKGOUNDCOLOR#; +        color: #MAIN_COLOR#;	 +			} +			 +			.dunkel { +				background-color: #HEADER_BACKGROUNDCOLOR#; +        color: #HEADER_COLOR#; +			} +			       +			.main_header { +			   color: black; +			    font-size: 32pt; +			    position: absolute; +			    right: 10%; +			    top: 40px; +				 +			} +       +     	#alert { +		    margin: 100px 250px; +		    font-family: Verdana, Arial, Helvetica, sans-serif; +		    font-size: 14px; +		    font-weight: normal; +		    color: red; +	    } +	 +	    .reqframe { +		    /*display: none;*/ +        visibility: hidden; +		   +	    } +      			                         +    </style>  + + +  <title>Single LogOut Vorgang ... </title> +</head> + +<body> +  <noscript> +		<p> +			<strong>Note:</strong> Since your browser does not support +			JavaScript, you must press the Continue button once to proceed. +		</p> +	</noscript> + +  <div id="page"> +		<div id="page1" class="case selected-case" role="main"> +			<h2 class="OA_header" role="heading">MOA-ID Single LogOut Information</h2> +			<div id="main"> +				<div id="leftcontent" class="hell" role="application"> +           +          #if($errorMsg) +	         <div class="alert"> +		        <p>$errorMsg</p>  +	         </div>	 +	        #end + +	        #if($successMsg) +	         <div> +		        <p>$successMsg</p>  +	         </div>	 +	        #end + +	        #if($redirectURLs) +		        <div> +			       <p> +				        Sie werden von allen Online-Applikationen abgemeldet. <br> +				        Dieser Vorgang kann einige Zeit in Anspruch nehmen. +			       </p> +		       </div> +	       #end +           +				</div> +			</div> +		</div> +		<div id="validation"> +			<a href="http://validator.w3.org/check?uri="> <img +				style="border: 0; width: 88px; height: 31px" +				src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" /> +			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img +				style="border: 0; width: 88px; height: 31px" +				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				alt="CSS ist valide!" /> +			</a> +		</div> +	</div> + + +  #foreach( $el in $redirectURLs ) +	   <iframe src=$el class="reqframe"></iframe> +  #end +   +</body> +</html>
\ No newline at end of file diff --git a/id/server/idserverlib/pom.xml b/id/server/idserverlib/pom.xml index 9bca6e0b6..5b2890658 100644 --- a/id/server/idserverlib/pom.xml +++ b/id/server/idserverlib/pom.xml @@ -241,12 +241,19 @@  			</dependency> -->
  		<!-- <dependency> <groupId>at.gv.egovernment.moa.id</groupId> <artifactId>mandate-validate</artifactId> 
  			<version>1.1</version> </dependency> -->
 -		<dependency>
 +        <!--
 +        <dependency>
  			<groupId>commons-lang</groupId>
  			<artifactId>commons-lang</artifactId>
  			<version>2.6</version>
  		</dependency>
 +        -->
 +        <dependency>
 +            <groupId>eu.stork</groupId>
 +            <artifactId>DocumentService</artifactId>
 +            <version>0.0.1-SNAPSHOT</version>
 +        </dependency>
  		<!-- JSON JWT implementation -->
  		<dependency>
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java index 6f83da367..e2c0c1f18 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java @@ -33,6 +33,10 @@ public interface MOAIDAuthConstants {    public static final String PARAM_SSO = "SSO";    public static final String INTERFEDERATION_IDP = "interIDP"; +  public static final String PARAM_SLOSTATUS = "status";	 +  public static final String SLOSTATUS_SUCCESS = "success"; +  public static final String SLOSTATUS_ERROR = "error"; +      /** servlet parameter "sourceID" */    public static final String PARAM_SOURCEID = "sourceID";      /** servlet parameter "BKUSelectionTemplate" */ 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/auth/servlet/IDPSingleLogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java new file mode 100644 index 000000000..ac4e56023 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java @@ -0,0 +1,122 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.auth.servlet; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.VelocityContext; + +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.moduls.AuthenticationManager; +import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.storage.AssertionStorage; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public class IDPSingleLogOutServlet extends AuthServlet { + +	private static final long serialVersionUID = -1301786072691577221L; +		 +	protected void doGet(HttpServletRequest req, HttpServletResponse resp) +			    throws ServletException, IOException { +		Logger.debug("receive IDP SingleLogOut Request"); +		SSOManager ssomanager = SSOManager.getInstance();		 +		String ssoid = ssomanager.getSSOSessionID(req); +		 +		Object tokkenObj = req.getParameter(PARAM_SLOSTATUS); +		String tokken = null; +		String status = null; +		if (tokkenObj != null && tokkenObj instanceof String) { +			tokken = (String) tokkenObj; +			try {	 +				status = AssertionStorage.getInstance().get(tokken, String.class); +				if (MiscUtil.isNotEmpty(status)) { +					AssertionStorage.getInstance().remove(tokken); +					 +				} +				VelocityContext context = new VelocityContext(); +				if (SLOSTATUS_SUCCESS.equals(status)) +					context.put("successMsg", +							MOAIDMessageProvider.getInstance().getMessage("slo.00", null)); +				else +					context.put("errorMsg",  +							MOAIDMessageProvider.getInstance().getMessage("slo.01", null)); +	                	 +					ssomanager.printSingleLogOutInfo(context, resp); +				 +			} catch (MOAIDException e) { +				handleErrorNoRedirect(e.getMessage(), e, req, resp); +				 +			} catch (MOADatabaseException e) { +				handleErrorNoRedirect(e.getMessage(), e, req, resp); +				 +			} +			 +		} + +		if (MiscUtil.isNotEmpty(status)) { +			//print status information +			 +			 +		} else if (MiscUtil.isNotEmpty(ssoid)) {			 +			if (ssomanager.isValidSSOSession(ssoid, null)) { +				 +				AuthenticationManager authmanager = AuthenticationManager.getInstance(); +				String moaSessionID = AuthenticationSessionStoreage.getMOASessionSSOID(ssoid); + +				if (MiscUtil.isNotEmpty(moaSessionID)) { +					AuthenticationSession authSession; +					try { +						authSession = AuthenticationSessionStoreage +								.getSession(moaSessionID); +						if(authSession != null) { +							authmanager.performSingleLogOut(req, resp, authSession, null); +							 +						} +						 +					} catch (MOADatabaseException e) { +						//TODO: insert error Handling +						 +					} catch (MOAIDException e) { +						// TODO Auto-generated catch block +						e.printStackTrace(); +					} +				}																 +			}						 +		} +				 +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java index 9b300578a..d7de985a4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/LogOutServlet.java @@ -109,7 +109,7 @@ public class LogOutServlet extends AuthServlet {  			RequestStorage.removePendingRequest(AuthenticationSessionStoreage.getPendingRequestID(moasessionid)); -			authmanager.logout(req, resp, moasessionid); +			authmanager.performOnlyIDPLogOut(req, resp, moasessionid);  			Logger.info("User with SSO Id " + ssoid + " is logged out and get redirect to "+ redirectUrl);  		} else {  			Logger.info("No active SSO session found. User is maybe logout already and get redirect to "+ redirectUrl); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java index 57755ca9f..6e1811c8b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/RedirectServlet.java @@ -46,6 +46,8 @@ public class RedirectServlet extends AuthServlet{  	public static final String REDIRCT_PARAM_URL = "redirecturl"; +	private static final String DEFAULT_REDIRECTTARGET = "_parent"; +	  	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			throws ServletException, IOException { @@ -55,16 +57,10 @@ public class RedirectServlet extends AuthServlet{  		String target = req.getParameter(PARAM_TARGET);  		String artifact = req.getParameter(PARAM_SAMLARTIFACT);  		String interIDP = req.getParameter(INTERFEDERATION_IDP); -		 -		if (MiscUtil.isEmpty(artifact) && MiscUtil.isEmpty(interIDP)) { -			resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid"); -			return; -		} -		  		Logger.debug("Check URL against online-applications");  		OnlineApplication oa = null; -		String redirectTarget = "_parent"; +		String redirectTarget = DEFAULT_REDIRECTTARGET;  		try {  			oa = ConfigurationDBRead.getActiveOnlineApplication(url);			  			if (oa == null) {		 @@ -118,10 +114,16 @@ public class RedirectServlet extends AuthServlet{  					resp.addHeader("Location", url); -				} else { -					resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Parameters not valid"); -					return; +				} else {					 +					Logger.debug("Redirect to " + url);					 +					String redirect_form = RedirectFormBuilder.buildLoginForm(url, DEFAULT_REDIRECTTARGET); +					resp.setContentType("text/html;charset=UTF-8"); +					resp.setStatus(HttpServletResponse.SC_OK); +					PrintWriter out = new PrintWriter(resp.getOutputStream());  +					out.write(redirect_form); +					out.flush(); +						  				}  			} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/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..d1e04e107 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/SLOInformationContainer.java @@ -24,13 +24,18 @@ package at.gv.egovernment.moa.id.data;  import java.io.Serializable;  import java.util.ArrayList; +import java.util.Collection;  import java.util.Iterator;  import java.util.LinkedHashMap;  import java.util.List; +import java.util.Map.Entry; +import java.util.Set;  import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.NameID;  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,58 +57,93 @@ 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()); +						sloDesc = SingleLogOutBuilder.getRequestSLODescriptor(el.getIdpurlprefix()); -						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(), +						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()) -			return interator.next(); -		 -		else -			return null;	 +	 +	public boolean hasFrontChannelOA() { +		return !activeFrontChannalOAs.isEmpty();  	} -	public SLOInformationImpl getFrontChannelOASessionDescripten(String oaID) { -		return activeFrontChannalOAs.get(oaID); +	public Set<Entry<String, SLOInformationImpl>> getFrontChannelOASessionDescriptions() { +		return activeFrontChannalOAs.entrySet();  	}  	public void removeFrontChannelOA(String oaID) { @@ -147,9 +187,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/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java index a3827ab73..0cbe749e0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java @@ -143,7 +143,7 @@ public class DispatcherServlet extends AuthServlet{  										//remove MOASession  										AuthenticationSession moaSession = AuthenticationSessionStoreage.getSessionWithPendingRequestID(pendingRequestID); -										AuthenticationManager.getInstance().logout(req, resp, moaSession.getSessionID()); +										AuthenticationManager.getInstance().performOnlyIDPLogOut(req, resp, moaSession.getSessionID());  										return;  									} @@ -468,12 +468,12 @@ public class DispatcherServlet extends AuthServlet{  						} catch (AuthenticationException e) {  							Logger.warn("SSO Session information can not be stored  -> SSO is not enabled!"); -							authmanager.logout(req, resp, moasessionID); +							authmanager.performOnlyIDPLogOut(req, resp, moasessionID);  							isSSOSession = false;  						}  					} else { -						authmanager.logout(req, resp, moasessionID); +						authmanager.performOnlyIDPLogOut(req, resp, moasessionID);  					}  					//Advanced statistic logging diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index 5a06b3ecd..a7eb51877 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -24,13 +24,21 @@ package at.gv.egovernment.moa.id.moduls;  import java.io.IOException;  import java.io.PrintWriter; +import java.io.StringWriter;  import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator;  import java.util.List; +import java.util.Map.Entry;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine;  import org.joda.time.DateTime;  import org.opensaml.common.impl.SecureRandomIdentifierGenerator;  import org.opensaml.common.xml.SAMLConstants; @@ -38,6 +46,8 @@ import org.opensaml.saml2.core.AuthnContextClassRef;  import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration;  import org.opensaml.saml2.core.AuthnRequest;  import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.LogoutResponse;  import org.opensaml.saml2.core.NameID;  import org.opensaml.saml2.core.NameIDPolicy;  import org.opensaml.saml2.core.NameIDType; @@ -45,12 +55,15 @@ import org.opensaml.saml2.core.RequestedAuthnContext;  import org.opensaml.saml2.core.Subject;  import org.opensaml.saml2.metadata.EntityDescriptor;  import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.SingleLogoutService;  import org.opensaml.saml2.metadata.SingleSignOnService;  import org.opensaml.saml2.metadata.provider.MetadataProviderException;  import org.opensaml.security.MetadataCredentialResolver;  import org.opensaml.security.MetadataCredentialResolverFactory;  import org.opensaml.security.MetadataCriteria;  import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.ws.soap.common.SOAPException; +import org.opensaml.xml.XMLObject;  import org.opensaml.xml.security.CriteriaSet;  import org.opensaml.xml.security.SecurityException;  import org.opensaml.xml.security.criteria.EntityIDCriteria; @@ -64,19 +77,32 @@ import at.gv.egovernment.moa.id.auth.exception.BuildException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;  import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.SLOInformationContainer; +import at.gv.egovernment.moa.id.data.SLOInformationImpl; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.ArtifactBinding;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.id.storage.AssertionStorage;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.ParamValidatorUtils; +import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MessageProvider;  import at.gv.egovernment.moa.util.MiscUtil;  import at.gv.egovernment.moa.util.StringUtils; @@ -138,7 +164,149 @@ public class AuthenticationManager extends AuthServlet {  		return false;  	} -	public void logout(HttpServletRequest request, +	public void performSingleLogOut(HttpServletRequest httpReq, +	HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException {		 +		String pvpSLOIssuer = null; +		String inboundRelayState = null; +		 +		if (pvpReq != null) { +			MOARequest samlReq = (MOARequest) pvpReq.getRequest(); +			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); +			pvpSLOIssuer = logOutReq.getIssuer().getValue(); +			inboundRelayState = samlReq.getRelayState(); +		} +		 +		SSOManager ssomanager = SSOManager.getInstance(); +		 +		//store active OAs to SLOContaine +		List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session); +		List<InterfederationSessionStore> dbIDPs = AuthenticationSessionStoreage.getAllActiveIDPsFromMOASession(session); +		SLOInformationContainer sloContainer = new SLOInformationContainer(); +		sloContainer.setSloRequest(pvpReq); +		sloContainer.parseActiveIDPs(dbIDPs, pvpSLOIssuer); +		sloContainer.parseActiveOAs(dbOAs, pvpSLOIssuer); +						 +		//terminate MOASession +		try { +			AuthenticationSessionStoreage.destroySession(session.getSessionID()); +			ssomanager.deleteSSOSessionID(httpReq, httpResp); +			 +		} catch (MOADatabaseException e) { +			Logger.warn("Delete MOASession FAILED."); +			sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix()); +			 +		} +		 +		//start service provider back channel logout process +		Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();	 +		while (nextOAInterator.hasNext()) { +			SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); +			LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); + +			try { +				List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); +				 +				LogoutResponse sloResp = null;						 +				for (XMLObject el : soapResp) { +					if (el instanceof LogoutResponse) +						sloResp = (LogoutResponse) el;							 +				} +				 +				if (sloResp == null) { +					Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() +							+ " FAILED. NO LogOut response received."); +					sloContainer.putFailedOA(sloReq.getIssuer().getValue()); +					 +				} +				 +				SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp); +										 +			} catch (SOAPException e) { +				Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() +						+ " FAILED.", e); +				sloContainer.putFailedOA(sloReq.getIssuer().getValue()); +				 +			} catch (SecurityException e) { +				Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() +						+ " FAILED.", e); +				sloContainer.putFailedOA(sloReq.getIssuer().getValue()); +				 +			}					 +		} +						 +		//start service provider front channel logout process +		try { +			if (sloContainer.hasFrontChannelOA()) { +				String relayState = Random.nextRandom(); +				 +				Collection<Entry<String, SLOInformationImpl>> sloDescr = sloContainer.getFrontChannelOASessionDescriptions(); +				List<String> sloReqList = new ArrayList<String>(); +				for (Entry<String, SLOInformationImpl> el : sloDescr) { +					LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(el.getValue()); +					try { +						sloReqList.add(SingleLogOutBuilder.getFrontChannelSLOMessageURL(el.getValue().getServiceURL(), el.getValue().getBinding(),  +								sloReq, httpReq, httpResp, relayState)); +						 +					} catch (Exception e) { +						Logger.warn("Failed to build SLO request for OA:" + el.getKey()); +						sloContainer.putFailedOA(el.getKey()); +						 +					}														 +				} +				 +				AssertionStorage.getInstance().put(relayState, sloContainer); +				 +		        VelocityContext context = new VelocityContext(); +		        context.put("redirectURLs", sloReqList); +		        ssomanager.printSingleLogOutInfo(context, httpResp); +				 +								 +			} else { +				if (pvpReq != null) { +					//send SLO response to SLO request issuer +					SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); +					LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); +					SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); +					 +				} else { +					//print SLO information directly +			        VelocityContext context = new VelocityContext(); +			        if (sloContainer.getSloFailedOAs() == null ||  +			        		sloContainer.getSloFailedOAs().size() == 0) +			        	context.put("successMsg",  +			        			MessageProvider.getInstance().getMessage("slo.00", null)); +			        else +			        	context.put("errorMsg",  +			        			MessageProvider.getInstance().getMessage("slo.01", null)); +			        ssomanager.printSingleLogOutInfo(context, httpResp); +										 +				} +									 +			}	 +								 +		} catch (MOADatabaseException e) { +			Logger.error("MOA AssertionDatabase ERROR", e); +			if (pvpReq != null) { +				SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); +				LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq); +				SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, inboundRelayState); +				 +			}else { +				//print SLO information directly +		        VelocityContext context = new VelocityContext(); +	        	context.put("errorMsg",  +	        			MessageProvider.getInstance().getMessage("slo.01", null)); +		        ssomanager.printSingleLogOutInfo(context, httpResp); +									 +			} +			 +		} catch (Exception e) { +			// TODO Auto-generated catch block +			e.printStackTrace(); +		}				 +	} +		 +	public void performOnlyIDPLogOut(HttpServletRequest request,  			HttpServletResponse response, String moaSessionID) {  		Logger.info("Logout"); @@ -196,7 +364,8 @@ public class AuthenticationManager extends AuthServlet {  			throws ServletException, IOException, MOAIDException {   			String form = SendAssertionFormBuilder.buildForm(target.requestedModule(),  -					target.requestedAction(), target.getRequestID(), oaParam, request.getContextPath()); +					target.requestedAction(), target.getRequestID(), oaParam,  +					AuthConfigurationProvider.getInstance().getPublicURLPrefix());  			response.setContentType("text/html;charset=UTF-8");  			PrintWriter out = new PrintWriter(response.getOutputStream());  diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java index f4f89a4ba..a46b11c6e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/SSOManager.java @@ -22,17 +22,31 @@   *******************************************************************************/  package at.gv.egovernment.moa.id.moduls; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.net.URI;  import java.util.List;  import javax.servlet.http.Cookie;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.app.VelocityEngine;  import org.hibernate.Query;  import org.hibernate.Session;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;  import at.gv.egovernment.moa.id.commons.db.dao.session.AuthenticatedSessionStore;  import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; @@ -42,11 +56,15 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil;  public class SSOManager { +	private static final String HTMLTEMPLATESDIR = "htmlTemplates/"; +	private static final String HTMLTEMPLATEFULL = "slo_template.html"; +	  	private static final String SSOCOOKIE = "MOA_ID_SSO";  	private static final String SSOINTERFEDERATION = "MOA_INTERFEDERATION_SSO"; @@ -267,6 +285,63 @@ public class SSOManager {  	} +	public void printSingleLogOutInfo(VelocityContext context, HttpServletResponse httpResp) throws MOAIDException {		 +		try {			 +			Logger.trace("Initialize VelocityEngine..."); +			VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); +			 +			InputStream is = null; +			try { +				String rootconfigdir = AuthConfigurationProvider.getInstance().getRootConfigFileDir(); +				String pathLocation = rootconfigdir + HTMLTEMPLATESDIR + HTMLTEMPLATEFULL; +				File file = new File(new URI(pathLocation)); +				is = new  FileInputStream(file); +				evaluateSLOTemplate(context, httpResp, is); +				 +			} catch (Exception e) { +				Logger.warn("SLO Template is not found in configuration directory. Load template from project library ... "); +				 +				try  { +					String pathLocation = "resources/templates/" + HTMLTEMPLATEFULL; +					is = Thread.currentThread() +							.getContextClassLoader() +							.getResourceAsStream(pathLocation);				 +					evaluateSLOTemplate(context, httpResp, is); +					 +				} catch (Exception e1) { +					Logger.error("Single LogOut form can not created.", e); +					throw new MOAIDException("Create Single LogOut information FAILED.", null, e); +				} +				 +			} finally { +				if (is != null) +					is.close(); +				 +			} +			 +		} catch (Exception e) { +			Logger.error("Single LogOut form can not created.", e); +			throw new MOAIDException("Create Single LogOut information FAILED.", null, e); +		} +			 +	} +	 +	private void evaluateSLOTemplate(VelocityContext context, HttpServletResponse httpResp, InputStream is) throws ConfigurationException, IOException { +		BufferedReader reader = new BufferedReader(new InputStreamReader(is )); +		 +		//set default elements to velocity context +		context.put("contextpath", AuthConfigurationProvider.getInstance().getPublicURLPrefix()); +		 +		StringWriter writer = new StringWriter();			 +		//velocityEngine.evaluate(context, writer, "SLO_Template", reader);			 +		Velocity.evaluate(context, writer, "SLO Template", reader); + +		 +		httpResp.setContentType("text/html;charset=UTF-8");             +		httpResp.getOutputStream().write(writer.toString().getBytes()); +		 +	} +	  	private String getValueFromCookie(HttpServletRequest httpReq, String cookieName) {  		Cookie[] cookies = httpReq.getCookies(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java new file mode 100644 index 000000000..ece1a805d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/opemsaml/MOAStringRedirectDeflateEncoder.java @@ -0,0 +1,71 @@ +/* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ +package at.gv.egovernment.moa.id.opemsaml; + +import org.opensaml.common.binding.SAMLMessageContext; +import org.opensaml.saml2.binding.encoding.HTTPRedirectDeflateEncoder; +import org.opensaml.ws.message.MessageContext; +import org.opensaml.ws.message.encoder.MessageEncodingException; + +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class MOAStringRedirectDeflateEncoder extends HTTPRedirectDeflateEncoder { + +	private String redirectURL = null; +	 +	public void encode(MessageContext messageContext) +			throws MessageEncodingException { +		if (!(messageContext instanceof SAMLMessageContext)) { +			Logger.error("Invalid message context type, this encoder only support SAMLMessageContext"); +			throw new MessageEncodingException( +					"Invalid message context type, this encoder only support SAMLMessageContext"); +		} + +		SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext; + +		String endpointURL = getEndpointURL(samlMsgCtx).buildURL(); + +		setResponseDestination(samlMsgCtx.getOutboundSAMLMessage(), endpointURL); + +		removeSignature(samlMsgCtx); + +		String encodedMessage = deflateAndBase64Encode(samlMsgCtx +				.getOutboundSAMLMessage()); + +		redirectURL = buildRedirectURL(samlMsgCtx, endpointURL, +				encodedMessage); +	} + +	/** +	 * @return the redirectURL +	 */ +	public String getRedirectURL() { +		return redirectURL; +	} +	 +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/MetadataAction.java index 01f7e18ba..fec8e3b98 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 @@ -244,7 +244,7 @@ public class MetadataAction implements IAction {  		postassertionConsumerService.setIndex(0);  		postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI);  		postassertionConsumerService.setLocation(PVPConfiguration -				.getInstance().getIDPSSOPostService());	 +				.getInstance().getSPSSOPostService());	  		postassertionConsumerService.setIsDefault(true);  		spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); @@ -253,7 +253,7 @@ public class MetadataAction implements IAction {  		redirectassertionConsumerService.setIndex(1);  		redirectassertionConsumerService.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI);  		redirectassertionConsumerService.setLocation(PVPConfiguration -				.getInstance().getIDPSSORedirectService());		 +				.getInstance().getSPSSORedirectService());  		spSSODescriptor.getAssertionConsumerServices().add(redirectassertionConsumerService); @@ -265,14 +265,14 @@ public class MetadataAction implements IAction {  //		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 redirectSLOService =  +				SAML2Utils.createSAMLObject(SingleLogoutService.class);			 +		redirectSLOService.setLocation(PVPConfiguration +				.getInstance().getSPSSORedirectService()); +		redirectSLOService +				.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); +		spSSODescriptor.getSingleLogoutServices().add(redirectSLOService);  		spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS); @@ -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/PVP2XProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java index d9ce6250a..7f8ea91bd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java @@ -111,6 +111,11 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  	public static final String ATTRIBUTEQUERY = "AttributeQuery";  	public static final String SINGLELOGOUT = "SingleLogOut"; +	public static final String ENDPOINT_IDP = "idp"; +	public static final String ENDPOINT_SP = "sp"; +	 +	public static final String PARAMETER_ENDPOINT = "endpointtype"; +	  	private static List<IDecoder> decoder = new ArrayList<IDecoder>();  	private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); @@ -168,6 +173,23 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  		return null;  	} +	private boolean isServiceProviderEndPointUsed(HttpServletRequest req) throws InvalidProtocolRequestException { +		Object obj = req.getParameter(PARAMETER_ENDPOINT); +		if (obj instanceof String) { +			String param = (String) obj; +			if (MiscUtil.isNotEmpty(param)) { +				if (ENDPOINT_IDP.equals(param)) +					return false; +				 +				else if (ENDPOINT_SP.equals(param)) +					return true; +			}			 +		} +		 +		Logger.error("No valid PVP 2.1 entpoint descriptor"); +		throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); +	} +	  	public PVP2XProtocol() {  		super();  	} @@ -193,7 +215,8 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			return null;  		}  		try { -			InboundMessage msg = (InboundMessage) decoder.decode(request, response); +						 +			InboundMessage msg = (InboundMessage) decoder.decode(request, response, isServiceProviderEndPointUsed(request));  			if (MiscUtil.isEmpty(msg.getEntityID())) {  				throw new InvalidProtocolRequestException("pvp2.20", new Object[] {}); @@ -217,13 +240,14 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			else if (msg instanceof MOARequest &&   					((MOARequest)msg).getSamlRequest() instanceof LogoutRequest) -				return preProcessLogOut(request, response, (MOARequest) msg); +				return preProcessLogOut(request, response, msg); -			else if (msg instanceof MOARequest &&  -					((MOARequest)msg).getSamlRequest() instanceof LogoutResponse) -				return preProcessLogOut(request, response, (MOARequest) msg); +			else if (msg instanceof MOAResponse &&  +					((MOAResponse)msg).getResponse() instanceof LogoutResponse) +				return preProcessLogOut(request, response, msg); -			else if (msg instanceof MOAResponse) { +			else if (msg instanceof MOAResponse && +					((MOAResponse)msg).getResponse() instanceof Response) {  				//load service provider AuthRequest from session  				IRequest obj = RequestStorage.getPendingRequest(msg.getRelayState()); @@ -420,20 +444,22 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  	 * @throws MOAIDException   	 */  	private IRequest preProcessLogOut(HttpServletRequest request, -			HttpServletResponse response, MOARequest msg) throws MOAIDException { +			HttpServletResponse response, InboundMessage inMsg) throws MOAIDException {  		PVPTargetConfiguration config = new PVPTargetConfiguration(); -		if (((MOARequest)msg).getSamlRequest() instanceof LogoutRequest) { +		MOARequest msg; +		if (inMsg instanceof MOARequest &&  +				((MOARequest)inMsg).getSamlRequest() instanceof LogoutRequest) {  			//preProcess single logout request from service provider -					 +			 +			msg = (MOARequest) inMsg; +			  			EntityDescriptor metadata = msg.getEntityMetadata();  			if(metadata == null) {  				throw new NoMetadataInformationException();  			} - -			  			String oaURL = metadata.getEntityID();  			oaURL = StringEscapeUtils.escapeHtml(oaURL); @@ -443,10 +469,11 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			config.setBinding(msg.getRequestBinding());									 -		} else if (((MOARequest)msg).getSamlRequest() instanceof LogoutResponse) { +		} else if (inMsg instanceof MOAResponse &&  +				((MOAResponse)inMsg).getResponse() instanceof LogoutResponse) {  			//preProcess single logour response from service provider -			LogoutResponse resp = (LogoutResponse) (((MOARequest)msg).getSamlRequest()); +			LogoutResponse resp = (LogoutResponse) (((MOAResponse)inMsg).getResponse());  			Logger.debug("PreProcess SLO Response from " + resp.getIssuer()); @@ -458,14 +485,14 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			}  			//TODO: check if relayState exists -			msg.getRelayState(); +			inMsg.getRelayState();  		} else   			throw new MOAIDException("Unsupported request", new Object[] {}); -		config.setRequest(msg); +		config.setRequest(inMsg);  		config.setAction(SINGLELOGOUT);  		return config;  	} @@ -624,7 +651,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  	 */  	private MOAResponse preProcessAuthResponse(MOAResponse msg) {  		Logger.debug("Start PVP21 assertion processing... "); -		Response samlResp = msg.getResponse(); +		Response samlResp = (Response) msg.getResponse();  		try {  			if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { 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..46e02d048 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java @@ -22,26 +22,51 @@   */  package at.gv.egovernment.moa.id.protocols.pvp2x; +import java.io.Serializable; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Collection;  import java.util.Iterator;  import java.util.List; +import java.util.Map.Entry;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.SerializationUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.hibernate.HibernateException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext;  import org.opensaml.common.xml.SAMLConstants;  import org.opensaml.saml2.core.LogoutRequest;  import org.opensaml.saml2.core.LogoutResponse;  import org.opensaml.saml2.core.RequestAbstractType;  import org.opensaml.saml2.core.Status;  import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;  import org.opensaml.ws.message.encoder.MessageEncodingException;  import org.opensaml.ws.soap.common.SOAPException;  import org.opensaml.xml.XMLObject;  import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.x509.X509Credential;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet; +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;  import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; @@ -49,9 +74,11 @@ import at.gv.egovernment.moa.id.data.IAuthData;  import at.gv.egovernment.moa.id.data.SLOInformationContainer;  import at.gv.egovernment.moa.id.data.SLOInformationImpl;  import at.gv.egovernment.moa.id.data.SLOInformationInterface; +import at.gv.egovernment.moa.id.moduls.AuthenticationManager;  import at.gv.egovernment.moa.id.moduls.IAction;  import at.gv.egovernment.moa.id.moduls.IRequest;  import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; @@ -59,12 +86,17 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.builder.SingleLogOutBuilder;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; +import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;  import at.gv.egovernment.moa.id.storage.AssertionStorage;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.Random; +import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MessageProvider;  import at.gv.egovernment.moa.util.MiscUtil; +import at.gv.egovernment.moa.util.URLEncoder;  /**   * @author tlenz @@ -82,16 +114,16 @@ public class SingleLogOutAction implements IAction {  		PVPTargetConfiguration pvpReq = (PVPTargetConfiguration) req;   -		if (pvpReq.getRequest() instanceof MOARequest) { +		if (pvpReq.getRequest() instanceof MOARequest && +				((MOARequest)pvpReq.getRequest()).getSamlRequest() instanceof LogoutRequest) { +			Logger.debug("Process Single LogOut request");  			MOARequest samlReq = (MOARequest) pvpReq.getRequest(); -			if (samlReq.getSamlRequest() instanceof LogoutRequest) { -				Logger.debug("Process Single LogOut request"); -				LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); +			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest(); -				AuthenticationSession session =  -						AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID( -								logOutReq.getIssuer().getValue(),  -								logOutReq.getNameID().getValue()); +			AuthenticationSession session =  +					AuthenticationSessionStoreage.searchMOASessionWithNameIDandOAID( +							logOutReq.getIssuer().getValue(),  +							logOutReq.getNameID().getValue());  				if (session == null) {  					Logger.warn("Can not find active SSO session with nameID "  @@ -104,7 +136,7 @@ public class SingleLogOutAction implements IAction {  						Logger.warn("Can not find active Session. Single LogOut not possible!");  						SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);  						LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq); -						sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); +						SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());  						return null;  					} else { @@ -116,101 +148,150 @@ public class SingleLogOutAction implements IAction {  							Logger.warn("Can not find active Session. Single LogOut not possible!");  							SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq);  							LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq); -							sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); +							SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());  							return null;  						}						  					}					  				} -				//store active OAs to SLOContaine -				List<OASessionStore> dbOAs = AuthenticationSessionStoreage.getAllActiveOAFromMOASession(session);				 -				SLOInformationContainer sloContainer = new SLOInformationContainer(); -				sloContainer.setSloRequest(pvpReq); -				sloContainer.parseActiveOAs(dbOAs, logOutReq.getIssuer().getValue()); -								 -				//terminate MOASession -				try { -					AuthenticationSessionStoreage.destroySession(session.getSessionID()); -					 -				} catch (MOADatabaseException e) { -					Logger.warn("Delete MOASession FAILED."); -					sloContainer.putFailedOA(AuthConfigurationProvider.getInstance().getPublicURLPrefix()); -					 -				} -				 -				//start service provider back channel logout process -				Iterator<String> nextOAInterator = sloContainer.getNextBackChannelOA();	 -				while (nextOAInterator.hasNext()) { -					SLOInformationImpl sloDescr = sloContainer.getBackChannelOASessionDescripten(nextOAInterator.next()); -					LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); - -					try { -						List<XMLObject> soapResp = MOASAMLSOAPClient.send(sloDescr.getServiceURL(), sloReq); -						 -						LogoutResponse sloResp = null;						 -						for (XMLObject el : soapResp) { -							if (el instanceof LogoutResponse) -								sloResp = (LogoutResponse) el;							 -						} -						 -						if (sloResp == null) { -							Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() -									+ " FAILED. NO LogOut response received."); -							sloContainer.putFailedOA(sloReq.getIssuer().getValue()); +				AuthenticationManager authManager = AuthenticationManager.getInstance(); +				authManager.performSingleLogOut(httpReq, httpResp, session, pvpReq); -						} -						 -						checkStatusCode(sloContainer, sloResp); -												 -					} catch (SOAPException e) { -						Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() -								+ " FAILED.", e); -						sloContainer.putFailedOA(sloReq.getIssuer().getValue()); -						 -					} catch (SecurityException e) { -						Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue() -								+ " FAILED.", e); -						sloContainer.putFailedOA(sloReq.getIssuer().getValue()); -						 -					}					 -				} -								 -				//start service provider front channel logout process -				try { -					doFrontChannelLogOut(sloContainer, httpReq, httpResp); -					 -				} catch (MOADatabaseException e) { -					Logger.error("MOA AssertionDatabase ERROR", e); -					SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); -					LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq); -					sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); -					return null; -					 -				} -				 -			} else if (samlReq.getSamlRequest() instanceof LogoutResponse) { +			} else if (pvpReq.getRequest() instanceof MOAResponse && +					((MOAResponse)pvpReq.getRequest()).getResponse() instanceof LogoutResponse) {  				Logger.debug("Process Single LogOut response"); -				LogoutResponse logOutResp = (LogoutResponse) samlReq.getSamlRequest(); +				LogoutResponse logOutResp = (LogoutResponse) ((MOAResponse)pvpReq.getRequest()).getResponse(); -				try { -					if (MiscUtil.isEmpty(samlReq.getRelayState())) { +				try {					 +					String relayState = pvpReq.getRequest().getRelayState(); +					if (MiscUtil.isEmpty(relayState)) {  						Logger.warn("SLO Response from " + logOutResp.getIssuer().getValue()   								+ " has no SAML2 RelayState.");					  						throw new SLOException("pvp2.19", null);  					} -					SLOInformationContainer sloContainer =  -							AssertionStorage.getInstance().get(samlReq.getRelayState(), SLOInformationContainer.class);					 -					checkStatusCode(sloContainer, logOutResp); -					sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue()); -					doFrontChannelLogOut(sloContainer, httpReq, httpResp); +					Session session = MOASessionDBUtils.getCurrentSession();					 +					boolean storageSuccess = false; +					int counter = 0; +					 +					//TODO: add counter to prevent deadlock +					 +					while (!storageSuccess) { +						Transaction tx = session.beginTransaction(); +						 +						List result; +						Query query = session.getNamedQuery("getAssertionWithArtifact"); +						query.setParameter("artifact", relayState); +						result = query.list();					   +						Logger.trace("Found entries: " + result.size()); +						   +						//Assertion requires an unique artifact +						if (result.size() != 1) { +							Logger.trace("No entries found."); +						   	throw new MOADatabaseException("No sessioninformation found with this ID"); +						} +						   +						AssertionStore element = (AssertionStore) result.get(0);					 +						Object data = SerializationUtils.deserialize(element.getAssertion()); +						 +						if (data instanceof SLOInformationContainer) { +							SLOInformationContainer sloContainer = (SLOInformationContainer) data; +							 +							//check status +							SingleLogOutBuilder.checkStatusCode(sloContainer, logOutResp); +														 +							if (sloContainer.hasFrontChannelOA()) {							 +								try { +									//some response are open +									byte[] serializedSLOContainer = SerializationUtils.serialize((Serializable) sloContainer); +									element.setAssertion(serializedSLOContainer); +									element.setType(sloContainer.getClass().getName()); +							 +									session.saveOrUpdate(element);							 +									tx.commit(); +									 +									//sloContainer could be stored to database +									storageSuccess = true; +									 +								} catch(HibernateException e) { +									tx.rollback(); + +									counter++;									 +									Logger.debug("SLOContainter could not stored to database. Wait some time and restart storage process ... "); +									java.util.Random rand = new java.util.Random(); +									 +									try { +										Thread.sleep(rand.nextInt(20)*10); +										 +									} catch (InterruptedException e1) { +										Logger.warn("Thread could not stopped. ReStart storage process immediately", e1); +									}																	 +								} +								 +							} else { +								//last response received. +								try { +									session.delete(element); +									tx.commit(); + +								} catch(HibernateException e) { +									tx.rollback();								 +									Logger.error("SLOContainter could not deleted from database. "); +									 +								} +									 +								storageSuccess = true; +								String redirectURL = null; +								if (sloContainer.getSloRequest() != null) { +									//send SLO response to SLO request issuer +									SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(sloContainer.getSloRequest()); +									LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, sloContainer.getSloRequest(), sloContainer.getSloFailedOAs()); +									redirectURL = SingleLogOutBuilder.getFrontChannelSLOMessageURL(sloService, message, httpReq, httpResp, sloContainer.getSloRequest().getRequest().getRelayState()); +																	 +								} else { +									//print SLO information directly +									redirectURL = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/idpSingleLogout"; +									 +									String artifact = Random.nextRandom(); +									 +							        String statusCode = null; +									if (sloContainer.getSloFailedOAs() == null ||  +							        		sloContainer.getSloFailedOAs().size() == 0)							       							   							        	 +							        	statusCode  = SLOSTATUS_SUCCESS; +							        else +							        	statusCode  = SLOSTATUS_ERROR; + +									AssertionStorage.getInstance().put(artifact, statusCode); +							        redirectURL = addURLParameter(redirectURL, PARAM_SLOSTATUS, artifact); +							         +								}								 +								//redirect to Redirect Servlet +								String url = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/RedirectServlet"; +								url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8")); +								url = httpResp.encodeRedirectURL(url); +							 +								httpResp.setContentType("text/html"); +								httpResp.setStatus(302); +								httpResp.addHeader("Location", url); +		 +							} +						} else { +							Logger.warn("Sessioninformation Cast-Exception by using Artifact=" + relayState); +							throw new MOADatabaseException("Sessioninformation Cast-Exception"); +						 +						}						 +					}  				} catch (MOADatabaseException e) {  					Logger.error("MOA AssertionDatabase ERROR", e);  					throw new SLOException("pvp2.19", null); +				} catch (UnsupportedEncodingException e) { +					Logger.error("Finale SLO redirct not possible.", e); +					throw new AuthenticationException("pvp2.13", new Object[]{}); +  				}  			} else { @@ -218,13 +299,7 @@ public class SingleLogOutAction implements IAction {  				throw new MOAIDException("pvp2.13", null);  			} -			 -		} else { -			Logger.error("Process SingleLogOutAction but request is NOT of type MOARequest."); -			throw new MOAIDException("pvp2.13", null); -			 -		} -				 +							  		return null;		  	} @@ -245,117 +320,12 @@ public class SingleLogOutAction implements IAction {  		return PVP2XProtocol.SINGLELOGOUT;  	} -	private void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) { -		Status status = logOutResp.getStatus();				 -		if (!status.getStatusCode().equals(StatusCode.SUCCESS_URI)) { -			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue() -					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue() -					+ " Message: " + status.getStatusMessage().getMessage() + ")"); -			sloContainer.putFailedOA(logOutResp.getIssuer().getValue()); -			 -		} else -			Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS"); -		 +	protected static String addURLParameter(String url, String paramname, +			String paramvalue) { +		String param = paramname + "=" + paramvalue; +		if (url.indexOf("?") < 0) +			return url + "?" + param; +		else +			return url + "&" + param;  	} -	 -	private void doFrontChannelLogOut(SLOInformationContainer sloContainer, -			HttpServletRequest httpReq, HttpServletResponse httpResp  -			) throws MOAIDException, MOADatabaseException { -		String nextOA = sloContainer.getNextFrontChannelOA(); -		if (MiscUtil.isNotEmpty(nextOA)) {					 -			SLOInformationImpl sloDescr = sloContainer.getFrontChannelOASessionDescripten(nextOA); -			LogoutRequest sloReq = SingleLogOutBuilder.buildSLORequestMessage(sloDescr); -			String relayState = Random.nextRandom(); -			 -			AssertionStorage.getInstance().put(relayState, sloContainer); -			 -			sendFrontChannelSLOMessage(sloDescr.getServiceURL(), sloDescr.getBinding(),  -					sloReq, httpReq, httpResp, relayState); -			 -		} else { -			//send SLO response to SLO request issuer -			PVPTargetConfiguration pvpReq = sloContainer.getSloRequest(); -			MOARequest samlReq = (MOARequest) pvpReq.getRequest(); -			SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); -			LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, sloContainer.getSloFailedOAs()); -			sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); -								 -		}		 -	} -	 -	/** -	 * @param serviceURL -	 * @param binding -	 * @param sloReq -	 * @param httpReq -	 * @param httpResp -	 * @param relayState -	 */ -	private void sendFrontChannelSLOMessage(String serviceURL, String bindingType, -			RequestAbstractType sloReq, HttpServletRequest httpReq, -			HttpServletResponse httpResp, String relayState) throws MOAIDException { -		IEncoder binding = null; -		if (bindingType.equals( -				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { -			binding = new RedirectBinding(); -						 -		} else if (bindingType.equals( -				SAMLConstants.SAML2_POST_BINDING_URI)) { -			binding = new PostBinding(); -			 -		} - -		if (binding == null) { -			throw new BindingNotSupportedException(bindingType); -		} -		 -		try { -			binding.encodeRequest(httpReq, httpResp, sloReq,  -					serviceURL, relayState); -			 -		} catch (MessageEncodingException e) { -			Logger.error("Message Encoding exception", e); -			throw new MOAIDException("pvp2.01", null, e); -			 -		} catch (SecurityException e) { -			Logger.error("Security exception", e); -			throw new MOAIDException("pvp2.01", null, e); - -		} -		 -	} - -	private void sendFrontChannelSLOMessage(SingleLogoutService consumerService,  -			LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp,  -			String relayState) throws MOAIDException { -		IEncoder binding = null; -		if (consumerService.getBinding().equals( -				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { -			binding = new RedirectBinding(); -						 -		} else if (consumerService.getBinding().equals( -				SAMLConstants.SAML2_POST_BINDING_URI)) { -			binding = new PostBinding(); -			 -		} - -		if (binding == null) { -			throw new BindingNotSupportedException(consumerService.getBinding()); -		} -		 -		try { -			binding.encodeRespone(req, resp, sloResp,  -					consumerService.getLocation(), relayState); -			 -		} catch (MessageEncodingException e) { -			Logger.error("Message Encoding exception", e); -			throw new MOAIDException("pvp2.01", null, e); -			 -		} catch (SecurityException e) { -			Logger.error("Security exception", e); -			throw new MOAIDException("pvp2.01", null, e); - -		} -		 -	}	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java index 8691667f0..4d353ffcd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/ArtifactBinding.java @@ -102,7 +102,7 @@ public class ArtifactBinding implements IDecoder, IEncoder {  	}  	public InboundMessageInterface decode(HttpServletRequest req, -			HttpServletResponse resp) throws MessageDecodingException, +			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,  			SecurityException {  		return null; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java index fb17c02b8..6619876dc 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/IDecoder.java @@ -33,7 +33,7 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface  public interface IDecoder {  	public InboundMessageInterface decode(HttpServletRequest req,  -			HttpServletResponse resp) +			HttpServletResponse resp, boolean isSPEndPoint)  					throws MessageDecodingException, SecurityException, PVP2Exception;  	public boolean handleDecode(String action, HttpServletRequest req); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java index a2fe5c01b..7f73b1ed7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java @@ -139,7 +139,7 @@ public class PostBinding implements IDecoder, IEncoder {  	}  	public InboundMessageInterface decode(HttpServletRequest req, -			HttpServletResponse resp) throws MessageDecodingException, +			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,  			SecurityException {  		HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool()); @@ -152,39 +152,38 @@ public class PostBinding implements IDecoder, IEncoder {  		} catch (ConfigurationException e) {  			throw new SecurityException(e);  		} -		 -		decode.decode(messageContext);		 -				 +							  		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); -		InboundMessage msg = null; +		//set metadata descriptor type +		if (isSPEndPoint) +			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); +		else +			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); -		if (messageContext.getInboundMessage() instanceof RequestAbstractType) { -			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);			 -			 +		decode.decode(messageContext); +		 +		InboundMessage msg = null;		 +		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {			  			RequestAbstractType inboundMessage = (RequestAbstractType) messageContext  					.getInboundMessage();			  			msg = new MOARequest(inboundMessage, getSAML2BindingName()); -		} else if (messageContext.getInboundMessage() instanceof Response){ -			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); -			 -			Response inboundMessage = (Response) messageContext.getInboundMessage();			 +		} else if (messageContext.getInboundMessage() instanceof StatusResponseType){ +			StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();			  			msg = new MOAResponse(inboundMessage);  		} else  			//create empty container if request type is unknown  			msg = new InboundMessage(); -		 -		msg.setVerified(false); -		 -		decode.decode(messageContext); +				  		if (messageContext.getPeerEntityMetadata() != null)  			msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());  		else  			Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer()); -				 +		 +		msg.setVerified(false);  		msg.setRelayState(messageContext.getRelayState());  		return msg; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java index 8fba6cde0..26f6f3a62 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/RedirectBinding.java @@ -129,7 +129,7 @@ public class RedirectBinding implements IDecoder, IEncoder {  	}  	public InboundMessageInterface decode(HttpServletRequest req, -			HttpServletResponse resp) throws MessageDecodingException, +			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,  			SecurityException {  		HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder( @@ -146,8 +146,6 @@ public class RedirectBinding implements IDecoder, IEncoder {  		BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>();  		messageContext  				.setInboundMessageTransport(new HttpServletRequestAdapter(req)); - -		decode.decode(messageContext);  		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); @@ -161,36 +159,39 @@ public class RedirectBinding implements IDecoder, IEncoder {  				policy);		  		messageContext.setSecurityPolicyResolver(resolver); -		InboundMessage msg = null; -		 -		if (messageContext.getInboundMessage() instanceof RequestAbstractType) { +		//set metadata descriptor type +		if (isSPEndPoint) +			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); +		else  			messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME); -			 +		 +		decode.decode(messageContext); + +		//check signature +		signatureRule.evaluate(messageContext);		 + +		InboundMessage msg = null; +		if (messageContext.getInboundMessage() instanceof RequestAbstractType) {			  			RequestAbstractType inboundMessage = (RequestAbstractType) messageContext  					.getInboundMessage();			  			msg = new MOARequest(inboundMessage, getSAML2BindingName()); -		} else if (messageContext.getInboundMessage() instanceof Response){ -			messageContext.setPeerEntityRole(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); -			 -			Response inboundMessage = (Response) messageContext.getInboundMessage();			 +		} else if (messageContext.getInboundMessage() instanceof StatusResponseType){ +			StatusResponseType inboundMessage = (StatusResponseType) messageContext.getInboundMessage();			  			msg = new MOAResponse(inboundMessage);  		} else   			//create empty container if request type is unknown  			msg = new InboundMessage(); -		signatureRule.evaluate(messageContext);		 -		msg.setVerified(true); - -		decode.decode(messageContext);  		if (messageContext.getPeerEntityMetadata() != null)  			msg.setEntityID(messageContext.getPeerEntityMetadata().getEntityID());  		else  			Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer()); +		msg.setVerified(true);  		msg.setRelayState(messageContext.getRelayState());  		return msg; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java index 75332cfea..f0eafe272 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java @@ -59,7 +59,7 @@ import at.gv.egovernment.moa.logging.Logger;  public class SoapBinding implements IDecoder, IEncoder {  	public InboundMessageInterface decode(HttpServletRequest req, -			HttpServletResponse resp) throws MessageDecodingException, +			HttpServletResponse resp, boolean isSPEndPoint) throws MessageDecodingException,  			SecurityException, PVP2Exception {  		HTTPSOAP11Decoder soapDecoder = new HTTPSOAP11Decoder(new BasicParserPool());  		BasicSAMLMessageContext<SAMLObject, ?, ?> messageContext =  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..eeb1dd104 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java @@ -22,30 +22,53 @@   */  package at.gv.egovernment.moa.id.protocols.pvp2x.builder; +import java.security.NoSuchAlgorithmException;  import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +  import org.joda.time.DateTime; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator;  import org.opensaml.common.xml.SAMLConstants;  import org.opensaml.saml2.core.Issuer;  import org.opensaml.saml2.core.LogoutRequest;  import org.opensaml.saml2.core.LogoutResponse;  import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.RequestAbstractType;  import org.opensaml.saml2.core.Status;  import org.opensaml.saml2.core.StatusCode;  import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.EntityDescriptor;  import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.SSODescriptor;  import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;  import org.opensaml.saml2.metadata.provider.MetadataProviderException; +import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.x509.X509Credential; +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.data.SLOInformationContainer;  import at.gv.egovernment.moa.id.data.SLOInformationImpl; +import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; +import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.logging.Logger; @@ -56,9 +79,141 @@ import at.gv.egovernment.moa.logging.Logger;   */  public class SingleLogOutBuilder { -	public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException { +	public static void checkStatusCode(SLOInformationContainer sloContainer, LogoutResponse logOutResp) { +		Status status = logOutResp.getStatus();				 +		if (!status.getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { +			String message = " Message: "; +			if (status.getStatusMessage() != null)  +				message += status.getStatusMessage().getMessage(); +			Logger.warn("Single LogOut for OA " + logOutResp.getIssuer().getValue() +					+ " FAILED. (ResponseCode: " + status.getStatusCode().getValue() +					+ message + ")"); +			sloContainer.putFailedOA(logOutResp.getIssuer().getValue()); +			 +		} else +			sloContainer.removeFrontChannelOA(logOutResp.getIssuer().getValue()); +			Logger.debug("Single LogOut for OA " + logOutResp.getIssuer().getValue() + " SUCCESS"); +		 +	} +		 +	/** +	 * @param serviceURL +	 * @param binding +	 * @param sloReq +	 * @param httpReq +	 * @param httpResp +	 * @param relayState +	 * @return  +	 */ +	public static String getFrontChannelSLOMessageURL(String serviceURL, String bindingType, +			RequestAbstractType sloReq, HttpServletRequest httpReq, +			HttpServletResponse httpResp, String relayState) throws MOAIDException { +		 +		try { +			X509Credential credentials = CredentialProvider +					.getIDPAssertionSigningCredential(); + +			Logger.debug("create SAML RedirectBinding response"); +			 +			MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();			 +			BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); +			SingleLogoutService service = new SingleLogoutServiceBuilder() +					.buildObject(); +			service.setBinding(SAMLConstants.SAML2_REDIRECT_BINDING_URI); +			service.setLocation(serviceURL); +			context.setOutboundSAMLMessageSigningCredential(credentials); +			context.setPeerEntityEndpoint(service); +			context.setOutboundSAMLMessage(sloReq); +			context.setRelayState(relayState); + +			encoder.encode(context); +			 +			return encoder.getRedirectURL(); +			 +		} catch (MessageEncodingException e) { +			Logger.error("Message Encoding exception", e); +			throw new MOAIDException("pvp2.01", null, e); +			 +		}		 +	} + +	public static String getFrontChannelSLOMessageURL(SingleLogoutService service, +			StatusResponseType sloResp, HttpServletRequest httpReq, +			HttpServletResponse httpResp, String relayState) throws MOAIDException { +		 +		try { +			X509Credential credentials = CredentialProvider +					.getIDPAssertionSigningCredential(); + +			Logger.debug("create SAML RedirectBinding response"); +			 +			MOAStringRedirectDeflateEncoder encoder = new MOAStringRedirectDeflateEncoder();			 +			BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); +			context.setOutboundSAMLMessageSigningCredential(credentials); +			context.setPeerEntityEndpoint(service); +			context.setOutboundSAMLMessage(sloResp); +			context.setRelayState(relayState); + +			encoder.encode(context); +			 +			return encoder.getRedirectURL(); +			 +		} catch (MessageEncodingException e) { +			Logger.error("Message Encoding exception", e); +			throw new MOAIDException("pvp2.01", null, e); +			 +		}		 +	} +	 +	public static void sendFrontChannelSLOMessage(SingleLogoutService consumerService,  +			LogoutResponse sloResp, HttpServletRequest req, HttpServletResponse resp,  +			String relayState) throws MOAIDException { +		IEncoder binding = null; +		if (consumerService.getBinding().equals( +				SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { +			binding = new RedirectBinding(); +						 +		} else if (consumerService.getBinding().equals( +				SAMLConstants.SAML2_POST_BINDING_URI)) { +			binding = new PostBinding(); +			 +		} + +		if (binding == null) { +			throw new BindingNotSupportedException(consumerService.getBinding()); +		} +		 +		try { +			binding.encodeRespone(req, resp, sloResp,  +					consumerService.getLocation(), relayState); +			 +		} catch (MessageEncodingException e) { +			Logger.error("Message Encoding exception", e); +			throw new MOAIDException("pvp2.01", null, e); +			 +		} catch (SecurityException e) { +			Logger.error("Security exception", e); +			throw new MOAIDException("pvp2.01", null, e); + +		}		 +	} +	 +	 +	public static LogoutRequest buildSLORequestMessage(SLOInformationImpl sloInfo) throws ConfigurationException, MOAIDException {  		LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class); +		SecureRandomIdentifierGenerator gen; +		try { +			gen = new SecureRandomIdentifierGenerator(); +			sloReq.setID(gen.generateIdentifier()); +			 +		} catch (NoSuchAlgorithmException e) { +			Logger.error("Internal server error", e); +			throw new AuthenticationException("pvp2.13", new Object[]{}); +			 +		}			 + +		  		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		  		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath());  		issuer.setFormat(NameID.ENTITY); @@ -75,14 +230,9 @@ public class SingleLogOutBuilder {  		return sloReq;		  	} -	public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException { -		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		 -		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		 -		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); -		issuer.setFormat(NameID.ENTITY); -		sloResp.setIssuer(issuer);		 -		sloResp.setIssueInstant(new DateTime());		 -		sloResp.setDestination(sloService.getLocation());		 +	public static LogoutResponse buildSLOErrorResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException { +		LogoutResponse sloResp = buildBasicResponse(sloService, spRequest); +		  		Status status = SAML2Utils.createSAMLObject(Status.class);  		StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class);  		StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); @@ -94,14 +244,8 @@ public class SingleLogOutBuilder {  		return sloResp;  	} -	public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws ConfigurationException {		 -		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		 -		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		 -		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); -		issuer.setFormat(NameID.ENTITY); -		sloResp.setIssuer(issuer);		 -		sloResp.setIssueInstant(new DateTime());		 -		sloResp.setDestination(sloService.getLocation()); +	public static LogoutResponse buildSLOResponseMessage(SingleLogoutService sloService, PVPTargetConfiguration spRequest, List<String> failedOAs) throws MOAIDException {		 +		LogoutResponse sloResp = buildBasicResponse(sloService, spRequest);  		Status status;  		if (failedOAs == null || failedOAs.size() == 0) { @@ -122,10 +266,41 @@ public class SingleLogOutBuilder {  	} +	private static LogoutResponse buildBasicResponse(SingleLogoutService sloService, PVPTargetConfiguration spRequest) throws ConfigurationException, MOAIDException { +		LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class);		 +		Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);		 +		issuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); +		issuer.setFormat(NameID.ENTITY); +		sloResp.setIssuer(issuer);		 +		sloResp.setIssueInstant(new DateTime());		 +		sloResp.setDestination(sloService.getLocation()); +		 +		SecureRandomIdentifierGenerator gen; +		try { +			gen = new SecureRandomIdentifierGenerator(); +			sloResp.setID(gen.generateIdentifier()); +			 +		} catch (NoSuchAlgorithmException e) { +			Logger.error("Internal server error", e); +			throw new AuthenticationException("pvp2.13", new Object[]{}); +			 +		}			 + +		if (spRequest.getRequest() instanceof MOARequest && +				((MOARequest)spRequest.getRequest()).getSamlRequest() instanceof LogoutRequest) { +			LogoutRequest sloReq =  (LogoutRequest) ((MOARequest)spRequest.getRequest()).getSamlRequest(); +			sloResp.setInResponseTo(sloReq.getID()); +			 +		} +		 +		return sloResp; +		 +	} +	  	public static SingleLogoutService getRequestSLODescriptor(String entityID) throws NOSLOServiceDescriptorException {  		try {  			EntityDescriptor entity = MOAMetadataProvider.getInstance().getEntityDescriptor(entityID); -			SPSSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS); +			SSODescriptor spsso = entity.getSPSSODescriptor(SAMLConstants.SAML20P_NS);  			SingleLogoutService sloService = null;			  			for (SingleLogoutService el : spsso.getSingleLogoutServices()) { @@ -139,19 +314,19 @@ public class SingleLogOutBuilder {  							)  					sloService = el; -				else  if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI) -						&& ( -								(sloService != null  -									&& !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI) -									&& !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))  -								|| sloService == null) -						) -					sloService = el;				 +//				else  if (el.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI) +//						&& ( +//								(sloService != null  +//									&& !sloService.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI) +//									&& !sloService.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI))  +//								|| sloService == null) +//						) +//					sloService = el;				  			}  			if (sloService == null) { -				Logger.error("Found no SLO ServiceDescriptor in Metadata");				 -				throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); +				Logger.error("Found no valid SLO ServiceDescriptor in Metadata");				 +				throw new NOSLOServiceDescriptorException("NO valid SLO ServiceDescriptor", null);  			}			  			return sloService; @@ -173,14 +348,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/protocols/pvp2x/config/PVPConfiguration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java index 255fba093..d3a9ad3e7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/config/PVPConfiguration.java @@ -33,7 +33,6 @@ import java.util.Properties;  import java.util.jar.Attributes;  import java.util.jar.Manifest; -import org.opensaml.Configuration;  import org.opensaml.saml2.metadata.Company;  import org.opensaml.saml2.metadata.ContactPerson;  import org.opensaml.saml2.metadata.ContactPersonTypeEnumeration; @@ -46,7 +45,6 @@ import org.opensaml.saml2.metadata.OrganizationName;  import org.opensaml.saml2.metadata.OrganizationURL;  import org.opensaml.saml2.metadata.SurName;  import org.opensaml.saml2.metadata.TelephoneNumber; -import org.opensaml.xml.security.SecurityConfiguration;  import at.gv.egovernment.moa.id.commons.db.dao.config.Contact;  import at.gv.egovernment.moa.id.commons.db.dao.config.OAPVP2; @@ -71,10 +69,12 @@ public class PVPConfiguration {  	}  	public static final String PVP2_METADATA = 	"/pvp2/metadata"; -	public static final String PVP2_REDIRECT = 	"/pvp2/redirect"; -	public static final String PVP2_POST = 		"/pvp2/post"; -	public static final String PVP2_SOAP = 		"/pvp2/soap"; -	public static final String PVP2_ATTRIBUTEQUERY = "/pvp2/attributequery"; +	public static final String PVP2_IDP_REDIRECT = 	"/pvp2/redirect"; +	public static final String PVP2_IDP_POST = 		"/pvp2/post"; +	public static final String PVP2_IDP_SOAP = 		"/pvp2/soap"; +	public static final String PVP2_IDP_ATTRIBUTEQUERY = "/pvp2/attributequery"; +	public static final String PVP2_SP_REDIRECT = 	"/pvp2/sp/redirect"; +	public static final String PVP2_SP_POST = 		"/pvp2/sp/post";  	public static final String PVP_CONFIG_FILE = "pvp2config.properties"; @@ -143,22 +143,30 @@ public class PVPConfiguration {  		return publicPath;  	} -	public String getIDPSSOPostService() throws ConfigurationException { -		return getIDPPublicPath() + PVP2_POST; +	public String getSPSSOPostService() throws ConfigurationException { +		return getIDPPublicPath() + PVP2_SP_POST;  	} -	public String getIDPSSOSOAPService() throws ConfigurationException { -		return getIDPPublicPath() + PVP2_SOAP; +	public String getSPSSORedirectService() throws ConfigurationException { +		return getIDPPublicPath() + PVP2_SP_REDIRECT;  	} -	public String getIDPAttributeQueryService() throws ConfigurationException { -		return getIDPPublicPath() + PVP2_ATTRIBUTEQUERY; +	public String getIDPSSOPostService() throws ConfigurationException { +		return getIDPPublicPath() + PVP2_IDP_POST;  	} -	 +  	public String getIDPSSORedirectService() throws ConfigurationException { -		return getIDPPublicPath() + PVP2_REDIRECT; +		return getIDPPublicPath() + PVP2_IDP_REDIRECT;  	} +	public String getIDPSSOSOAPService() throws ConfigurationException { +		return getIDPPublicPath() + PVP2_IDP_SOAP; +	} +	 +	public String getIDPAttributeQueryService() throws ConfigurationException { +		return getIDPPublicPath() + PVP2_IDP_ATTRIBUTEQUERY; +	} +		  	public String getIDPSSOMetadataService() throws ConfigurationException {  		return getIDPPublicPath() + PVP2_METADATA;  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java index 870273cf3..f2512b122 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/messages/MOAResponse.java @@ -23,7 +23,7 @@  package at.gv.egovernment.moa.id.protocols.pvp2x.messages;  import org.opensaml.Configuration; -import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.xml.io.Unmarshaller;  import org.opensaml.xml.io.UnmarshallerFactory;  import org.opensaml.xml.io.UnmarshallingException; @@ -35,16 +35,16 @@ public class MOAResponse extends InboundMessage {  	private static final long serialVersionUID = -1133012928130138501L; -	public MOAResponse(Response response) { +	public MOAResponse(StatusResponseType response) {  		setSAMLMessage(response.getDOM());  	} -	public Response getResponse() {		 +	public StatusResponseType getResponse() {		  		UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory();  		Unmarshaller unmashaller = unmarshallerFactory.getUnmarshaller(getInboundMessage());  		try { -			return (Response) unmashaller.unmarshall(getInboundMessage()); +			return (StatusResponseType) unmashaller.unmarshall(getInboundMessage());  		} catch (UnmarshallingException e) {  			Logger.warn("AuthnResponse Unmarshaller error", e); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java index 61b481447..ee0088576 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java @@ -28,6 +28,7 @@ import org.opensaml.saml2.core.Assertion;  import org.opensaml.saml2.core.AuthnContextClassRef;  import org.opensaml.saml2.core.AuthnStatement;  import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.core.Subject;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption; @@ -38,15 +39,16 @@ public class AssertionAttributeExtractor {  	private Assertion assertion = null; -	public AssertionAttributeExtractor(Response samlResponse) throws AssertionAttributeExtractorExeption { -		if (samlResponse != null) { -			if (samlResponse.getAssertions().size() == 0)  +	public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption { +		if (samlResponse != null && samlResponse instanceof Response) { +			List<Assertion> assertions = ((Response) samlResponse).getAssertions();			 +			if (assertions.size() == 0)   				throw new AssertionAttributeExtractorExeption("Assertion"); -			else if (samlResponse.getAssertions().size() > 1) +			else if (assertions.size() > 1)  				Logger.warn("Found more then ONE PVP2.1 assertions. Only the First is used."); -			assertion = samlResponse.getAssertions().get(0);			 +			assertion = assertions.get(0);			  		} else   			throw new AssertionAttributeExtractorExeption();		 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java index 6388042d9..3be5df917 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java @@ -32,6 +32,7 @@ import org.opensaml.saml2.core.EncryptedAssertion;  import org.opensaml.saml2.core.RequestAbstractType;  import org.opensaml.saml2.core.Response;  import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.encryption.Decrypter;  import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;  import org.opensaml.saml2.metadata.IDPSSODescriptor; @@ -76,7 +77,7 @@ public class SAMLVerificationEngine {  	} -	public void verifyResponse(Response samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception { +	public void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {  		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();  		try {  		    profileValidator.validate(samlObj.getSignature()); diff --git a/id/server/idserverlib/src/main/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/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index c8cca157d..9aab22ef5 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -243,9 +243,9 @@ pvp2.16=Fehler beim verschl\u00FCsseln der PVP2 Assertion  pvp2.17=Der QAA Level {0} entspricht nicht dem angeforderten QAA Level {1}
  pvp2.18=Es konnten nicht alle Single Sign-On Sessions beendet werden.
  pvp2.19=Der Single LogOut Vorgang musste wegen eines unkorregierbaren Fehler abgebrochen werden. 
 -pvp2.20=Für die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
 +pvp2.20=F\u00FCr die im Request angegebene EntityID konnten keine g\u00FCltigen Metadaten gefunden werden.
  pvp2.21=Die Signature des Requests konnte nicht g\u00FCltig validiert werden.  
 -pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler={0}).
 +pvp2.22=Der Request konnte nicht g\u00FCltig validiert werden (Fehler\={0}).
  oauth20.01=Fehlerhafte redirect url
  oauth20.02=Fehlender Parameter "{0}"
 @@ -256,3 +256,6 @@ oauth20.06=Die angegebene OA kann nicht verwendet werden  oauth20.07=Angeforderter grant_type ist nicht erlaubt
  oauth20.08=Nicht berechtigt f\u00FCr Token-Request
  oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{0}"
 +
 +slo.00=Sie konnten erfolgreich von allen Online-Applikation abgemeldet werden.
 +slo.01=Sie konnten NICHT erfolgreich von allen Online-Applikationen abgemeldet werden\!<BR>Bitte schlie\u00DFen Sie aus sicherheitsgr\u00FCnden Ihren Browser.
 diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html new file mode 100644 index 000000000..a652855c4 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html @@ -0,0 +1,438 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +  <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> +   +   <!-- MOA-ID 2.x BKUSelection Layout CSS -->                +    <style type="text/css"> +			@media screen and (min-width: 650px) { +			 +				body { +					margin:0; +					padding:0; +					color : #000; +					background-color : #fff; +			  	text-align: center; +			  	background-color: #6B7B8B; +				} +   +			  #page { +			    display: block; +			    border: 2px solid rgb(0,0,0); +			    width: 650px; +			    height: 460px; +			    margin: 0 auto; +			    margin-top: 5%; +			    position: relative; +			    border-radius: 25px; +			    background: rgb(255,255,255); +			  } +			   +			  #page1 { +			    text-align: center; +			  } +			   +			  #main { +			    /*	clear:both; */ +				  position:relative; +			    margin: 0 auto; +			    width: 250px; +			    text-align: center; +			  } +			   +			  .OA_header { +			/*	  background-color: white;*/ +			    font-size: 20pt; +			    margin-bottom: 25px; +			    margin-top: 25px; +			  } +			 +			  #leftcontent { +			    /*float:left; */ +				  width:250px; +				  margin-bottom: 25px; +			    text-align: left; +			    /*border: 1px solid rgb(0,0,0);*/ +			  } +			 +			  #leftcontent { +				 width: 300px; +				 margin-top: 30px; +			  } +       +        h2#tabheader{ +				  font-size: 1.1em;  +          padding-left: 2%; +          padding-right: 2%; +          position: relative; +			  } +        		   +			  .setAssertionButton_full { +			  	background: #efefef; +				  cursor: pointer; +				  margin-top: 15px; +			    width: 100px; +			    height: 30px +			  } +			 +			  #leftbutton  { +				 width: 30%;  +				 float:left;  +				 margin-left: 40px; +			  } +			 +			  #rightbutton { +				 width: 30%;  +				 float:right;  +				 margin-right: 45px;  +				 text-align: right; +			  } +         +        button { +          height: 25px; +          width: 75px; +          margin-bottom: 10px; +        } +         +       #validation { +        position: absolute; +        bottom: 0px; +        margin-left: 270px; +        padding-bottom: 10px; +      } +			 +			} + +      @media screen and (max-width: 205px) { +        #localBKU p { +          font-size: 0.6em; +        }  +         +        #localBKU input { +          font-size: 0.6em; +          min-width: 60px; +         /* max-width: 65px; */ +          min-height: 1.0em; +         /* border-radius: 5px; */ +        } +         +      } + +      @media screen and (max-width: 249px) and (min-width: 206px) { +        #localBKU p { +          font-size: 0.7em; +        }  +         +        #localBKU input { +          font-size: 0.7em; +          min-width: 70px; +       /*    max-width: 75px;    */ +          min-height: 0.95em; +        /*  border-radius: 6px;    */ +        } +          +      } + +      @media screen and (max-width: 299px) and (min-width: 250px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +       /*    max-width: 75px;      */ +      /*    border-radius: 6px;  */ +        } + +      } + +      @media screen and (max-width: 399px) and (min-width: 300px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 75px;     */ +      /*    border-radius: 6px;       */ +        } + +      } +       +      @media screen and (max-width: 649px) and (min-width: 400px) { +        #localBKU p { +          font-size: 0.9em; +        }  +         +        #localBKU input { +          font-size: 0.8em; +          min-width: 70px; +      /*     max-width: 80px;       */ +     /*     border-radius: 6px;          */ +        } + +      } + + +			 +			@media screen and (max-width: 649px) { +				 +        body { +					margin:0; +					padding:0; +					color : #000; +			  	text-align: center; +          font-size: 100%; +			  	background-color: #MAIN_BACKGOUNDCOLOR#; +				} +        				 +			  #page { +			     visibility: hidden; +			     margin-top: 0%; +			  } +			   +			  #page1 { +			    visibility: hidden; +			  } +			   +			  #main { +			    visibility: hidden; +			  } +         +        #validation { +          visibility: hidden; +          display: none; +        } +			   +			  .OA_header { +			    margin-bottom: 0px; +			    margin-top: 0px; +			    font-size: 0pt; +			    visibility: hidden; +			  } +			 +			  #leftcontent { +			    visibility: visible; +			    margin-bottom: 0px; +			    text-align: left; +			    border:none; +          vertical-align: middle; +          min-height: 173px; +          min-width: 204px; +           +			  } +         +        input[type=button] { +/*          height: 11%;  */ +          width: 70%; +        } +			} +			       +			* { +				margin: 0; +				padding: 0; +        font-family: #FONTTYPE#; +			} +							      			 +			#selectArea { +				padding-top: 10px; +				padding-bottom: 55px; +				padding-left: 10px; +			} +			 +			.setAssertionButton { +				background: #efefef; +				cursor: pointer; +				margin-top: 15px; +			  width: 70px; +			  height: 25px; +			} +			 +			#leftbutton  { +				width: 35%;  +				float:left;  +				margin-left: 15px; +			} +			 +			#rightbutton { +				width: 35%;  +				float:right;  +				margin-right: 25px;  +				text-align: right; +			} + +/*		input[type=button], .sendButton { +				background: #BUTTON_BACKGROUNDCOLOR#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;  */ +/*				cursor: pointer; +/*        box-shadow: 3px 3px 3px #222222;  */ +/*			} +			 +/*      button:hover, button:focus, button:active,  +      .sendButton:hover , .sendButton:focus, .sendButton:active, +      #mandateCheckBox:hover, #mandateCheckBox:focus, #mandateCheckBox:active { +				background: #BUTTON_BACKGROUNDCOLOR_FOCUS#; +        color: #BUTTON_COLOR#; +/*				border:1px solid #000;                */ +/*				cursor: pointer; +/*        box-shadow: -1px -1px 3px #222222;  */ +/*			} +       +*/       +			input { +				/*border:1px solid #000;*/ +				cursor: pointer; +			} +       +      #localBKU input { +/*        color: #BUTTON_COLOR#;  */ +        border: 0px; +        display: inline-block; +         +      } +			 +      #localBKU input:hover, #localBKU input:focus, #localBKU input:active { +        text-decoration: underline; +      } +       +			#installJava, #BrowserNOK { +				clear:both; +				font-size:0.8em; +				padding:4px; +			} +						 +			.selectText{ +			 +			} +			 +			.selectTextHeader{ +			 +			} +			 +			.sendButton { +        width: 30%; +        margin-bottom: 1%;	 +			} +			 +			#leftcontent a { +				text-decoration:none;  +				color: #000; +			/*	display:block;*/ +				padding:4px;	 +			} +			 +			#leftcontent a:hover, #leftcontent a:focus, #leftcontent a:active { +				text-decoration:underline; +				color: #000;	 +			} +						 +			.infobutton { +				background-color: #005a00; +				color: white; +				font-family: serif; +				text-decoration: none; +				padding-top: 2px; +				padding-right: 4px; +				padding-bottom: 2px; +				padding-left: 4px; +				font-weight: bold; +			} +			 +			.hell { +				background-color : #MAIN_BACKGOUNDCOLOR#; +        color: #MAIN_COLOR#;	 +			} +			 +			.dunkel { +				background-color: #HEADER_BACKGROUNDCOLOR#; +        color: #HEADER_COLOR#; +			} +			       +			.main_header { +			   color: black; +			    font-size: 32pt; +			    position: absolute; +			    right: 10%; +			    top: 40px; +				 +			} +       +     	#alert { +		    margin: 100px 250px; +		    font-family: Verdana, Arial, Helvetica, sans-serif; +		    font-size: 14px; +		    font-weight: normal; +		    color: red; +	    } +	 +	    .reqframe { +		    /*display: none;*/ +        visibility: hidden; +		   +	    } +      			                         +    </style>  + + +  <title>Single LogOut Vorgang ... </title> +</head> + +<body> +  <noscript> +		<p> +			<strong>Note:</strong> Since your browser does not support +			JavaScript, you must press the Continue button once to proceed. +		</p> +	</noscript> + +  <div id="page"> +		<div id="page1" class="case selected-case" role="main"> +			<h2 class="OA_header" role="heading">MOA-ID Single LogOut Information</h2> +			<div id="main"> +				<div id="leftcontent" class="hell" role="application"> +           +          #if($errorMsg) +	         <div class="alert"> +		        <p>$errorMsg</p>  +	         </div>	 +	        #end + +	        #if($successMsg) +	         <div> +		        <p>$successMsg</p>  +	         </div>	 +	        #end + +	        #if($redirectURLs) +		        <div> +			       <p> +				        Sie werden von allen Online-Applikationen abgemeldet. <br> +				        Dieser Vorgang kann einige Zeit in Anspruch nehmen. +			       </p> +		       </div> +	       #end +           +				</div> +			</div> +		</div> +		<div id="validation"> +			<a href="http://validator.w3.org/check?uri="> <img +				style="border: 0; width: 88px; height: 31px" +				src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" /> +			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img +				style="border: 0; width: 88px; height: 31px" +				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				alt="CSS ist valide!" /> +			</a> +		</div> +	</div> + + +  #foreach( $el in $redirectURLs ) +	   <iframe src=$el class="reqframe"></iframe> +  #end +   +</body> +</html>
\ No newline at end of file diff --git a/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT-classes.jar b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT-classes.jarBinary files differ new file mode 100644 index 000000000..d338cb3d6 --- /dev/null +++ b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT-classes.jar diff --git a/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.jar b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.jarBinary files differ new file mode 100644 index 000000000..411ba64b7 --- /dev/null +++ b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.jar diff --git a/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.pom b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.pom new file mode 100644 index 000000000..519d70468 --- /dev/null +++ b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.pom @@ -0,0 +1,154 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +  <modelVersion>4.0.0</modelVersion> +  <groupId>eu.stork</groupId> +  <artifactId>DocumentService</artifactId> +  <version>0.0.1-SNAPSHOT</version> +  <name>DocumentService</name> +  <description>DTL webservice</description> +  <dependencies> +  <!-- log4j --> +		<dependency> +			<groupId>log4j</groupId> +			<artifactId>log4j</artifactId> +			<version>1.2.17</version> +			<exclusions> +				<exclusion> +					<groupId>javax.jms</groupId> +					<artifactId>jms</artifactId> +				</exclusion> +				<exclusion> +					<groupId>com.sun.jdmk</groupId> +					<artifactId>jmxtools</artifactId> +				</exclusion> +				<exclusion> +					<groupId>com.sun.jmx</groupId> +					<artifactId>jmxri</artifactId> +				</exclusion> +				<exclusion> +					<artifactId>mail</artifactId> +					<groupId>javax.mail</groupId> +				</exclusion> +			</exclusions> +		</dependency> +   +   +  		<dependency> +			<groupId>junit</groupId> +			<artifactId>junit</artifactId> +			<version>4.1</version> +		</dependency>      +		<dependency> +			<groupId>mysql</groupId> +			<artifactId>mysql-connector-java</artifactId> +			<version>5.1.27</version> +		</dependency> +		<dependency> +			<groupId>org.glassfish.jersey.core</groupId> +			<artifactId>jersey-common</artifactId> +			<version>2.0-m03</version> +		</dependency> +               +		<dependency> +			<groupId>org.apache.axis</groupId> +			<artifactId>axis</artifactId> +			<version>1.4</version> +		</dependency> +<!-- 		<dependency> --> +<!-- 			<groupId>com.sun.org.apache</groupId> --> +<!-- 			<artifactId>jaxp-ri</artifactId> --> +<!-- 			<version>1.4</version> --> +<!-- 		</dependency> --> +		<dependency> +	        <groupId>com.sun.xml.ws</groupId> +	        <artifactId>jaxws-tools</artifactId> +	        <version>2.2.8</version> +      	</dependency> +      	<dependency> +    	<groupId>com.sun.xml.ws</groupId> +		    <artifactId>jaxws-rt</artifactId> +		    <version>2.2.8</version> +		    <scope>provided</scope> +		</dependency>	 +		<dependency> +			<groupId>javax.xml</groupId> +			<artifactId>jaxrpc-api</artifactId> +			<version>1.1</version> +		</dependency> +		<!-- Bouncy Castle --> +		<dependency> +			<groupId>org.bouncycastle</groupId> +			<artifactId>bcprov-jdk16</artifactId> +			<version>1.46</version> +		</dependency> +		<dependency> +			<groupId>com.sun.xml.security</groupId> +			<artifactId>xml-security-impl</artifactId> +			<version>1.0</version> +		</dependency> +		<dependency> +	<groupId>org.jvnet</groupId> +	<artifactId>mimepull</artifactId> +	<version>1.6</version> +</dependency> +<dependency> +            <groupId>eu.stork</groupId> +            <artifactId>SamlEngine</artifactId> +            <version>1.4.0</version> +        </dependency> + +<!-- 		<dependency> --> +<!-- 			<groupId>MOA.id.server</groupId> --> +<!-- 			<artifactId>moa-id-lib</artifactId> --> +<!-- 			<version>2.1.0-RC1</version> --> +<!-- 			<classifier>classes</classifier> --> +<!-- 		</dependency> --> +  </dependencies> +  <build> +  <finalName>DocumentService</finalName> +    <sourceDirectory>src</sourceDirectory> +    <resources> +      <resource> +        <directory>src</directory> +        <excludes> +          <exclude>**/*.java</exclude> +        </excludes> +      </resource> +    </resources> +    <plugins> +      <plugin> +        <artifactId>maven-compiler-plugin</artifactId> +        <version>3.1</version> +        <configuration> +          <source>1.7</source> +          <target>1.7</target> +        </configuration> +      </plugin> +      <plugin> +        <artifactId>maven-war-plugin</artifactId> +        <version>2.3</version> +        <configuration> +          <warSourceDirectory>WebContent</warSourceDirectory> +          <failOnMissingWebXml>false</failOnMissingWebXml> +          <attachClasses>true</attachClasses> +        </configuration> +      </plugin> +        <plugin> +            <groupId>org.apache.maven.plugins</groupId> +            <artifactId>maven-jar-plugin</artifactId> +            <configuration> +                <archive> +                    <addMavenDescriptor>true</addMavenDescriptor> +                </archive> +            </configuration> +            <executions> +                <execution> +                    <goals> +                        <goal>jar</goal> +                    </goals> +                </execution> +            </executions> +        </plugin> +    </plugins>     +  </build> +  <packaging>jar</packaging> +</project> diff --git a/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.war b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.warBinary files differ new file mode 100644 index 000000000..b6622a63c --- /dev/null +++ b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/DocumentService-0.0.1-SNAPSHOT.war diff --git a/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/maven-metadata-local.xml b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/maven-metadata-local.xml new file mode 100644 index 000000000..be8b41c9d --- /dev/null +++ b/repository/eu/stork/DocumentService/0.0.1-SNAPSHOT/maven-metadata-local.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<metadata modelVersion="1.1.0"> +  <groupId>eu.stork</groupId> +  <artifactId>DocumentService</artifactId> +  <version>0.0.1-SNAPSHOT</version> +  <versioning> +    <snapshot> +      <localCopy>true</localCopy> +    </snapshot> +    <lastUpdated>20140605160207</lastUpdated> +    <snapshotVersions> +      <snapshotVersion> +        <extension>jar</extension> +        <value>0.0.1-SNAPSHOT</value> +        <updated>20140605160207</updated> +      </snapshotVersion> +      <snapshotVersion> +        <extension>pom</extension> +        <value>0.0.1-SNAPSHOT</value> +        <updated>20140605160207</updated> +      </snapshotVersion> +      <snapshotVersion> +        <classifier>classes</classifier> +        <extension>jar</extension> +        <value>0.0.1-SNAPSHOT</value> +        <updated>20140605160137</updated> +      </snapshotVersion> +      <snapshotVersion> +        <extension>war</extension> +        <value>0.0.1-SNAPSHOT</value> +        <updated>20140605160137</updated> +      </snapshotVersion> +    </snapshotVersions> +  </versioning> +</metadata> diff --git a/repository/eu/stork/DocumentService/maven-metadata-local.xml b/repository/eu/stork/DocumentService/maven-metadata-local.xml new file mode 100644 index 000000000..325a76ecd --- /dev/null +++ b/repository/eu/stork/DocumentService/maven-metadata-local.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<metadata> +  <groupId>eu.stork</groupId> +  <artifactId>DocumentService</artifactId> +  <versioning> +    <versions> +      <version>0.0.1-SNAPSHOT</version> +    </versions> +    <lastUpdated>20140604172305</lastUpdated> +  </versioning> +</metadata> 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
 | 
