/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.sling.auth.form.impl;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;

import javax.jcr.Credentials;
import javax.jcr.SimpleCredentials;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;
import org.apache.sling.api.auth.Authenticator;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.auth.core.AuthConstants;
import org.apache.sling.auth.core.AuthUtil;
import org.apache.sling.auth.core.spi.AuthenticationHandler;
import org.apache.sling.auth.core.spi.AuthenticationInfo;
import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler;
import org.apache.sling.auth.form.FormReason;
import org.apache.sling.auth.form.impl.jaas.FormCredentials;
import org.apache.sling.auth.form.impl.jaas.JaasHelper;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>FormAuthenticationHandler</code> class implements the authorization
 * steps based on a cookie.
 */
@Component(name = "org.apache.sling.auth.form.FormAuthenticationHandler", property = {
		AuthenticationHandler.TYPE_PROPERTY + "="
				+ HttpServletRequest.FORM_AUTH }, service = AuthenticationHandler.class, immediate = true)
@Designate(ocd = FormAuthenticationHandlerConfig.class)
public class FormAuthenticationHandler extends DefaultAuthenticationFeedbackHandler implements AuthenticationHandler {

	/**
	 * The request method required for user name and password submission by the form
	 * (value is "POST").
	 */
	private static final String REQUEST_METHOD = "POST";

	/**
	 * The last segment of the request URL for the user name and password submission
	 * by the form (value is "/j_security_check").
	 * <p>
	 * This name is derived from the prescription in the Servlet API 2.4
	 * Specification, Section SRV.12.5.3.1 Login Form Notes: <i>In order for the
	 * authentication to proceed appropriately, the action of the login form must
	 * always be set to <code>j_security_check</code>.</i>
	 */
	private static final String REQUEST_URL_SUFFIX = "/j_security_check";

	/**
	 * The name of the form submission parameter providing the name of the user to
	 * authenticate (value is "j_username").
	 * <p>
	 * This name is prescribed by the Servlet API 2.4 Specification, Section
	 * SRV.12.5.3 Form Based Authentication.
	 */
	private static final String PAR_J_USERNAME = "j_username";

	/**
	 * The name of the form submission parameter providing the password of the user
	 * to authenticate (value is "j_password").
	 * <p>
	 * This name is prescribed by the Servlet API 2.4 Specification, Section
	 * SRV.12.5.3 Form Based Authentication.
	 */
	private static final String PAR_J_PASSWORD = "j_password";

	/**
	 * Key in the AuthenticationInfo map which contains the domain on which the auth
	 * cookie should be set.
	 */
	private static final String COOKIE_DOMAIN = "cookie.domain";

	/**
	 * The factor to convert minute numbers into milliseconds used internally
	 */
	private static final long MINUTES = 60L * 1000L;

	/** default log */
	private final Logger log = LoggerFactory.getLogger(getClass());

	private AuthenticationStorage authStorage;

	private String loginForm;

	/**
	 * The timeout of a login session in milliseconds, converted from the
	 * configuration property {@link #PAR_AUTH_TIMEOUT} by multiplying with
	 * {@link #MINUTES}.
	 */
	private long sessionTimeout;

	/**
	 * The name of the credentials attribute which is set to the cookie data to
	 * validate.
	 */
	private String attrCookieAuthData;

	/**
	 * The {@link TokenStore} used to persist and check authentication data
	 */
	private TokenStore tokenStore;

	/**
	 * The {@link FormLoginModulePlugin} service registration created when this
	 * authentication handler is registered. If the login module plugin cannot be
	 * created this field is set to <code>null</code>.
	 */
	private ServiceRegistration<?> loginModule;

	/**
	 * If true, the handler will attempt to include the login form instead of doing
	 * a redirect.
	 */
	private boolean includeLoginForm;

	/**
	 * The resource resolver factory used to resolve the login form as a resource
	 */
	@Reference(policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.OPTIONAL)
	private volatile ResourceResolverFactory resourceResolverFactory;

	/**
	 * If true the login form will be presented when the token expires.
	 */
	private boolean loginAfterExpire;

	private JaasHelper jaasHelper;

	/**
	 * Extracts cookie/session based credentials from the request. Returns
	 * <code>null</code> if the handler assumes HTTP Basic authentication would be
	 * more appropriate, if no form fields are present in the request and if the
	 * secure user data is not present either in the cookie or an HTTP Session.
	 */
	@Override
	public AuthenticationInfo extractCredentials(HttpServletRequest request, HttpServletResponse response) {

		AuthenticationInfo info = null;

		// 1. try credentials from POST'ed request parameters
		info = this.extractRequestParameterAuthentication(request);

		// 2. try credentials from the cookie or session
		if (info == null) {
			String authData = authStorage.extractAuthenticationInfo(request);
			if (authData != null) {
				if (tokenStore.isValid(authData)) {
					info = createAuthInfo(authData);
				} else {
					// clear the cookie, its invalid and we should get rid of it
					// so that the invalid cookie isn't present on the authN
					// operation.
					authStorage.clear(request, response);
					if (this.loginAfterExpire || AuthUtil.isValidateRequest(request)) {
						// signal the requestCredentials method a previous login
						// failure
						request.setAttribute(FAILURE_REASON, FormReason.TIMEOUT);
						info = AuthenticationInfo.FAIL_AUTH;
					}
				}
			}
		}

		return info;
	}

	/**
	 * Unless the <code>sling:authRequestLogin</code> to anything other than
	 * <code>Form</code> this method either sends back a 403/FORBIDDEN response if
	 * the <code>j_verify</code> parameter is set to <code>true</code> or redirects
	 * to the login form to ask for credentials.
	 * <p>
	 * This method assumes the <code>j_verify</code> request parameter to only be
	 * set in the initial username/password submission through the login form. No
	 * further checks are applied, though, before sending back the 403/FORBIDDEN
	 * response.
	 */
	@Override
	public boolean requestCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException {

		// 0. ignore this handler if an authentication handler is requested
		if (ignoreRequestCredentials(request)) {
			// consider this handler is not used
			return false;
		}

		// check the referrer to see if the request is for this handler
		if (!AuthUtil.checkReferer(request, loginForm)) {
			// not for this handler, so return
			return false;
		}

		final String resource = AuthUtil.setLoginResourceAttribute(request, request.getRequestURI());

		if (includeLoginForm && (resourceResolverFactory != null)) {
			ResourceResolver resourceResolver = null;
			try {
				resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);
				Resource loginFormResource = resourceResolver.resolve(loginForm);
				Servlet loginFormServlet = loginFormResource.adaptTo(Servlet.class);
				if (loginFormServlet != null) {
					try {
						loginFormServlet.service(request, response);
						return true;
					} catch (ServletException e) {
						log.error("Failed to include the form: " + loginForm, e);
					}
				}
			} catch (LoginException e) {
				log.error(
						"Unable to get a resource resolver to include for the login resource. Will redirect instead.");
			} finally {
				if (resourceResolver != null) {
					resourceResolver.close();
				}
			}
		}

		HashMap<String, String> params = new HashMap<String, String>();
		params.put(Authenticator.LOGIN_RESOURCE, resource);

		// append indication of previous login failure
		if (request.getAttribute(FAILURE_REASON) != null) {
			final Object jReason = request.getAttribute(FAILURE_REASON);
			@SuppressWarnings("rawtypes")
			final String reason = (jReason instanceof Enum) ? ((Enum) jReason).name() : jReason.toString();
			params.put(FAILURE_REASON, reason);
		}

		try {
			AuthUtil.sendRedirect(request, response, request.getContextPath() + loginForm, params);
		} catch (IOException e) {
			log.error("Failed to redirect to the login form " + loginForm, e);
		}

		return true;
	}

	/**
	 * Clears all authentication state which might have been prepared by this
	 * authentication handler.
	 */
	@Override
	public void dropCredentials(HttpServletRequest request, HttpServletResponse response) {
		authStorage.clear(request, response);
	}

	// ---------- AuthenticationFeedbackHandler

	/**
	 * Called after an unsuccessful login attempt. This implementation makes sure
	 * the authentication data is removed either by removing the cookie or by remove
	 * the HTTP Session attribute.
	 */
	@Override
	public void authenticationFailed(HttpServletRequest request, HttpServletResponse response,
			AuthenticationInfo authInfo) {

		/*
		 * Note: This method is called if this handler provided credentials which cause
		 * a login failure
		 */

		// clear authentication data from Cookie or Http Session
		authStorage.clear(request, response);

		// signal the reason for login failure
		request.setAttribute(FAILURE_REASON, FormReason.INVALID_CREDENTIALS);
	}

	/**
	 * Called after successful login with the given authentication info. This
	 * implementation ensures the authentication data is set in either the cookie or
	 * the HTTP session with the correct security tokens.
	 * <p>
	 * If no authentication data already exists, it is created. Otherwise if the
	 * data has expired the data is updated with a new security token and a new
	 * expiry time.
	 * <p>
	 * If creating or updating the authentication data fails, it is actually removed
	 * from the cookie or the HTTP session and future requests will not be
	 * authenticated any longer.
	 */
	@Override
	public boolean authenticationSucceeded(HttpServletRequest request, HttpServletResponse response,
			AuthenticationInfo authInfo) {

		/*
		 * Note: This method is called if this handler provided credentials which
		 * succeeded login into the repository
		 */

		// ensure fresh authentication data
		refreshAuthData(request, response, authInfo);

		final boolean result;
		// SLING-1847: only consider a resource redirect if this is a POST request
		// to the j_security_check URL
		if (REQUEST_METHOD.equals(request.getMethod()) && request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {

			if (DefaultAuthenticationFeedbackHandler.handleRedirect(request, response)) {
				// terminate request, all done in the default handler
				result = false;
			} else {
				// check whether redirect is requested by the resource parameter
				final String targetResource = AuthUtil.getLoginResource(request, null);
				if (targetResource != null) {
					try {
						if (response.isCommitted()) {
							throw new IllegalStateException("Response is already committed");
						}
						response.resetBuffer();

						StringBuilder b = new StringBuilder();
						if (AuthUtil.isRedirectValid(request, targetResource)) {
							b.append(targetResource);
						} else if (request.getContextPath().length() == 0) {
							b.append("/");
						} else {
							b.append(request.getContextPath());
						}
						response.sendRedirect(b.toString());
					} catch (IOException ioe) {
						log.error("Failed to send redirect to: " + targetResource, ioe);
					}

					// terminate request, all done
					result = true;
				} else {
					// no redirect, hence continue processing
					result = false;
				}
			}
		} else {
			// no redirect, hence continue processing
			result = false;
		}

		// no redirect
		return result;
	}

	@Override
	public String toString() {
		return "Form Based Authentication Handler";
	}

	// --------- Force HTTP Basic Auth ---------

	/**
	 * Returns <code>true</code> if this authentication handler should ignore the
	 * call to {@link #requestCredentials(HttpServletRequest, HttpServletResponse)}.
	 * <p>
	 * This method returns <code>true</code> if the {@link #REQUEST_LOGIN_PARAMETER}
	 * is set to any value other than "Form" (HttpServletRequest.FORM_AUTH).
	 */
	private boolean ignoreRequestCredentials(final HttpServletRequest request) {
		final String requestLogin = request.getParameter(REQUEST_LOGIN_PARAMETER);
		return requestLogin != null && !HttpServletRequest.FORM_AUTH.equals(requestLogin);
	}

	/**
	 * Ensures the authentication data is set (if not set yet) and the expiry time
	 * is prolonged (if auth data already existed).
	 * <p>
	 * This method is intended to be called in case authentication succeeded.
	 *
	 * @param request
	 *            The current request
	 * @param response
	 *            The current response
	 * @param authInfo
	 *            The authentication info used to successful log in
	 */
	private void refreshAuthData(final HttpServletRequest request, final HttpServletResponse response,
			final AuthenticationInfo authInfo) {

		// get current authentication data, may be missing after first login
		String authData = getCookieAuthData(authInfo);

		// check whether we have to "store" or create the data
		final boolean refreshCookie = needsRefresh(authData, this.sessionTimeout);

		// add or refresh the stored auth hash
		if (refreshCookie) {
			long expires = System.currentTimeMillis() + this.sessionTimeout;
			try {
				authData = null;
				authData = tokenStore.encode(expires, authInfo.getUser());
			} catch (InvalidKeyException e) {
				log.error(e.getMessage(), e);
			} catch (IllegalStateException e) {
				log.error(e.getMessage(), e);
			} catch (UnsupportedEncodingException e) {
				log.error(e.getMessage(), e);
			} catch (NoSuchAlgorithmException e) {
				log.error(e.getMessage(), e);
			}

			if (authData != null) {
				authStorage.set(request, response, authData, authInfo);
			} else {
				authStorage.clear(request, response);
			}
		}
	}

	// --------- Request Parameter Auth ---------

	private AuthenticationInfo extractRequestParameterAuthentication(HttpServletRequest request) {
		AuthenticationInfo info = null;

		// only consider login form parameters if this is a POST request
		// to the j_security_check URL
		if (REQUEST_METHOD.equals(request.getMethod()) && request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {

			String user = request.getParameter(PAR_J_USERNAME);
			String pwd = request.getParameter(PAR_J_PASSWORD);

			if (user != null && pwd != null) {
				info = new AuthenticationInfo(HttpServletRequest.FORM_AUTH, user, pwd.toCharArray());
				info.put(AuthConstants.AUTH_INFO_LOGIN, new Object());

				// if this request is providing form credentials, we have to
				// make sure, that the request is redirected after successful
				// authentication, otherwise the request may be processed
				// as a POST request to the j_security_check page (unless
				// the j_validate parameter is set); but only if this is not
				// a validation request
				if (!AuthUtil.isValidateRequest(request)) {
					AuthUtil.setLoginResourceAttribute(request, request.getContextPath());
				}
			}
		}

		return info;
	}

	private AuthenticationInfo createAuthInfo(final String authData) {
		final String userId = getUserId(authData);
		if (userId == null) {
			return null;
		}

		final AuthenticationInfo info = new AuthenticationInfo(HttpServletRequest.FORM_AUTH, userId);

		if (jaasHelper.enabled()) {
			// JcrResourceConstants.AUTHENTICATION_INFO_CREDENTIALS
			info.put("user.jcr.credentials", new FormCredentials(userId, authData));
		} else {
			info.put(attrCookieAuthData, authData);
		}

		return info;
	}

	private String getCookieAuthData(final AuthenticationInfo info) {
		Object data = info.get(attrCookieAuthData);
		if (data instanceof String) {
			return (String) data;
		}
		return null;
	}

	// ---------- LoginModulePlugin support

	private String getCookieAuthData(final Credentials credentials) {
		if (credentials instanceof SimpleCredentials) {
			Object data = ((SimpleCredentials) credentials).getAttribute(attrCookieAuthData);
			if (data instanceof String) {
				return (String) data;
			}
		} else if (credentials instanceof FormCredentials) {
			return ((FormCredentials) credentials).getAuthData();
		}

		// no SimpleCredentials or no valid attribute
		return null;
	}

	boolean hasAuthData(final Credentials credentials) {
		return getCookieAuthData(credentials) != null;
	}

	public boolean isValid(final Credentials credentials) {
		String authData = getCookieAuthData(credentials);
		if (authData != null) {
			return tokenStore.isValid(authData);
		}

		// no authdata, not valid
		return false;
	}

	// ---------- SCR Integration ----------------------------------------------

	/**
	 * Called by SCR to activate the authentication handler.
	 *
	 * @throws InvalidKeyException
	 * @throws NoSuchAlgorithmException
	 * @throws IllegalStateException
	 * @throws UnsupportedEncodingException
	 */
	@Activate
	protected void activate(FormAuthenticationHandlerConfig config, ComponentContext componentContext)
			throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException {

		this.jaasHelper = new JaasHelper(this, componentContext.getBundleContext(), config);
		this.loginForm = config.form_login_form();
		log.info("Login Form URL {}", loginForm);

		final String authName = config.form_auth_name();

		String defaultCookieDomain = config.form_default_cookie_domain();
		if (defaultCookieDomain.length() == 0) {
			defaultCookieDomain = null;
		}

		final String authStorage = config.form_auth_storage();
		if (FormAuthenticationHandlerConfig.AUTH_STORAGE_SESSION_ATTRIBUTE.equals(authStorage)) {
			this.authStorage = new SessionStorage(authName);
			log.info("Using HTTP Session store with attribute name {}", authName);
		} else {
			this.authStorage = new CookieStorage(authName, defaultCookieDomain);
			log.info("Using Cookie store with name {}", authName);
		}

		this.attrCookieAuthData = config.form_credentials_name();
		log.info("Setting Auth Data attribute name {}", attrCookieAuthData);

		int timeoutMinutes = config.form_auth_timeout();
		if (timeoutMinutes < 1) {
			timeoutMinutes = FormAuthenticationHandlerConfig.DEFAULT_AUTH_TIMEOUT;
		}
		log.info("Setting session timeout {} minutes", timeoutMinutes);
		this.sessionTimeout = MINUTES * timeoutMinutes;

		final String tokenFileName = config.form_token_file();
		final File tokenFile = getTokenFile(tokenFileName, componentContext.getBundleContext());
		final boolean fastSeed = config.form_token_fastseed();
		log.info("Storing tokens in {}", tokenFile.getAbsolutePath());
		this.tokenStore = new TokenStore(tokenFile, sessionTimeout, fastSeed);

		this.loginModule = null;
		if (!jaasHelper.enabled()) {
			try {
				this.loginModule = FormLoginModulePlugin.register(this, componentContext.getBundleContext());
			} catch (Throwable t) {
				log.info(
						"Cannot register FormLoginModulePlugin. This is expected if Sling LoginModulePlugin services are not supported");
				log.debug("dump", t);
			}
		}

		this.includeLoginForm = config.useInclude();

		this.loginAfterExpire = config.form_onexpire_login();
	}

	@Deactivate
	protected void deactivate() {
		if (jaasHelper != null) {
			jaasHelper.close();
			jaasHelper = null;
		}

		if (loginModule != null) {
			loginModule.unregister();
			loginModule = null;
		}
	}

	/**
	 * Returns an absolute file indicating the file to use to persist the security
	 * tokens.
	 * <p>
	 * This method is not part of the API of this class and is package private to
	 * enable unit tests.
	 *
	 * @param tokenFileName
	 *            The configured file name, must not be null
	 * @param bundleContext
	 *            The BundleContext to use to make an relative file absolute
	 * @return The absolute file
	 */
	File getTokenFile(final String tokenFileName, final BundleContext bundleContext) {
		File tokenFile = new File(tokenFileName);
		if (tokenFile.isAbsolute()) {
			return tokenFile;
		}

		tokenFile = bundleContext.getDataFile(tokenFileName);
		if (tokenFile == null) {
			final String slingHome = bundleContext.getProperty("sling.home");
			if (slingHome != null) {
				tokenFile = new File(slingHome, tokenFileName);
			} else {
				tokenFile = new File(tokenFileName);
			}
		}

		return tokenFile.getAbsoluteFile();
	}

	/**
	 * Returns the user id from the authentication data. If the authentication data
	 * is a non-<code>null</code> value with 3 fields separated by an @ sign, the
	 * value of the third field is returned. Otherwise <code>null</code> is
	 * returned.
	 * <p>
	 * This method is not part of the API of this class and is package private to
	 * enable unit tests.
	 *
	 * @param authData
	 * @return
	 */
	String getUserId(final String authData) {
		if (authData != null) {
			String[] parts = TokenStore.split(authData);
			if (parts != null) {
				return parts[2];
			}
		}
		return null;
	}

	/**
	 * Refresh the cookie periodically.
	 *
	 * @param sessionTimeout
	 *            time to live for the session
	 * @return true or false
	 */
	private boolean needsRefresh(final String authData, final long sessionTimeout) {
		boolean updateCookie = false;
		if (authData == null) {
			updateCookie = true;
		} else {
			String[] parts = TokenStore.split(authData);
			if (parts != null && parts.length == 3) {
				long cookieTime = Long.parseLong(parts[1].substring(1));
				if (System.currentTimeMillis() + (sessionTimeout / 2) > cookieTime) {
					updateCookie = true;
				}
			}
		}
		return updateCookie;
	}

	/**
	 * The <code>AuthenticationStorage</code> interface abstracts the API required
	 * to store the authentication data in an HTTP cookie or in an HTTP Session. The
	 * concrete class -- {@link CookieStorage} or {@link SessionStorage} -- is
	 * selected using the {@link FormAuthenticationHandler#PAR_AUTH_STORAGE}
	 * configuration parameter, {@link CookieStorage} by default.
	 */
	private static interface AuthenticationStorage {
		String extractAuthenticationInfo(HttpServletRequest request);

		void set(HttpServletRequest request, HttpServletResponse response, String authData, AuthenticationInfo info);

		void clear(HttpServletRequest request, HttpServletResponse response);
	}

	/**
	 * The <code>CookieStorage</code> class supports storing the authentication data
	 * in an HTTP Cookie.
	 */
	private static class CookieStorage implements AuthenticationStorage {

		/**
		 * The Set-Cookie header used to manage the login cookie.
		 *
		 * @see CookieStorage#setCookie(HttpServletRequest, HttpServletResponse, String,
		 *      String, int, String)
		 */
		private static final String HEADER_SET_COOKIE = "Set-Cookie";

		private final String cookieName;
		private final String domainCookieName;
		private final String defaultCookieDomain;

		public CookieStorage(final String cookieName, final String defaultCookieDomain) {
			this.cookieName = cookieName;
			this.domainCookieName = cookieName + "." + COOKIE_DOMAIN;
			this.defaultCookieDomain = defaultCookieDomain;
		}

		@Override
		public String extractAuthenticationInfo(HttpServletRequest request) {
			Cookie[] cookies = request.getCookies();
			if (cookies != null) {
				for (Cookie cookie : cookies) {
					if (this.cookieName.equals(cookie.getName())) {
						// found the cookie, so try to extract the credentials
						// from it and reverse the base64 encoding
						String value = cookie.getValue();
						if (value.length() > 0) {
							try {
								return new String(Base64.decodeBase64(value), "UTF-8");
							} catch (UnsupportedEncodingException e1) {
								throw new RuntimeException(e1);
							}
						}
					}
				}
			}

			return null;
		}

		@Override
		public void set(HttpServletRequest request, HttpServletResponse response, String authData,
				AuthenticationInfo info) {
			// base64 encode to handle any special characters
			String cookieValue;
			try {
				cookieValue = Base64.encodeBase64URLSafeString(authData.getBytes("UTF-8"));
			} catch (UnsupportedEncodingException e1) {
				throw new RuntimeException(e1);
			}

			// send the cookie to the response
			String cookieDomain = (String) info.get(COOKIE_DOMAIN);
			if (cookieDomain == null || cookieDomain.length() == 0) {
				cookieDomain = defaultCookieDomain;
			}
			setCookie(request, response, this.cookieName, cookieValue, -1, cookieDomain);

			// send the cookie domain cookie if domain is not null
			if (cookieDomain != null) {
				setCookie(request, response, this.domainCookieName, cookieDomain, -1, cookieDomain);
			}
		}

		@Override
		public void clear(HttpServletRequest request, HttpServletResponse response) {
			Cookie oldCookie = null;
			String oldCookieDomain = null;
			Cookie[] cookies = request.getCookies();
			if (cookies != null) {
				for (Cookie cookie : cookies) {
					if (this.cookieName.equals(cookie.getName())) {
						// found the cookie
						oldCookie = cookie;
					} else if (this.domainCookieName.equals(cookie.getName())) {
						oldCookieDomain = cookie.getValue();
					}
				}
			}

			// remove the old cookie from the client
			if (oldCookie != null) {
				setCookie(request, response, this.cookieName, "", 0, oldCookieDomain);
				if (oldCookieDomain != null && oldCookieDomain.length() > 0) {
					setCookie(request, response, this.domainCookieName, "", 0, oldCookieDomain);
				}
			}
		}

		private void setCookie(final HttpServletRequest request, final HttpServletResponse response, final String name,
				final String value, final int age, final String domain) {

			final String ctxPath = request.getContextPath();
			final String cookiePath = (ctxPath == null || ctxPath.length() == 0) ? "/" : ctxPath;

			/*
			 * The Servlet Spec 2.5 does not allow us to set the commonly used HttpOnly
			 * attribute on cookies (Servlet API 3.0 does) so we create the Set-Cookie
			 * header manually. See http://www.owasp.org/index.php/HttpOnly for information
			 * on what the HttpOnly attribute is used for.
			 */

			final StringBuilder header = new StringBuilder();

			// default setup with name, value, cookie path and HttpOnly
			header.append(name).append("=").append(value);
			header.append("; Path=").append(cookiePath);
			header.append("; HttpOnly"); // don't allow JS access

			// set the cookie domain if so configured
			if (domain != null) {
				header.append("; Domain=").append(domain);
			}

			// Only set the Max-Age attribute to remove the cookie
			if (age >= 0) {
				header.append("; Max-Age=").append(age);
			}

			// ensure the cookie is secured if this is an https request
			if (request.isSecure()) {
				header.append("; Secure");
			}

			response.addHeader(HEADER_SET_COOKIE, header.toString());
		}
	}

	/**
	 * The <code>SessionStorage</code> class provides support to store the
	 * authentication data in an HTTP Session.
	 */
	private static class SessionStorage implements AuthenticationStorage {
		private final String sessionAttributeName;

		SessionStorage(final String sessionAttributeName) {
			this.sessionAttributeName = sessionAttributeName;
		}

		@Override
		public String extractAuthenticationInfo(HttpServletRequest request) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object attribute = session.getAttribute(sessionAttributeName);
				if (attribute instanceof String) {
					return (String) attribute;
				}
			}
			return null;
		}

		@Override
		public void set(HttpServletRequest request, HttpServletResponse response, String authData,
				AuthenticationInfo info) {
			// store the auth hash as a session attribute
			HttpSession session = request.getSession();
			session.setAttribute(sessionAttributeName, authData);
		}

		@Override
		public void clear(HttpServletRequest request, HttpServletResponse response) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				session.removeAttribute(sessionAttributeName);
			}
		}

	}
}