/*
 * Gretty
 *
 * Copyright (C) 2013-2015 Andrey Hihlovskiy and contributors.
 *
 * See the file "LICENSE" for copying and usage permission.
 * See the file "CONTRIBUTORS" for complete list of contributors.
 */
package org.akhikhl.gretty;

import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.SessionAuthentication;
import org.eclipse.jetty.security.authentication.SpnegoAuthenticator;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.MultiMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import static org.eclipse.jetty.security.authentication.FormAuthenticator.__J_POST;
import static org.eclipse.jetty.security.authentication.FormAuthenticator.__J_URI;

/**
 *
 * @author akhikhl
 */
public class SSOSpnegoAuthenticator extends SpnegoAuthenticator {

    private static final Logger LOG = LoggerFactory.getLogger(SSOSpnegoAuthenticator.class);

    public SSOSpnegoAuthenticator() {
    }

    public SSOSpnegoAuthenticator(String authMethod) {
      super(authMethod);
    }

    @Override
    public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
    {
        HttpServletRequest request = (HttpServletRequest)req;

        if (!mandatory)
            return new DeferredAuthentication(this);

        // ++ copied from FormAuthenticator

        HttpSession session = request.getSession(true);

        // Look for cached authentication
        Authentication authentication = (Authentication) session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
        if (authentication != null)
        {
            // Has authentication been revoked?
            if (authentication instanceof Authentication.User &&
                _loginService!=null &&
                !_loginService.validate(((Authentication.User)authentication).getUserIdentity()))
            {

                session.removeAttribute(SessionAuthentication.__J_AUTHENTICATED);
            }
            else
            {
                String j_uri=(String)session.getAttribute(__J_URI);
                if (j_uri!=null)
                {
                    MultiMap<String> j_post = (MultiMap<String>)session.getAttribute(__J_POST);
                    if (j_post!=null)
                    {
                        StringBuffer buf = request.getRequestURL();
                        if (request.getQueryString() != null)
                            buf.append("?").append(request.getQueryString());

                        if (j_uri.equals(buf.toString()))
                        {
                            // This is a retry of an original POST request
                            // so restore method and parameters

                            session.removeAttribute(__J_POST);
                            Request base_request = (req instanceof Request)?(Request)req:AbstractHttpConnection.getCurrentConnection().getRequest();
                            base_request.setMethod(HttpMethods.POST);
                            base_request.setParameters(j_post);
                        }
                    }
                    else
                        session.removeAttribute(__J_URI);

                }
                return authentication;
            }
        }
        // -- copied from FormAuthenticator

        return super.validateRequest(req, res, mandatory);
    }
}
