Announcement Announcement Module
Collapse
No announcement yet.
Invalidate user session and force re-logging Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Invalidate user session and force re-logging

    Hello,

    I am trying to force logout an user using Spring Security with OpenID provider.

    I have User with full right which can modify authorities (revoke, add roles) of others users. My question is, how to invalidate User session to force re-logging ? (cannot use SecurityContextHolder because I want to change another User session).
    I read some topic talking about SessionRegistry, so I try it but I user are not logout.
    See my code :
    applicationContext-security.xml :
    Code:
    ....
    <security:http access-denied-page="/error/403" auto-config="false" disable-url-rewriting="true">
        ... (intercept-url)
        <security:openid-login login-page="/auth/login" default-target-url="/" authentication-failure-url="/auth/login?error=true">
            ....... (openid-attribute)
        </security:openid-login>
        <security:logout invalidate-session="true" logout-success-url="/auth/login" logout-url="/auth/logout" />
        <security:session-management invalid-session-url="/auth/login">
               <security:concurrency-control max-sessions="1" session-registry-ref="sessionRegistry" expired-url="/auth/login" />
        </security:session-management>
    </security:http>
    
    <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />
    <bean id="openIdUserService" class="com.me.security.OpenIdUserDetailsService" />
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="openIdUserService"></security:authentication-provider>
    </security:authentication-manager>
    Invalidate session code :
    Code:
    // user object = User currently updated
    // invalidate user session
    List<Object> loggedUsers = sessionRegistry.getAllPrincipals();
    for (Object principal : loggedUsers) {
        if(principal instanceof User) {
            final User loggedUser = (User) principal;
            if(user.getUsername().equals(loggedUser.getUsername())) {
                List<SessionInformation> sessionsInfo = sessionRegistry.getAllSessions(principal, false);
                if(null != sessionsInfo && sessionsInfo.size() > 0) {
                    for (SessionInformation sessionInformation : sessionsInfo) {
                        LOGGER.info("Exprire now :" + sessionInformation.getSessionId());
                        sessionInformation.expireNow();
                        sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
                        // User is not forced to re-logging
                    }
                }
            }
        }
    }
    When I call this invalidate user session code, my logger print "Expire now:LONG_SESSION_ID_CODE" (so it has found some sessionInformation from SessionRegistry). But my User is not forced to logout and he keep all his current right (authorities).

    How can I perform that functionality ? That is my problem ?

  • #2
    Hello,
    I'm facing same issue. Does anyone has a solution?

    Comment


    • #3
      I think i got the reason why the user was still logged on even after the sessionInformation object was expired.

      In my code, I called both sessionInformation.expireNow() and followed by sessionRegistry.removeSessionInformation(sessionIn formation.getSessionId()).

      The problem lies in the ConcurrentSessionFilter.doFilter method.

      public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
      HttpServletRequest request = (HttpServletRequest) req;
      HttpServletResponse response = (HttpServletResponse) res;

      HttpSession session = request.getSession(false);

      if (session != null) {
      SessionInformation info = sessionRegistry.getSessionInformation(session.getI d());

      if (info != null) {
      if (info.isExpired()) {
      // Expired - abort processing
      doLogout(request, response);

      String targetUrl = determineExpiredUrl(request, info);

      if (targetUrl != null) {
      redirectStrategy.sendRedirect(request, response, targetUrl);

      return;
      } else {
      response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +
      "logins being attempted as the same user).");
      response.flushBuffer();
      }

      return;
      } else {
      // Non-expired - update last request date/time
      sessionRegistry.refreshLastRequest(info.getSession Id());
      }
      }
      }

      chain.doFilter(request, response);
      }

      In the method doFilter, since the sessioninformation is removed from the sessionRegistry, the method doLogout will never be called; hence the reason why the user is still logged in.

      To fix the problem, I do not call sessionRegistry.removeSessionInformation and it works. However, the sesionInformation object will only get removed from SessionRegistry after the user is forced to log out.

      Comment

      Working...
      X