Granting Authority in Spring Security Based on Active Session

348 views Asked by At

Is there a straightforward way to grant authorities in Spring Security/Spring Session based on whether there is currently an active session? What I would like to do is to limit ADMIN authority to a single active session at a time.

For example:

  • Both User A and User B can potentially be granted ADMIN authority.
  • User A logs in.
    • Create session and grant authority ADMIN
  • User B logs in while user A's session is still active.
    • Create session and grant authority USER

If User B logs in when no other session is active, grant authority ADMIN. If User A logs in again when there is already an active session associated with user A, associate authority USER with the new session (leaving authority ADMIN associated with the 'old' session for user A).

2

There are 2 answers

1
Ritesh On

Assuming SessionRegistry and HttpSessionEventPublisher are already configured, we can check the existence of an active admin session as follows:

public boolean adminActiveSessionExists () {

    for(Object principal: sessionRegistry.getAllPrincipals()) {
        /* write a method hasAdminAuthority to check if principal is admin */
        if (hasAdminAuthority(principal)) {
            /* Check if there is any active admin session */
            if (sessionRegistry.getAllSessions(principal, false)
                    .stream().anyMatch(sessionInfo -> !sessionInfo.isExpired())) {

                return true;
            }
        }
    }

    return false;
}

You can then use it in your authentication logic to grant authority. Note that this will only work on a single server.

1
Vedran Pavic On

Your requirement sounds like a ConcurrentSessionControlAuthenticationStrategy but based on granted authority rather than principal (username).

This is complicated since API for retrieving sessions (Spring Session's FindByIndexNameSessionRepository) currently don't support retrieving sessions by such criteria (granted authority), or retrieving all sessions from the underlying session store. So you'd have to extend the session store to provide such capabilities.

Alternatively, you could use a different approach - you could have a single user that is granted ADMIN authority, limit the number of concurrent sessions for that user to one session, and use Spring Session's multiple session support to switch to ADMIN user when needed. Don't know if that's acceptable for you but it could be an option.