I tried a lot of things for pac4j but I'm feeling a bit lost.
I just want to use a definition of an code authorisation flow for OIDC and then use the fetched and validated access token and id token for other requests started from my webapp. But in the examples I seem only to find examples regarding usage of Spring and other more abstracted frameworks.
I found https://www.pac4j.org/docs/callback-endpoint.html, but this seems to be for 6.0. I can't use that, because I must not use Jakarta, I have to use javax.
I managed to configure the initial redirect but now I'm stuck at the callback. It doesn't use the retrieved data or put the tokens into session.
Are there anywhere examples or unit tests I might derive how to configure, combine and call the different parts?
I'm using build.gradle with dependencies:
dependencies {
// https://mvnrepository.com/artifact/org.pac4j/jee-pac4j
implementation 'org.pac4j:jee-pac4j:6.1.0'
// https://mvnrepository.com/artifact/org.pac4j/pac4j-core
implementation 'org.pac4j:pac4j-core:5.7.0'
implementation 'org.pac4j:pac4j-oidc:5.7.0'
implementation 'org.pac4j:pac4j-javaee:5.7.0'
...
}
Unfortunately I see an class cast exception, when the authentication returns from IDP:
08-Apr-2023 17:12:09.751 SEVERE [http-nio-8080-exec-8] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [default] in context with path [/Gradle___com_example___pac4j_1_0_SNAPSHOT_war] threw exception
java.lang.ClassCastException: class org.pac4j.jee.context.JEEContext cannot be cast to class org.pac4j.core.context.JEEContext (org.pac4j.jee.context.JEEContext and org.pac4j.core.context.JEEContext are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @5ababd21)
at org.pac4j.core.http.adapter.JEEHttpActionAdapter.adapt(JEEHttpActionAdapter.java:27)
at org.pac4j.core.engine.DefaultCallbackLogic.perform(DefaultCallbackLogic.java:94)
at com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter(CustomCallbackFilter.java:75)
which points to callbackLogic.perform(context, new JEESessionStoreFactory().newSessionStore(), getConfig(), JEEHttpActionAdapter.INSTANCE, "/", true, getDefaultClient());
from my CustomCallbackFilter.java:
package com.example.sampleweb.pac4j;
import org.aeonbits.owner.ConfigFactory;
import org.pac4j.core.client.Client;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.pac4j.jee.context.JEEContext;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.engine.DefaultCallbackLogic;
import org.pac4j.core.http.adapter.JEEHttpActionAdapter;
import org.pac4j.jee.context.session.JEESessionStoreFactory;
import org.pac4j.jee.filter.CallbackFilter;
import org.pac4j.oidc.config.OidcConfiguration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
@WebFilter(urlPatterns = "/callback")
public class CustomCallbackFilter extends CallbackFilter {
private static final Logger LOGGER = Logger.getLogger(CustomCallbackFilter.class.getName());
private DefaultCallbackLogic callbackLogic;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
LOGGER.severe("init started");
super.init(filterConfig);
EisConfiguration eisConfiguration = ConfigFactory.create(EisConfiguration.class);
CustomOidcIdpConfigurationFactory idpConfigurationFactory = new CustomOidcIdpConfigurationFactory(eisConfiguration, "app1");
OidcConfiguration oidcConfiguration = idpConfigurationFactory.createOidcConfiguration();
Config config =
//new Config();
getSharedConfig();
LOGGER.severe("init using config " + config);
String client = getDefaultClient();
LOGGER.severe("init using client " + client);
callbackLogic = new DefaultCallbackLogic();
LOGGER.severe("init using callbackLogic " + callbackLogic);
setCallbackLogic(callbackLogic);
setConfig(config);
LOGGER.severe("init finished");
super.init(filterConfig);
}
@Override
protected void internalFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
LOGGER.severe("callback internalFilter started");
LOGGER.severe("callback internalFilter callbackLogic " + callbackLogic);
WebContext context = new JEEContext(request, response);
Config config = getSharedConfig();
LOGGER.severe("callback internalFilter Config " + config);
LOGGER.severe("callback internalFilter Config " + config.getSessionStoreFactory());
String defaultClient = getDefaultClient();
LOGGER.severe("callback internalFilter defaultClient " + defaultClient);
Clients clients = config.getClients();
LOGGER.severe("callback internalFilter clients " + clients);
Optional<Client> oidcClient = clients.findClient("IDP_CLIENT");
LOGGER.severe("callback internalFilter oidcClient " + oidcClient);
LOGGER.severe("callback internalFilter perform " + callbackLogic);
LOGGER.severe("callback internalFilter state " + request.getParameter("state"));
org.pac4j.core.context.JEEContext webContext = new org.pac4j.core.context.JEEContext(request, response);
callbackLogic.perform(context, new JEESessionStoreFactory().newSessionStore(), getConfig(), JEEHttpActionAdapter.INSTANCE, "/", true, getDefaultClient());
//dcl.perform(context, config.getSessionStore(), config, config.getHttpActionAdapter(), getDefaultUrl(), config.c);
//super.internalFilter(request, response, chain);
LOGGER.severe("callback internalFilter finished");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
LOGGER.severe("callback filter started");
//super.doFilter(request, response, chain);
LOGGER.severe("callback filter finished");
}
}
Looking at the server logs I print, it seems there is everything returning nicely from IDP, but the class cast is not possible because of the used JARs. As you can see above I tried to comply with the signature of the perform method an provided request/response using the alternative JEE implementation for the call, but that doesn't work either. However org.pac4j.jee.context.JEEContext; seems to be in conflict with org.pac4j.core.context.JEEContext and I don't know exactly what to do here.
Thanks for your help in advance!
Thorsten