Multi-Account Profile Switching: Solving the 'Google Login' Experience in Enterprise Apps
Think about your daily workflow in Google Workspace or Microsoft Azure. In the top-right corner, you click your profile picture and switch instantly between your personal account, your work account, and a client’s tenant—all without logging out.
Users have come to expect this seamless, multi-account profile experience in modern web applications. Yet, if you look at the product backlogs of most enterprise SaaS startups, you will find that multi-account profile switching is deprioritized to 'never.'
In this article, we’ll look at why this feature is so hard to build from scratch, how open-source identity providers like Zitadel are driving this requirement, and how Framework M makes supporting it as simple as flipping an environment variable flag.
The Sprint Dilemma: Why Nobody Builds This
When product teams plan their sprints, they focus on core features: checkout flows, reporting dashboards, or search performance. When "multi-account login" is suggested, the engineering estimation quickly explodes:
- How do we structure browser cookies? Do we issue one cookie per account or merge them?
- How do we handle active token refreshes for background sessions?
- How does the frontend track which account is currently making API requests?
- What happens when the user logs out of just one of their accounts?
Confronted with this complexity, most teams default to: "If you want to use another account, log out first, or open an incognito window." This is a compromise that degrades user experience, especially for power users like consultants, agency operators, and administrators.
Enter Zitadel and prompt=select_account
Modern open-source identity providers like Zitadel have brought enterprise-grade identity management to the masses. One of their key strengths is first-class support for the OpenID Connect (OIDC) standard parameter: prompt=select_account.
When your application initiates an authentication flow with prompt=select_account, it tells the identity provider: "Show the user their active accounts and let them select one, or sign into a new one."
However, when Zitadel redirects the user back to your application with the newly issued tokens, your application's backend must know what to do with them. If your backend is architected around a simple session.user_id = current_user model, receiving a second set of credentials will either overwrite the active session or fail entirely.
How Framework M Solves This (With One Flag)
In Framework M, we designed the session and authentication layer to support multi-account profiles natively. Enabling it requires zero custom database schema design or session routing. You simply flip a single configuration flag:
ENABLE_PROFILE_SWITCHER=True
Once enabled:
- The Desk UI automatically displays the account-switching dropdown under the user's profile avatar.
- The framework exposes endpoints like
POST /auth/switch-profileandPOST /auth/remove-profile. - The React frontend automatically invalidates caches and swaps contexts on the fly.
Under the Hood: The Multi-Account Session Model
To maintain strict security boundaries while providing a smooth user experience, Framework M uses a Backend-for-Frontend (BFF) pattern.
Instead of storing multiple OAuth tokens directly in the browser (which increases the attack surface), the browser only receives a single, opaque session cookie pointing to a server-side session manager. The actual session record is signed, encrypted, and stored server-side with a dictionary layout:
{
"active_account_id": "usr_9023_personal",
"accounts": {
"usr_9023_personal": {
"user_id": "usr_9023",
"email": "employee.profile@example.com",
"access_token": "ey...",
"refresh_token": "ref_..."
},
"usr_4892_corporate": {
"user_id": "usr_4892",
"email": "admin.profile@example.com",
"access_token": "ey...",
"refresh_token": "ref_..."
}
}
}
When an API request comes in from the browser, the BFF intercepts it, extracts the active account's tokens from the session record, and forwards them to downstream microservices.
Profile Switching vs. User Impersonation
It is important not to confuse Multi-Account Profile Switching with administrative impersonation (like "Run As" or "Sudo"). They represent different security domains and audit compliance rules:
| Dimension | Multi-Account Profile Switcher | User Impersonation ("Run As" / "Sudo") |
|---|---|---|
| Authentication Proof | Mandatory. The user must have successfully authenticated (via password, OIDC, or magic links) for every profile in the session. | Administrative delegation. A highly privileged user assumes another identity without knowing or entering their credentials. |
| Session Binding | All profiles share the same session manager instance, cookie, and absolute session timeout. | A separate temporary token or sub-session is issued, decoupled from the administrator's core session. |
| Audit Trails | Simple. Actions are logged directly under the active profile's own user ID. | Dual-actor logs are mandatory. The logs must record both the impersonator (actor/operator) and the target user (subject/context) for non-repudiation. |
Safe In-Session Logout
What happens when a user wants to log out of their corporate account on a shared machine but keep their personal session active?
Framework M implements In-Session Individual Profile Removal:
- When the user clicks "Remove" on an inactive profile, the BFF deletes that specific entry from the server-side session dictionary and invalidates the frontend cache.
- If the user removes the currently active profile, the BFF automatically swaps the
active_account_idto the remaining active account and redirects the user, ensuring they never see an unauthenticated screen. - If the user removes the last remaining profile, the session manager completely destroys the server-side session record and clears the browser cookie.
By building the complexity of multi-account session management into the core framework, we've eliminated the development overhead of one of the most requested enterprise UI patterns.
