diff options
Diffstat (limited to 'id/oa')
7 files changed, 633 insertions, 6 deletions
| diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java index af1dd84be..d6d2b32da 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/Constants.java @@ -28,4 +28,10 @@ public class Constants {  	public static final String SERVLET_PVP2ASSERTION = "demoapplication";  	public static final String SESSION_PVP2REQUESTID = "pvp2requestid"; + +	public static final String SERVLET_PVPSINGLELOGOUT = "singlelogout"; + +	public static final String SESSION_NAMEID = "pvp2nameID"; + +	public static final String SESSION_NAMEIDFORMAT = "pvp2nameIDFormat";  } diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java index 4c9bc6d76..24ba26a59 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/BuildMetadata.java @@ -56,6 +56,7 @@ import org.opensaml.saml2.metadata.LocalizedString;  import org.opensaml.saml2.metadata.NameIDFormat;  import org.opensaml.saml2.metadata.SPSSODescriptor;  import org.opensaml.saml2.metadata.ServiceName; +import org.opensaml.saml2.metadata.SingleLogoutService;  import org.opensaml.saml2.metadata.impl.EncryptionMethodBuilder;  import org.opensaml.xml.encryption.EncryptionConstants;  import org.opensaml.xml.encryption.OAEPparams; @@ -238,10 +239,15 @@ public class BuildMetadata extends HttpServlet {  			postassertionConsumerService.setIndex(0);  			postassertionConsumerService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); -			postassertionConsumerService.setLocation(serviceURL + Constants.SERVLET_PVP2ASSERTION); -		 +			postassertionConsumerService.setLocation(serviceURL + Constants.SERVLET_PVP2ASSERTION);		  			spSSODescriptor.getAssertionConsumerServices().add(postassertionConsumerService); +			//set Single Log-Out service +			SingleLogoutService sloService =  SAML2Utils.createSAMLObject(SingleLogoutService.class); +			sloService.setBinding(SAMLConstants.SAML2_POST_BINDING_URI); +			sloService.setLocation(serviceURL + Constants.SERVLET_PVPSINGLELOGOUT); +			spSSODescriptor.getSingleLogoutServices().add(sloService); +			  			spSSODescriptor.addSupportedProtocol(SAMLConstants.SAML20P_NS);  			spEntityDescriptor.getRoleDescriptors().add(spSSODescriptor); diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java index dcd478864..cde9451a4 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/DemoApplication.java @@ -73,6 +73,7 @@ import org.opensaml.xml.signature.Signature;  import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine;  import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants;  import at.gv.egovernment.moa.id.demoOA.PVPConstants;  import at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean;  import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; @@ -223,14 +224,19 @@ public class DemoApplication extends HttpServlet {  									birthday = attributes.get(x).getAttributeValues().get(0).getDOM().getTextContent();  								}								  							} -						} +						}						 +						request.getSession().setAttribute(Constants.SESSION_NAMEIDFORMAT, +								saml2assertion.getSubject().getNameID().getFormat()); +						request.getSession().setAttribute(Constants.SESSION_NAMEID,  +								saml2assertion.getSubject().getNameID().getValue()); +						  					} -					 +										  					bean.setDateOfBirth(birthday);  					bean.setFamilyName(familyName);  					bean.setGivenName(givenName);  					bean.setLogin(true); -					 +										  					setAnser(request, response, bean);  					return; diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java new file mode 100644 index 000000000..c68ea9b1f --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/Index.java @@ -0,0 +1,335 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +import org.joda.time.DateTime; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.binding.decoding.HTTPPostDecoder; +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.LogoutResponse; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.Response; +import org.opensaml.saml2.core.Status; +import org.opensaml.saml2.core.StatusCode; +import org.opensaml.saml2.core.StatusResponseType; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.security.MetadataCredentialResolver; +import org.opensaml.security.MetadataCredentialResolverFactory; +import org.opensaml.security.MetadataCriteria; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.ws.transport.http.HttpServletRequestAdapter; +import org.opensaml.ws.transport.http.HttpServletResponseAdapter; +import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.security.CriteriaSet; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.criteria.EntityIDCriteria; +import org.opensaml.xml.security.criteria.UsageCriteria; +import org.opensaml.xml.security.keyinfo.BasicProviderKeyInfoCredentialResolver; +import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver; +import org.opensaml.xml.security.keyinfo.KeyInfoProvider; +import org.opensaml.xml.security.keyinfo.provider.DSAKeyValueProvider; +import org.opensaml.xml.security.keyinfo.provider.InlineX509DataProvider; +import org.opensaml.xml.security.keyinfo.provider.RSAKeyValueProvider; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.SignableXMLObject; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.impl.ExplicitKeySignatureTrustEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.ApplicationBean; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.gv.egovernment.moa.util.DOMUtils; +import at.iaik.commons.util.MiscUtil; + + +public class Index extends HttpServlet { + +	private static final long serialVersionUID = -2129228304760706063L; +	private static final Logger log = LoggerFactory +			.getLogger(Index.class);	 +	 +	 +	private void process(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { + +		 +		ApplicationBean bean = new ApplicationBean(); +		 +		 +		String method = request.getMethod(); +		HttpSession session = request.getSession(); +		if (session == null) { +			log.info("NO HTTP Session"); +			bean.setErrorMessage("NO HTTP session"); +			setAnser(request, response, bean); +			return; +		} +		 +		if (method.equals("POST")) {					 +			try { +				Configuration config = Configuration.getInstance(); +				 +				//Decode with HttpPost Binding +				HTTPPostDecoder decode = new HTTPPostDecoder(new BasicParserPool()); +				BasicSAMLMessageContext<Response, ?, ?> messageContext = new BasicSAMLMessageContext<Response, SAMLObject, SAMLObject>(); +				messageContext +					.setInboundMessageTransport(new HttpServletRequestAdapter( +							request)); +				decode.decode(messageContext); +							 +				SignableXMLObject samlResponse = (SignableXMLObject) messageContext.getInboundMessage(); +			 +				Signature sign = samlResponse.getSignature(); +				if (sign == null) { +					log.info("Only http POST Requests can be used"); +					bean.setErrorMessage("Only http POST Requests can be used"); +					setAnser(request, response, bean); +					return; +				} +				 +				//Validate Signature +				SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); +				profileValidator.validate(sign); +				 +				//Verify Signature +				List<KeyInfoProvider> keyInfoProvider = new ArrayList<KeyInfoProvider>(); +				keyInfoProvider.add(new DSAKeyValueProvider()); +				keyInfoProvider.add(new RSAKeyValueProvider()); +				keyInfoProvider.add(new InlineX509DataProvider()); + +				KeyInfoCredentialResolver keyInfoResolver = new BasicProviderKeyInfoCredentialResolver( +						keyInfoProvider); +				 +				MetadataCredentialResolverFactory credentialResolverFactory = MetadataCredentialResolverFactory.getFactory();     +				MetadataCredentialResolver credentialResolver = credentialResolverFactory.getInstance(config.getMetaDataProvier());   +				   +				CriteriaSet criteriaSet = new CriteriaSet();   +				criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS));   +				criteriaSet.add(new EntityIDCriteria(config.getPVP2IDPMetadataEntityName())); +				criteriaSet.add(new UsageCriteria(UsageType.SIGNING)); +				  				 +				ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credentialResolver, keyInfoResolver); +				trustEngine.validate(sign, criteriaSet); +				 +				log.info("PVP2 statusrequest or statusresponse is valid"); +				 +				 +				if (samlResponse instanceof LogoutResponse) { +				 +					LogoutResponse sloResp = (LogoutResponse) samlResponse;  +					 +					//set assertion +					org.w3c.dom.Document doc = SAML2Utils.asDOMDocument(samlResponse); +					String assertion = DOMUtils.serializeNode(doc);				 +					bean.setAssertion(assertion); +								 +					if (sloResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { + +						bean.setSuccessMessage("Der Single Log-Out Vorgang konnte erfolgreich durchgeführt werden."); +					 +						setAnser(request, response, bean); +						return; +										 +					} else { +						bean.setErrorMessage("Der Single Log-Out Vorgang war nicht erfolgreich.<br>Bitte schließen Sie aus sicherheitsgründen den Browser!"); +						setAnser(request, response, bean); +						return; +					 +					} +					 +				} else if (samlResponse instanceof LogoutRequest) { +					//invalidate user session +					request.getSession().invalidate(); +					 +					//build LogOutResponse +					LogoutResponse sloResp = SAML2Utils.createSAMLObject(LogoutResponse.class); +					SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); +					sloResp.setID(gen.generateIdentifier()); +					sloResp.setIssueInstant(new DateTime()); +					NameID name = SAML2Utils.createSAMLObject(NameID.class); +					Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); +					 +					String serviceURL = config.getPublicUrlPreFix(request); +					if (!serviceURL.endsWith("/")) +						serviceURL = serviceURL + "/"; +					name.setValue(serviceURL); +					issuer.setValue(serviceURL); +					issuer.setFormat(NameIDType.ENTITY); +					sloResp.setIssuer(issuer); +					 +					Status status = SAML2Utils.createSAMLObject(Status.class); +					sloResp.setStatus(status); +					StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); +					statusCode.setValue(StatusCode.SUCCESS_URI); +					status.setStatusCode(statusCode ); +					 +					String entityname = config.getPVP2IDPMetadataEntityName(); +					if (MiscUtil.isEmpty(entityname)) { +						log.info("No IDP EntityName configurated"); +						throw new ConfigurationException("No IDP EntityName configurated"); +					} +					 +					//get IDP metadata from metadataprovider +					HTTPMetadataProvider idpmetadata = config.getMetaDataProvier();			 +					EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); +					if (idpEntity == null) { +						log.info("IDP EntityName is not found in IDP Metadata"); +						throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); +					} +					 +					//select authentication-service url from metadata +					SingleLogoutService redirectEndpoint = null;   +					for (SingleLogoutService sss :  +							idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleLogoutServices()) { +						 +						//Get the service address for the binding you wish to use +						if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {  +							redirectEndpoint = sss;   +						}   +					} +					sloResp.setDestination(redirectEndpoint.getLocation()); +					 +					//sign authentication request +					KeyStore keyStore = config.getPVP2KeyStore(); +					X509Credential authcredential = new KeyStoreX509CredentialAdapter( +							keyStore,  +							config.getPVP2KeystoreAuthRequestKeyAlias(),  +							config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); + +					Signature signer = SAML2Utils.createSAMLObject(Signature.class); +					signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); +					signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); +					signer.setSigningCredential(authcredential); +					sloResp.setSignature(signer); + +					//generate Http-POST Binding message +					VelocityEngine engine = new VelocityEngine(); +					engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); +					engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); +					engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); +					engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); +					engine.setProperty("classpath.resource.loader.class", +							"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); +					engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, +							"org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); +					engine.init(); + +					HTTPPostEncoder encoder = new HTTPPostEncoder(engine, +							"templates/pvp_postbinding_template.html"); +					HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( +							response, true); +					BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); +					SingleSignOnService service = new SingleSignOnServiceBuilder() +							.buildObject(); +					service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); +					service.setLocation(redirectEndpoint.getLocation());; +					 +					context.setOutboundSAMLMessageSigningCredential(authcredential); +					context.setPeerEntityEndpoint(service); +					context.setOutboundSAMLMessage(sloResp); +					context.setOutboundMessageTransport(responseAdapter); +					context.setRelayState(messageContext.getRelayState()); +					 +					encoder.encode(context); +					 +				} else { +					bean.setErrorMessage("Kein gültiger LogOut Request oder LogOut Response"); +					setAnser(request, response, bean); +					return; +					 +				} +				 +				 +			} catch (Exception e) { +				log.warn("Internal error", e); +				bean.setErrorMessage("Internal Error: " + e.getMessage()); +				setAnser(request, response, bean); +				return; +			} +			 +		} else { +			bean.setErrorMessage("Die Demoapplikation unterstützt nur SAML2 POST-Binding."); +			setAnser(request, response, bean); +			return; +			 +		} +	}	 +	 +	private void setAnser(HttpServletRequest request, HttpServletResponse response, ApplicationBean answersBean) throws ServletException, IOException { +        // store bean in session +        request.setAttribute("answers", answersBean); + +        // you now can forward to some view, for example some results.jsp +        request.getRequestDispatcher("demoapp.jsp").forward(request, response); +		 +	} +	 +	/** +	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse +	 *      response) +	 */ +	protected void doGet(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { +				 +		process(request, response); +	} + + +	/** +	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse +	 *      response) +	 */ +	protected void doPost(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { +		process(request, response); +	} +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java new file mode 100644 index 000000000..11cc020ff --- /dev/null +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/servlet/pvp2/SingleLogOut.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright 2014 Federal Chancellery Austria + * MOA-ID has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + *******************************************************************************/ +package at.gv.egovernment.moa.id.demoOA.servlet.pvp2; + +import java.io.IOException; +import java.security.KeyStore; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +import org.joda.time.DateTime; +import org.opensaml.common.SAMLObject; +import org.opensaml.common.binding.BasicSAMLMessageContext; +import org.opensaml.common.impl.SecureRandomIdentifierGenerator; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder; +import org.opensaml.saml2.core.AuthnContextClassRef; +import org.opensaml.saml2.core.AuthnContextComparisonTypeEnumeration; +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDPolicy; +import org.opensaml.saml2.core.NameIDType; +import org.opensaml.saml2.core.RequestedAuthnContext; +import org.opensaml.saml2.core.Subject; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.SingleLogoutService; +import org.opensaml.saml2.metadata.SingleSignOnService; +import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder; +import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; +import org.opensaml.ws.transport.http.HttpServletResponseAdapter; +import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter; +import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import at.gv.egovernment.moa.id.demoOA.Configuration; +import at.gv.egovernment.moa.id.demoOA.Constants; +import at.gv.egovernment.moa.id.demoOA.exception.ConfigurationException; +import at.gv.egovernment.moa.id.demoOA.utils.SAML2Utils; +import at.iaik.commons.util.MiscUtil; + + +/** + * Servlet implementation class Authenticate + */ +public class SingleLogOut extends HttpServlet { +	private static final long serialVersionUID = 1L; +	 +	private static final Logger log = LoggerFactory +			.getLogger(SingleLogOut.class);	 +	 +	/** +	 * @see HttpServlet#HttpServlet() +	 */ +	public SingleLogOut() { +		super(); +		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); +		factory.setNamespaceAware(true); +		try { +			builder = factory.newDocumentBuilder(); +			 +		} catch (ParserConfigurationException e) { +			log.warn("PVP2 AuthenticationServlet can not be initialized.", e); +		} +	} + +	DocumentBuilder builder; + + +	//generate AuthenticationRequest +	protected void process(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { +		try { +			 +			Configuration config = Configuration.getInstance(); +			config.initializePVP2Login(); +			 +			String nameIDFormat = (String) request.getSession().getAttribute(Constants.SESSION_NAMEIDFORMAT); +			String nameID = (String) request.getSession().getAttribute(Constants.SESSION_NAMEID); +			 +			if (MiscUtil.isEmpty(nameID) || MiscUtil.isEmpty(nameIDFormat)) { +				log.warn("No user information found. Single Log-Out not possible"); +				throw new ServletException("No user information found. Single Log-Out not possible"); +				 +			} else +				log.info("Fount user information for user nameID: " + nameID  +						+ " , nameIDFormat: " + nameIDFormat +						+ ". Build Single Log-Out request ..."); +			 +			//invalidate local session +			request.getSession().invalidate(); +			 +			//build Single LogOut request +			LogoutRequest sloReq = SAML2Utils.createSAMLObject(LogoutRequest.class); +			SecureRandomIdentifierGenerator gen = new SecureRandomIdentifierGenerator(); +			sloReq.setID(gen.generateIdentifier()); +			sloReq.setIssueInstant(new DateTime()); +			NameID name = SAML2Utils.createSAMLObject(NameID.class); +			Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); +			 +			String serviceURL = config.getPublicUrlPreFix(request); +			if (!serviceURL.endsWith("/")) +				serviceURL = serviceURL + "/"; +			name.setValue(serviceURL); +			issuer.setValue(serviceURL); +			issuer.setFormat(NameIDType.ENTITY); +			sloReq.setIssuer(issuer); +						 +			NameID userNameID = SAML2Utils.createSAMLObject(NameID.class); +			sloReq.setNameID(userNameID); +			userNameID.setFormat(nameIDFormat); +			userNameID.setValue(nameID); +			 +			String entityname = config.getPVP2IDPMetadataEntityName(); +			if (MiscUtil.isEmpty(entityname)) { +				log.info("No IDP EntityName configurated"); +				throw new ConfigurationException("No IDP EntityName configurated"); +			} +			 +			//get IDP metadata from metadataprovider +			HTTPMetadataProvider idpmetadata = config.getMetaDataProvier();			 +			EntityDescriptor idpEntity = idpmetadata.getEntityDescriptor(entityname); +			if (idpEntity == null) { +				log.info("IDP EntityName is not found in IDP Metadata"); +				throw new ConfigurationException("IDP EntityName is not found in IDP Metadata"); +			} +			 +			//select authentication-service url from metadata +			SingleLogoutService redirectEndpoint = null;   +			for (SingleLogoutService sss :  +					idpEntity.getIDPSSODescriptor(SAMLConstants.SAML20P_NS).getSingleLogoutServices()) { +				 +				//Get the service address for the binding you wish to use +				if (sss.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) {  +					redirectEndpoint = sss;   +				}   +			} +			sloReq.setDestination(redirectEndpoint.getLocation()); +			 +			//sign authentication request +			KeyStore keyStore = config.getPVP2KeyStore(); +			X509Credential authcredential = new KeyStoreX509CredentialAdapter( +					keyStore,  +					config.getPVP2KeystoreAuthRequestKeyAlias(),  +					config.getPVP2KeystoreAuthRequestKeyPassword().toCharArray()); + +			Signature signer = SAML2Utils.createSAMLObject(Signature.class); +			signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1); +			signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); +			signer.setSigningCredential(authcredential); +			sloReq.setSignature(signer); + +			//generate Http-POST Binding message +			VelocityEngine engine = new VelocityEngine(); +			engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); +			engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8"); +			engine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8"); +			engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); +			engine.setProperty("classpath.resource.loader.class", +					"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); +			engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, +					"org.apache.velocity.runtime.log.SimpleLog4JLogSystem"); +			engine.init(); + +			HTTPPostEncoder encoder = new HTTPPostEncoder(engine, +					"templates/pvp_postbinding_template.html"); +			HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter( +					response, true); +			BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject> context = new BasicSAMLMessageContext<SAMLObject, SAMLObject, SAMLObject>(); +			SingleSignOnService service = new SingleSignOnServiceBuilder() +					.buildObject(); +			service.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); +			service.setLocation(redirectEndpoint.getLocation());; +			 +			context.setOutboundSAMLMessageSigningCredential(authcredential); +			context.setPeerEntityEndpoint(service); +			context.setOutboundSAMLMessage(sloReq); +			context.setOutboundMessageTransport(responseAdapter); + +			encoder.encode(context); +						 +		} catch (Exception e) { +			log.warn("Authentication Request can not be generated", e); +			throw new ServletException("Authentication Request can not be generated.", e); +		} +	} + +	/** +	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse +	 *      response) +	 */ +	protected void doGet(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { +				 +		process(request, response); +	} + +	/** +	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse +	 *      response) +	 */ +	protected void doPost(HttpServletRequest request, +			HttpServletResponse response) throws ServletException, IOException { +		process(request, response); +	} + +} diff --git a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java index 832993604..05c253b6e 100644 --- a/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java +++ b/id/oa/src/main/java/at/gv/egovernment/moa/id/demoOA/utils/ApplicationBean.java @@ -36,6 +36,7 @@ public class ApplicationBean implements Serializable {  	private boolean isLogin = false;   	private String errorMessage; +	private String successMessage;  	/**  	 * @return the familyName @@ -109,6 +110,18 @@ public class ApplicationBean implements Serializable {  	public void setLogin(boolean isLogin) {  		this.isLogin = isLogin;  	} +	/** +	 * @return the successMessage +	 */ +	public String getSuccessMessage() { +		return successMessage; +	} +	/** +	 * @param successMessage the successMessage to set +	 */ +	public void setSuccessMessage(String successMessage) { +		this.successMessage = successMessage; +	} diff --git a/id/oa/src/main/webapp/WEB-INF/web.xml b/id/oa/src/main/webapp/WEB-INF/web.xml index 85a1bbaeb..d40f156cd 100644 --- a/id/oa/src/main/webapp/WEB-INF/web.xml +++ b/id/oa/src/main/webapp/WEB-INF/web.xml @@ -8,7 +8,7 @@    <servlet>  		<servlet-name>pvp2login</servlet-name> -		<display-name>pvp2login</display-name> +		<display-name>PVP 2.1 Authentication request builder</display-name>  		<servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.Authenticate</servlet-class>  	</servlet> @@ -17,6 +17,17 @@  		<url-pattern>/servlet/pvp2login</url-pattern>  	</servlet-mapping> +	<servlet> +		<servlet-name>pvp2slo</servlet-name> +		<display-name>PVP 2.1 Single Log-Out request builder</display-name> +		<servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.SingleLogOut</servlet-class> +	</servlet> +  	 + 	<servlet-mapping> +		<servlet-name>pvp2slo</servlet-name> +		<url-pattern>/servlet/startpvp2slo</url-pattern> +	</servlet-mapping> +	   	<servlet>  		<servlet-name>pvp2metadata</servlet-name>  		<display-name>Metadata</display-name> @@ -39,5 +50,16 @@  		<url-pattern>/demoapplication</url-pattern>  	</servlet-mapping> +   	<servlet> +		<servlet-name>index</servlet-name> +		<display-name>Mainpage</display-name> +		<servlet-class>at.gv.egovernment.moa.id.demoOA.servlet.pvp2.Index</servlet-class> +	</servlet> +  	 + 	<servlet-mapping> +		<servlet-name>index</servlet-name> +		<url-pattern>/singlelogout</url-pattern> +	</servlet-mapping> +    </web-app> | 
