We have a scenario whereby we have a series of applications, all using spring-session (w/Redis) where a user can log in more than once to access different apps.
If an admin amends a user to add a new role (e.g. access to a new app) (a GrantedAuthority) we need that to be reflected in all the users active sessions.
The problem is, i think, that the SecurityContextHolder uses ThreadLocal storage for the SecurityContext (which in turn holds the GrantedAuthorities).
I've tried interacting with the session repository and using that to update the session info but because of the above TL storage it doesn't get reflected across the applications.
Is there a common pattern/strategy to propagate updates to role information in this way?
Thanks.
The simplest (and IMO preferred) solution would be to force your users to re-authenticate and therefore create a new
Authentication
which would then contain a freshGrantedAuthority
collection. You can use Spring Session'sFindByIndexNameSessionRepository
to obtain all sessions for a given user and then delete them. This will generateSessionDeletedEvent
which will propagate to all your apps (since they share the same Redis session store).If you must preserve active sessions things are more complicated. You can still use
FindByIndexNameSessionRepository
to obtain all sessions for a given user, but then you need to extractSecurityContext
from each session and update itsAuthentication
with new authorities and make sure that is done on all apps that share the session store. To do that you'll need to disableeraseCredentialsAfterAuthentication
on yourProviderManager
so that you can re-create theAuthentication
with new authorities (you need credentials from the originalAuthentication
). To ensureSecurityContext
is updated on all your apps you have to employ some sort of publish-subscribe mechanism in order to trigger the execution of that code.As you can see the first solution is much simpler, and more secure (since you don't need to disable
eraseCredentialsAfterAuthentication
). It's also worth noting that second solution would be simpler if Spring Session supportedHttpSessionAttributeListener
(see this ticket) since that would cover the publish-subscribe mechanism part.