Properly doing a volatile login

187 views
Skip to first unread message

Björn Kautler

unread,
Oct 7, 2022, 9:06:22 PM10/7/22
to Pac4j users mailing list
Hi

I'm playing with adding SAML support to an application and have a question about a questionable tactic I used short of finding a better option, but maybe you have some valuable input.

I have a rich client and a JEE based backend.
I added pac4j with saml to the backend.
From the rich client I open an URL in the system browser that is protected by pac4j.
This initiates the Web Browser SSO SAML profile to do the login.
After this is finished, the servlet handling the invoked URL is invoked.
In that servlet I start the rich client session for the user authenticated through SAML.

Now in that http session I do not want the authenticated status to persist.
Otherwise if you close the rich client and start it again, the authentication is taken from the http session instead of requerying the IdP for authentication.
So I thought I make it short and hard and just do `request.getSession().invalidate();` in that servlet.

The question is, whether this is a good idea, or whether there is a better way to achieve that.

A side effect of this session invalidation is, that if I then logout of the IdP, the SLO calls the logout on the backend which then fails with
```
UT005023: Exception handling request to /saml/callback: java.lang.IllegalStateException: UT000010: Session is invalid EOTiI8v-zND3rX7DnkhCfilqAq11NoPy49pldl7I
        at io.under...@2.2.5.Final//io.undertow.server.session.InMemorySessionManager$SessionImpl.setAttribute(InMemorySessionManager.java:538)
        at io.undert...@2.2.5.Final//io.undertow.servlet.spec.HttpSessionImpl.setAttribute(HttpSessionImpl.java:169)
        at ....war//org.pac4j.jee.context.session.JEESessionStore.set(JEESessionStore.java:89)
```
So I suppressed this using `cfg.setLogoutHandler(new LogoutHandler() {});` in the config factory, as the http session is logged out anyway immediately.

There are two things that bug me though.
1. It feels dirty and I hope there is a better way
2. I'd like to actually end the rich-client session when this SLO request is coming in, but at least in the `LogoutHandler` I do not have the remote identity anymore where I can find it but just that session id. I guess I need to somewhere remember a mapping of session id to rich client session to handle this properly.

Regards
Björn

Jérôme LELEU

unread,
Oct 10, 2022, 1:44:41 AM10/10/22
to Björn Kautler, Pac4j users mailing list
Hi,

You have at least two options: you can tell the SAML2Client not to save the authenticated profile in session (but just in the current HTTP request): saml2Client.setSaveProfileInSession(false);
or you can do it by yourself with the ProfileManager: profileManager.removeProfiles();
Thanks.
Best regards,
Jérôme


--
You received this message because you are subscribed to the Google Groups "Pac4j users mailing list" 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/8bfcdad3-ca57-4e78-bb36-c02ff1cdf22an%40googlegroups.com.

Björn Kautler

unread,
Oct 11, 2022, 9:37:02 AM10/11/22
to Jérôme LELEU, Pac4j users mailing list
Hi Jérôme

Thanks for your response, but I didn't completely get it working
properly yet, maybe you have another helping hand.

I tried using `saml2Client.setSaveProfileInSession(false);`, but that
causes a loop in my current setup.
I have `/saml/login` bound to a servlet that should do the rich client
login and is protected by the `SecurityFilter`.
So if `/saml/login` is called, the authentication is done and
`/saml/callback` called.
`/saml/callback` has the `CallbackFilter` applied, so handles the IdP
callback and then redirects back to the original `/saml/login`.
But as the profile is not stored to the session, the `SecurityFilter`
again starts the authentication and the loop starts again.
Did you mean this somehow differently?
Should I subclass the `CallbackFilter` and do the rich client login
and logout there somehow?
Or how else?

I guess the other option with `profileManager.removeProfiles()` I
could do where I previously did quit the session, in the servlet that
handles the `/saml/login` URL.
But how do I get hold of the `profileManager`?
The docs at https://github.com/pac4j/jee-pac4j/wiki/Get-the-authenticated-user-profiles
suggest that you can do `new ProfileManager(new JEEContext(request,
response))`
to get one, but that doc is outdated, the constructor also requires a
non-null `SessionStore` as second argument.

Best regards
Björn
> You received this message because you are subscribed to a topic in the Google Groups "Pac4j users mailing list" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/pac4j-users/i8nittF5r4U/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to pac4j-users...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/pac4j-users/CAP279LxUbMpco5G5oXsjyJX40du%3DgiLWWD%3DOz6avXAWS_eQCcg%40mail.gmail.com.

Jérôme LELEU

unread,
Oct 11, 2022, 10:06:22 AM10/11/22
to Björn Kautler, Pac4j users mailing list
Hi,

In that case, not saving the profile in session leads you to a loop. So the best is to use the ProfileManager.

And I just refreshed the doc with the session store argument.

Thanks for pointing that out.
Best regards,
Jérôme

Björn Kautler

unread,
Oct 11, 2022, 12:58:04 PM10/11/22
to Jérôme LELEU, Pac4j users mailing list
Ah, great, that works like intended now, thanks.

Two more questions if you don't mind.



How do I get hold of the relay state?
I also played with IdP initiated SSO and there configured a relay
state so that I know it is IdP initiated as I need that information.
In the browser dev tools I see that the IdP is giving the relay state
to the callback URL.
But when I'm at the redirect url servlet, I cannot see how to get the
value of the relay state.
I thought it should come as a query parameter to the redirect url, but
that's not the case.



And the other question is about the logout.
How do I properly do that?
I need the remote user that is logged out, is that possible somewhere somehow?
I thought the proper way might be to configure a custom
`LogoutHandler` that is a subclass of `DefaultLogoutHandler`, forward
the calls and doing my rich-client session logout logic there.
But as far as I can see I cannot get the logged out user there, is that right?
Is there a better way?

If not, I guess I need to persist / link the "key" that is given in
the `LogoutHandler` methods to the rich-client session and then lookup
the rich-client session by that key on logout?
If that is the way to go, how do I create the link?
I do not mean technically, I mean where to properly do it?
As far as I can see I can also not get the remote user in the
`LogoutHandler#recordSession` method.
And I didn't right away find a way to get the "key" in my servlet that
does create the rich-client session and then removes the profiles with
the profile manager.

Best regards
Björn
> To view this discussion on the web visit https://groups.google.com/d/msgid/pac4j-users/CAP279Lx2J6qTFn%3Dqytb5xTgt6547%2BY-5kReEJzbxHtL0y7NXtg%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages