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