How is your experience with the OutSystems Community?
35
Views
2
Comments
Session Expires if same user login from two devices
Application Type
Reactive
Service Studio Version
11.55.79 (Build 65019)

Hi Community,

I am encountering an issue with session invalidation when a user logs into our Reactive Web App from multiple devices.

Environment Details:

  • Platform Version: OutSystems 11 (Reactive Web)

  • Environment: Staging (1 Front-End Server, 1 Back-End Server)

Scenario / Steps to Reproduce:

  1. User A logs in to the Reactive Web Application on Laptop 1.

  2. User A subsequently logs in to the same application on Laptop 2.

  3. On Laptop 1, as soon as the user triggers the next Server Action, Data Action, or Aggregate, the request fails.

  4. Service Center logs a  Role required security exception for Laptop 1's request.

Current Implementation & Observations:

  • Upon successful login, custom roles are granted programmatically using GrantRole.

  • These roles are configured as Persistent Roles (Is Persistent = Yes).

  • I am using the Outsystems user action 'User_Login' when a user login to the application

Questions:

  1. Is this standard platform behavior where User_Login invalidates active security tokens across other active browser sessions for the same user ID?

  2. What is the recommended architectural pattern if we want to allow concurrent sessions without kicking out the first device?






2023-12-26 10-35-28
OutSystems Neo
Staff
AI Generated
  1. Is this standard platform behavior?

Yes, what you’re seeing matches the standard behavior of the OutSystems Users module and the platform’s security model in O11:

  • Each browser/device has its own session, but the login state and security token are global per user (environment-wide SSO), not per browser session.
  • When you call User_Login with a given UserId, the platform issues a new security context/token for that user. The previous token(s) used by that user in other active sessions become invalid.
  • The next time any of those “old” sessions makes a server call (Server Action / Data Action / Aggregate), that request fails with a required security exception because the token is no longer valid.

This is effectively the “single active login token per user” behavior that people observe when trying to use the same user on multiple browsers/devices. It’s not configurable via a toggle – it’s how the built‑in authentication works today in O11. Number of concurrent logins and how outsystem handles if it reaches the limit

The fact that you are granting persistent roles (Is Persistent = Yes) is orthogonal: persistent roles just mean that, once granted, the roles survive across sessions/logins. They don’t change the “single active security token per user” behavior.

So, answer to Q1: Yes, calling User_Login for a user effectively invalidates existing security contexts for that same user, which is why the first device starts failing with security exceptions.

  1. How to allow concurrent sessions without kicking out the first device?

You essentially have two options, depending on how far you’re willing to move away from the built‑in Users login.


Option A – Accept platform behavior and adjust UX

If hard concurrency (same user, multiple devices simultaneously) is not a strict requirement, the simplest is to:

  • Keep using User_Login as is.
  • Catch the security exception on failed requests and redirect the affected session to the Login screen with a clear message like “Your session is no longer valid. Please log in again.”

This doesn’t give true concurrent sessions, but it avoids a “mysterious” error and gives a controlled UX.


Option B – Implement your own session tracking + conditional login

If you must support concurrent sessions, you need to implement an application-level session model and avoid triggering a fresh User_Login in a way that invalidates the previous token.

Technically, the Users module still only supports one active security token per user; you can’t configure multiple independent tokens per user. What you can do is:

  1. Minimize calls to User_Login

    • Call User_Login only once when the user first authenticates in a given browser/device.
    • After that, rely on session state (session variables) and your own logic instead of repeatedly calling User_Login for the same user.
    • If you currently call User_Login again during a flow (e.g., re-auth, switch tenant, or after granting roles), remove those extra calls and just keep the user logged in with the original session.
  2. Store application sessions in your own entity
    Create an entity, for example UserAppSession, with fields such as:

    • Id
    • UserId (Users.UserId)
    • SessionId (use GetSessionId() from the System action)
    • DeviceInfo / Browser (optional)
    • LoginDateTime
    • LastActivityOn
    • IsActive

    On login:

    • After calling User_Login, create a new UserAppSession row for the current UserId + SessionId, marked IsActive = True.
  3. Decide your concurrency policy

    You have two common patterns:

    Pattern 1 – Allow multiple sessions per user (what you want)

    • On login, do not invalidate other UserAppSession rows for the same user.
    • Each browser/device gets its own OutSystems session (SessionId) and one active UserAppSession row.
    • As long as you don’t call User_Login again for that same user from another session, the existing sessions stay valid.
    • For inactivity management, periodically update LastActivityOn and, if needed, clean up or flag IsActive = False for stale sessions (purely app-side).

    Key point: the “kicking out first device” effect happens when User_Login is called again; so you must only call User_Login on the first authentication per browser and avoid re-calls.

    Pattern 2 – Single session per user (the opposite behavior)

    For completeness: if you ever want to prevent multiple concurrent sessions (user can only be logged in from one device), you implement:

    • On login:
      • Find other active UserAppSession rows for that user.
      • Mark them inactive and/or flag them so their next request forces a logout.
      • Then create the new session row.
    • On each request (OnBeginWebRequest):
      • Use GetUserId() + GetSessionId() to read the corresponding UserAppSession.
      • If there is no active row for that SessionId, call Logout().

    This is exactly the pattern described by community members for implementing “no concurrent login” logic. Disable Concurrent Logins from the Same Account

    You don’t want this pattern in your current scenario, but it’s good to know because the behavior you have today (user losing token on second login) is conceptually similar.


Concrete recommendations for your case

Given your scenario:

  • Symptom:
    First device gets a “required security exception” as soon as you log in from a second device and trigger a new request.

  • Likely causes:

    • User_Login is called again for the same user when logging in from Laptop 2, which invalidates the token used on Laptop 1.
    • You might also be calling User_Login multiple times within the same session (e.g., after role assignment), causing unnecessary invalidations.
  • Steps to fix / enable concurrent sessions:

  1. Ensure User_Login is called exactly once per browser login:

    • Typically in your Login screen action, only after successful credential validation.
    • Do not call it again in other flows (e.g., when granting roles, changing some context, or navigating).
  2. Keep your role assignment separated from User_Login:

    • Grant persistent roles before or after the login, but don’t re-login the same user every time you adjust roles.
    • Persistent roles are stored in the DB and will be picked up in subsequent requests automatically.
  3. Test with two devices / browsers:

    • Login User A on Laptop 1 → User_Login(UserIdA) once.
    • Login User A on Laptop 2 → User_Login(UserIdA) once.
    • Confirm that you do not call User_Login again during later navigation on either device.
    • You should now see both sessions working independently, each expiring according to session timeout and idle time, as long as the login token for the user is not re-issued again.

If after ensuring a single call to User_Login per browser you still see the first session being invalidated, then you’re hitting a limitation of the current Users module authentication model, and the only way forward is to:

  • Accept this as “one active token per user” and design the UX accordingly, or
  • Move to a custom or external IdP / SSO mechanism where you manage issued tokens per device and validate them yourself (which is a more advanced architecture and comes with its own complexity).

Summary

  1. Yes, what you’re seeing is aligned with standard platform behavior: calling User_Login for a user issues a new security context that effectively invalidates existing ones, leading to required security exceptions in other active sessions for the same user. Disable Concurrent Logins from the Same Account
  2. To allow concurrent sessions:
    • Avoid multiple User_Login calls for the same user across existing sessions.
    • Optionally add your own UserAppSession entity to track sessions and control concurrency at the application level, without re-logging the user and thereby invalidating previous tokens.
This answer was AI-generated. Please read it carefully and use the forums for clarifications
2026-09-26 04-01-21
Huarlem Lima

I don't think User_Login invalidating other sessions is standard behavior. In O11 the same user can normally be logged in on several browsers at the same time, that's why there are Forge components like No concurrent login (https://www.outsystems.com/forge/component-overview/17561/no-concurrent-login-o11) built specifically to block it.

Since the error is a Role exception and not a redirect to login, it might be something in your login flow removing the role, for example a RevokeRole before the GrantRole, or some cleanup logic that runs on each login. Can you check if the user still has the role (Users app > user detail) right after logging in on Laptop 2? If the role disappears there, that's probably it.

Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.