/*
* 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();
}