package org.pac4j.springframework.security.web;

import org.pac4j.core.client.Client;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.JEEContext;
import org.pac4j.core.context.session.JEESessionStore;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.engine.DefaultSecurityLogic;
import org.pac4j.core.exception.TechnicalException;
import org.pac4j.core.exception.http.HttpAction;
import org.pac4j.core.http.adapter.HttpActionAdapter;
import org.pac4j.core.http.adapter.JEEHttpActionAdapter;
import org.pac4j.core.util.CommonHelper;
import org.pac4j.core.util.FindBest;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * This entry point can be defined with a security configuration and a client name:
 * if it's an indirect client, it redirects the user to te identity provider for login. Otherwise, a 401 error page is returned.
 * If no configuration is provided, an error is returned directly.
 *
 * @author Jerome Leleu
 * @since 1.0.0
 */
public class Pac4jEntryPoint extends DefaultSecurityLogic<Object, JEEContext> implements AuthenticationEntryPoint {

    private Config config;

    private String clientName;

    public Pac4jEntryPoint() {}

    public Pac4jEntryPoint(final Config config, final String clientName) {
        this.config = config;
        this.clientName = clientName;
    }

    @Override
    public void commence(final HttpServletRequest request, final HttpServletResponse response,
                         final AuthenticationException authException) throws IOException, ServletException {

        if (config != null && CommonHelper.isNotBlank(clientName)) {
            final SessionStore<JEEContext> bestSessionStore = FindBest.sessionStore(null, config, JEESessionStore.INSTANCE);
            final HttpActionAdapter<Object, JEEContext> bestAdapter = FindBest.httpActionAdapter(null, config, JEEHttpActionAdapter.INSTANCE);
            final JEEContext context = new JEEContext(request, response, bestSessionStore);

            final List<Client> currentClients = new ArrayList<>();
            final Client client = config.getClients().findClient(clientName).orElseThrow(() -> new TechnicalException("Cannot find clientName: " + clientName));
            currentClients.add(client);

            HttpAction action;
            try {
                if (startAuthentication(context, currentClients)) {
                    logger.debug("Redirecting to identity provider for login");
                        saveRequestedUrl(context, currentClients, config.getClients().getAjaxRequestResolver());
                        action = redirectToIdentityProvider(context, currentClients);
                } else {
                    action = unauthorized(context, currentClients);
                }
            } catch (final HttpAction e) {
                logger.debug("extra HTTP action required in Pac4jEntryPoint: {}", e.getCode());
                action = e;
            }
            bestAdapter.adapt(action, context);

        } else {
            throw new TechnicalException("The Pac4jEntryPoint has been defined without config, nor clientName: it must be defined in a <security:http> section with the pac4j SecurityFilter or CallbackFilter");
        }
    }

    public Config getConfig() {
        return config;
    }

    public void setConfig(final Config config) {
        this.config = config;
    }

    public String getClientName() {
        return clientName;
    }

    public void setClientName(final String clientName) {
        this.clientName = clientName;
    }

    @Override
    public String toString() {
        return CommonHelper.toNiceString(this.getClass(), "config", config, "clientName", clientName);
    }
}

@@ -257,32 +257,79 @@
 n.SessionStore;%0A
+import org.pac4j.core.credentials.Credentials;%0A
 import org.pac4j
@@ -363,16 +363,16 @@
 yLogic;%0A
-
 import o
@@ -649,24 +649,81 @@
 l.FindBest;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 import org.s
@@ -1500,24 +1500,114 @@
 tryPoint %7B%0A%0A
+    private static final Logger LOGGER = LoggerFactory.getLogger(Pac4jEntryPoint.class);%0A%0A
     private 
@@ -2515,16 +2515,39 @@
 t%3CClient
+%3C? extends Credentials%3E
 %3E curren
@@ -2600,16 +2600,39 @@
 l Client
+%3C? extends Credentials%3E
  client 
@@ -2930,38 +2930,38 @@
                 
-logger
+LOGGER
 .debug(%22Redirect
@@ -3371,14 +3371,14 @@
     
-logger
+LOGGER
 .deb

update to pac4j v4.0.1