OIDC for JEE

220 views
Skip to first unread message

Thorsten Stumpf

unread,
Apr 6, 2023, 1:42:35 PM4/6/23
to Please use https://stackoverflow.com with the pac4j tag
Hi,
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?
Many thanks in advance,
Thorsten

Thorsten Stumeson

unread,
Apr 8, 2023, 11:48:30 AM4/8/23
to Please use https://stackoverflow.com with the pac4j tag
Has nobody a glue or an working example?

I'm using build.gradle with 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.

Server log:
08-Apr-2023 17:12:04.603 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.doFilter callback filter started
08-Apr-2023 17:12:04.604 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter started
08-Apr-2023 17:12:04.604 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter callbackLogic #DefaultCallbackLogic# | clientFinder: org.pac4j.core.client.finder.DefaultCallbackClientFinder@5df97940 | errorUrl: null | savedRequestHandler: org.pac4j.core.engine.savedrequest.DefaultSavedRequestHandler@15e9d3e2 |
08-Apr-2023 17:12:06.027 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter Config org.pac4j.core.config.Config@1cacc679
08-Apr-2023 17:12:06.027 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter Config null
08-Apr-2023 17:12:06.027 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter defaultClient null
08-Apr-2023 17:12:06.028 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter clients #Clients# | callbackUrl: http://localhost:8080/Gradle___com_example___pac4j_1_0_SNAPSHOT_war/callback | clients: [#CustomOidcClient# | name: IDP_CLIENT | callbackUrl: http://localhost:8080/Gradle___com_example___pac4j_1_0_SNAPSHOT_war/callback | callbackUrlResolver: org.pac4j.core.http.callback.NoParameterCallbackUrlResolver@112b51d1 | ajaxRequestResolver: org.pac4j.core.http.ajax.DefaultAjaxRequestResolver@294b3077 | redirectionActionBuilder: org.pac4j.oidc.redirect.OidcRedirectionActionBuilder@3c32da91 | credentialsExtractor: org.pac4j.oidc.credentials.extractor.OidcExtractor@6f158587 | authenticator: org.pac4j.oidc.credentials.authenticator.OidcAuthenticator@5c7f5280 | profileCreator: org.pac4j.oidc.profile.creator.OidcProfileCreator@337eab68 | logoutActionBuilder: org.pac4j.oidc.logout.OidcLogoutActionBuilder@2c4719f0 | authorizationGenerators: [] | configuration: #OidcConfiguration# | clientId: IDP_TEST | secret: [protected] | discoveryURI: https://idp.myexample.com/idp/.well-known/openid-configuration | scope: openid | customParams: {} | clientAuthenticationMethod: null | useNonce: true | preferredJwsAlgorithm: null | maxAge: null | maxClockSkew: 30 | connectTimeout: 500 | readTimeout: 5000 | resourceRetriever: com.nimbusds.jose.util.DefaultResourceRetriever@60bb8bb | responseType: code | responseMode: null | logoutUrl: null | withState: true | stateGenerator: com.example.sampleweb.pac4j.EisValueGenerator@74fea534 | logoutHandler: #DefaultLogoutHandler# | store: #GuavaStore# | size: 10000 | timeout: 30 | timeUnit: MINUTES | | destroySession: false | | tokenValidator: null | mappedClaims: {} | allowUnsignedIdTokens: false | SSLFactory: null | privateKeyJWTClientAuthnMethodConfig: null | |] | ajaxRequestResolver: null | callbackUrlResolver: null | authorizationGenerators: [] | defaultSecurityClients: null | urlResolver: null |
08-Apr-2023 17:12:06.029 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter oidcClient Optional[#CustomOidcClient# | name: IDP_CLIENT | callbackUrl: http://localhost:8080/Gradle___com_example___pac4j_1_0_SNAPSHOT_war/callback | callbackUrlResolver: org.pac4j.core.http.callback.NoParameterCallbackUrlResolver@112b51d1 | ajaxRequestResolver: org.pac4j.core.http.ajax.DefaultAjaxRequestResolver@294b3077 | redirectionActionBuilder: org.pac4j.oidc.redirect.OidcRedirectionActionBuilder@3c32da91 | credentialsExtractor: org.pac4j.oidc.credentials.extractor.OidcExtractor@6f158587 | authenticator: org.pac4j.oidc.credentials.authenticator.OidcAuthenticator@5c7f5280 | profileCreator: org.pac4j.oidc.profile.creator.OidcProfileCreator@337eab68 | logoutActionBuilder: org.pac4j.oidc.logout.OidcLogoutActionBuilder@2c4719f0 | authorizationGenerators: [] | configuration: #OidcConfiguration# | clientId: IDP_TEST | secret: [protected] | discoveryURI: https://idp.myexample.com/idp/.well-known/openid-configuration | scope: openid | customParams: {} | clientAuthenticationMethod: null | useNonce: true | preferredJwsAlgorithm: null | maxAge: null | maxClockSkew: 30 | connectTimeout: 500 | readTimeout: 5000 | resourceRetriever: com.nimbusds.jose.util.DefaultResourceRetriever@60bb8bb | responseType: code | responseMode: null | logoutUrl: null | withState: true | stateGenerator: com.example.sampleweb.pac4j.EisValueGenerator@74fea534 | logoutHandler: #DefaultLogoutHandler# | store: #GuavaStore# | size: 10000 | timeout: 30 | timeUnit: MINUTES | | destroySession: false | | tokenValidator: null | mappedClaims: {} | allowUnsignedIdTokens: false | SSLFactory: null | privateKeyJWTClientAuthnMethodConfig: null | |]
08-Apr-2023 17:12:06.029 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter perform #DefaultCallbackLogic# | clientFinder: org.pac4j.core.client.finder.DefaultCallbackClientFinder@5df97940 | errorUrl: null | savedRequestHandler: org.pac4j.core.engine.savedrequest.DefaultSavedRequestHandler@15e9d3e2 |
08-Apr-2023 17:12:06.031 SEVERE [http-nio-8080-exec-8] com.example.sampleweb.pac4j.CustomCallbackFilter.internalFilter callback internalFilter state 1e20827450-app:app1-terminal:100000
[http-nio-8080-exec-8] WARN org.pac4j.oidc.profile.creator.TokenValidator - Preferred JWS algorithm: null not available. Using all metadata algorithms: [RS256, RS384, RS512]
[http-nio-8080-exec-8] ERROR org.pac4j.oidc.profile.creator.OidcProfileCreator - Bad User Info response, error=null


Best regards,

Thorsten

Jérôme LELEU

unread,
Apr 11, 2023, 2:57:40 AM4/11/23
to Thorsten Stumeson, Please use https://stackoverflow.com with the pac4j tag
Please use https://stackoverflow.com with the pac4j tag

--
You received this message because you are subscribed to the Google Groups "Please use https://stackoverflow.com with the pac4j tag" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pac4j-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pac4j-users/f3f1b5ae-3a51-420d-8dc2-85a0f422abd6n%40googlegroups.com.
Reply all
Reply to author
Forward
Message has been deleted
0 new messages