/* * Copyright 2011 Federal Chancellery Austria and * Graz University of Technology * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.gv.util.filter.moaid; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; 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.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.util.MiscUtil; import at.gv.util.ToStringUtil; import at.gv.util.WebAppUtil; import at.gv.util.client.moaid.MOAIDClient; import at.gv.util.client.moaid.MOAIDClientException; import at.gv.util.config.EgovUtilConfiguration; import at.gv.util.xsd.saml.assertion.AssertionType; import at.gv.util.xsd.saml.protocol.ResponseType; /** * @author Arne Tauber * @author Thomas Knall */ public abstract class AbstractGenericMOAIDAuthenticationServlet extends HttpServlet { private static final long serialVersionUID = 1L; public static final String REQUEST_ATTRIBUTE_ERROR_MESSAGE = "javax.servlet.error.message"; //private boolean alreadyLogged = false; private HttpServletRequest request = null; private HttpServletResponse response = null; private final Logger log = LoggerFactory.getLogger(AbstractGenericMOAIDAuthenticationServlet.class); @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } private void errorPage(HttpServletRequest request, HttpServletResponse response, String... args) { this.request = request; this.response = response; log.debug("Forwarding to error page \"" + this.getErrorPage() + "\"."); log.error("Messages for Errorpage (saved in request attribute \"" + REQUEST_ATTRIBUTE_ERROR_MESSAGE + "\"): " + ToStringUtil.toString(args)); request.setAttribute(REQUEST_ATTRIBUTE_ERROR_MESSAGE, ToStringUtil.toString(args)); try { request.getRequestDispatcher(this.getErrorPage()).forward(request, response); return; } catch (Throwable t) { log.error("Unexpected error (" + t.getMessage() + ") forwarding to error page \"" + this.getErrorPage() + "\"."); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { log.debug("MOAIDLogin invoked."); this.request = request; this.response = response; String artifact = request.getParameter("SAMLArtifact"); if (MiscUtil.isEmpty(artifact)) { this.errorPage(request, response, "SAMLArtifact post parameter must not be null or empty."); return; } String expectedTarget = this.getExpectedTarget(); String target = request.getParameter("Target"); if (MiscUtil.isNotEmpty(target)) { if (MiscUtil.isNotEmpty(expectedTarget)) { log.debug("Verifying target parameter."); if (!expectedTarget.equals(target)) { this.errorPage(request, response, "Transmitted target parameter does not match the expected target parameter value \"" + expectedTarget + "\"."); return; } } } else { log.debug("No expected target parameter given. Maybe configured as wbpk application. Skipping target value evaluation."); } log.debug("SAMLArtifact = \"" + artifact + "\"."); AssertionType assertion = null; try { MOAIDClient client = new MOAIDClient(this.getConfiguration()); ResponseType moaidResponse = client.sendGetAuthenticationDataRequest(this.getAuthDataURL(), artifact); if (!"Success".equals(moaidResponse.getStatus().getStatusCode().getValue().getLocalPart())) { throw new MOAIDClientException("Wrong MOA-ID return code: " + moaidResponse.getStatus().getStatusCode().getValue().toString()); } assertion = moaidResponse.getAssertion().get(0); } catch (MOAIDClientException c) { String em = "Error retrieving authentication data (" + c.getMessage() + ")."; log.error(em); this.errorPage(request, response, em); return; } HttpSession session = request.getSession(false); if (session != null) { HashMap attributes = new HashMap(); Enumeration enames = session.getAttributeNames(); while (enames.hasMoreElements()) { String name = enames.nextElement(); if (!name.equals("JSESSIONID")) attributes.put(name, session.getAttribute( name)); } // // alle Notizen kopieren // HashMap notes = new HashMap(); // Iterator nameit = session.getNoteN; // while (nameit.hasNext()) { // String name = nameit.next(); // notes.put( name, session.getNote( name)); // } // session.invalidate(); session = request.getSession(true); // Attribute und Notizen zurückkopieren for (Entry et : attributes.entrySet()) { session.setAttribute( et.getKey(), et.getValue()); } } else session = request.getSession(true); log.debug("Using session " + session.getId() + ", created at " + DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(session.getCreationTime()) + "."); Object authData = this.getAuthDataObject(assertion, request); if (authData == null) { log.info("No auth data provided from implementing application. Denying access."); response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access is denied."); return; } log.debug("Authentication data = " + authData); session.setAttribute(this.getAuthDataSessionAttribute(), authData); String originalURL = null; String authenticatedPage = StringUtils.trim(this.getAuthenticatedPage(request, originalURL)); if (MiscUtil.isNotEmpty(authenticatedPage)) { try { // check if absolute URL is given new URL(authenticatedPage); // if absolute URL is given take it } catch (MalformedURLException e) { // if no absolute URL is given, prepend the webapp context authenticatedPage = WebAppUtil.getBaseURL(request) + MiscUtil.removePrecedingSlash(authenticatedPage); } log.debug("User is authenticated. Authenticated page given. Redirecting to \"" + authenticatedPage + "\"."); response.sendRedirect(response.encodeRedirectURL(authenticatedPage)); return; } else { log.debug("No authenticated page given. Trying to find original url."); String sessionAttribute = this.getStoredRequestURLSessionAttribute(); if (MiscUtil.isNotEmpty(sessionAttribute)) { log.debug("Fetching saved request url from session attribute \"" + sessionAttribute + "\"."); originalURL = (String) session.getAttribute(sessionAttribute); session.removeAttribute(sessionAttribute); } if (originalURL == null) { log.warn("Unable to find saved request. Session seems to got lost."); String sessionLostPage = this.getSessionLostPage(); if (MiscUtil.isNotEmpty(sessionLostPage)) { sessionLostPage = WebAppUtil.getBaseURL(request) + MiscUtil.removePrecedingSlash(sessionLostPage); log.debug("Found failsafe page for redirection in case of session loss. Redirecting to \"" + sessionLostPage + "\"."); response.sendRedirect(response.encodeRedirectURL(sessionLostPage)); return; } this.errorPage(request, response, "Unable to find saved request."); return; } log.debug("User is authenticated. Redirecting to original location \"" + originalURL + "\"."); response.sendRedirect(response.encodeRedirectURL(originalURL)); return; } } public HttpServletRequest getRequest() { return request; } public HttpServletResponse getResponse() { return response; } public abstract String getAuthenticatedPage(HttpServletRequest request, String savedRequestURL); public abstract String getAuthDataSessionAttribute(); public abstract String getStoredRequestURLSessionAttribute(); public abstract String getErrorPage(); public abstract Object getAuthDataObject(AssertionType samlAssertion); public Object getAuthDataObject(AssertionType samlAssertion, HttpServletRequest request) { return this.getAuthDataObject(samlAssertion); } public abstract String getAuthDataURL(); public abstract String getSessionLostPage(); public abstract String getExpectedTarget(); public abstract EgovUtilConfiguration getConfiguration(); }