aboutsummaryrefslogtreecommitdiff
path: root/id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java')
-rw-r--r--id/ConfigWebTool/src/main/java/at/gv/egovernment/moa/id/configuration/auth/pvp2/servlets/SLOFrontChannelServlet.java287
1 files changed, 287 insertions, 0 deletions
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);
+ }
+
+}