
Most B2B products are not a single app. There's a web dashboard, a documentation portal, maybe a companion mobile app, a CLI tool, or an analytics SPA embedded inside the main product. Each surface exists for a good reason, but authentication has always lagged behind.
Connecting these surfaces through a shared session has meant one of two things: building your own cross-app session broker, or stitching together multiple auth vendors and syncing user state between them. Both approaches work, eventually. Neither is something you want to maintain.
Multi-App Authentication is now part of Scalekit Full Stack Auth. It extends the auth infrastructure you already have, giving every app in your product its own OAuth client, its own credentials, and its own token lifecycle, while sharing a single underlying user session. Login once on any surface; every other app recognises you.
.png)
The model is simple. Your Scalekit environment is the identity authority. Each application — web app, SPA, mobile app, CLI, desktop client — registers as an independent OAuth client within that environment. Each gets its own client_id. Web apps additionally get a client_secret for server-side flows.
When a user authenticates on any surface, Scalekit creates a session tied to the environment, not to any individual app. Any other registered application can exchange an authorization code for tokens against the same session without prompting the user to log in again. The session is shared. The tokens are scoped per client.
1. Separate credentials per appEach app has its own client_id. Web apps rotate client_secret independently. A compromised SPA client cannot call server-side Management APIs.
2. Shared session layerThe user authenticates once. Scalekit's session persists at the environment level. Subsequent auth requests from other registered apps skip the login prompt.
3. Correct OAuth flows per client typeWeb apps use Authorization Code + client_secret. SPAs and native apps enforce PKCE automatically. Public clients cannot generate secrets. The dashboard enforces this at the application type level — not a config toggle.
4. Per-app token configurationAccess token expiry can be overridden per application. A short-lived token for an analytics SPA and a longer-lived token for a backend CLI coexist in the same environment without touching each other.
Your main app lives at app.yourproduct.com. Your docs portal lives at docs.yourproduct.com — often a separate deployment, sometimes a different framework entirely.
Without a shared session layer, the docs portal either has no auth (so you can't gate content or personalise by plan), or you hand-roll cookie sharing between domains. With Multi-App Authentication, both apps register as web applications under the same environment. If the user already has an active session from the dashboard, they land on the docs page they were trying to reach — no login screen.
DashboardDocs portalApplication typeWeb AppWeb AppManagement API accessEnabledDisabledBackchannel logoutConfiguredConfigured
You have a server-side web application. Alongside it lives a SPA — an analytics dashboard, a reporting widget, a customer-facing portal that runs entirely in the browser.
SPAs cannot store secrets. Multi-App Authentication handles this by registering the SPA as a separate client type, enforcing PKCE on every auth request, and issuing no client secret. The web app and the SPA share the same user session. If the user is logged into the web app, the SPA's auth request returns an authorization code without a login prompt.
On callback, the SPA exchanges the code ,no client_secret, only the verifier stored in memory:
Your product ships a mobile companion app. The mobile app accesses the same backend API as the web app but lives in a completely different runtime — no cookies, no shared browser session, custom URI scheme callbacks.
Mobile and desktop apps register as native application types. PKCE is required, no client_secret is issued. The login flow opens the system browser, not an embedded WebView — per RFC 8252, this is the correct approach. The session sharing mechanism works across the browser boundary: if a user is already logged into your web app in Safari and opens your iOS app, they may not need to re-enter credentials.
Tokens are returned via a custom URI scheme (myapp://callback) or a universal link, then stored in the platform's secure store.
The proof is in the pudding. Ee didn't just build Multi-App Authentication for our customers, we run it ourselves.
app.scalekit.com and docs.scalekit.com run against the same Scalekit production environment. Each is registered as a separate web application with its own client_id and client_secret. The dashboard app has Management API access enabled. it needs to manage users, organizations, and credentials on behalf of authenticated users. The docs app does not. It only needs to know who the user is.
When a developer authenticates on app.scalekit.com, Scalekit creates an environment-level session. If they then navigate to docs.scalekit.com, the docs portal's auth redirect returns an authorization code immediately. The login page does not appear. Developers who are actively working in the dashboard don't hit a login wall when they switch tabs to the docs — this is the experience we wanted, and it's the one we built Multi-App Auth to enable.
Both apps configure backchannel logout URIs. When a user logs out on either surface, Scalekit sends a signed notification to both endpoints. Each backend clears its own session. Logging out of the dashboard terminates the docs session. Logging out of the docs terminates the dashboard session. A user who explicitly logs out is logged out everywhere.
Turns out, our customers wanted the same thing, and found their own way to the same pattern.
"We host our docs on GitBook and wanted to gate them for logged-in users without building a separate auth layer. We registered GitBook as a new application in Scalekit, dropped in the OIDC credentials, and that was it — our users now single sign-on seamlessly between the product and the docs. No separate login wall, no session mismatch. Took maybe twenty minutes to set up." — Head of Engineering, at a AI-powered Revenue Autopilot
Building this on our own infrastructure reinforced a few things that made it into the product:
Per-app token expiry is essential. The docs portal has different session semantics than the dashboard. A single environment-wide expiry would force a choice between over-privileged docs sessions or unnecessary friction on the dashboard.
PKCE must be enforced at the application type level, not as a toggle. Making it non-editable for SPA and native client types removes a class of misconfiguration entirely.
Backchannel logout needs to be verified, not trusted. Scalekit sends a signed JWT to your backchannel endpoint. Validate the signature against JWKS before invalidating the session.
If you're already using Scalekit Full Stack Auth, adding a new application takes under a minute.
client_id (and client_secret for web apps — shown only once)Questions? Reach us at support@scalekit.com or talk to an engineer at scalekit.com.
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is Multi-App Authentication?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Multi-App Authentication is part of Scalekit Full Stack Auth. It gives every app in your product its own OAuth client, credentials, and token lifecycle, while sharing a single underlying user session. Login once on any surface and every other app recognises you."
}
},
{
"@type": "Question",
"name": "How does the shared session work across multiple apps?",
"acceptedAnswer": {
"@type": "Answer",
"text": "When a user authenticates on any surface, Scalekit creates a session tied to the environment, not to any individual app. Any other registered application can exchange an authorization code for tokens against the same session without prompting the user to log in again."
}
},
{
"@type": "Question",
"name": "What app types does Multi-App Authentication support?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Multi-App Authentication supports web applications, single page applications (SPAs), native mobile apps, and desktop clients. Each registers as an independent OAuth client with the correct flow enforced per type — Authorization Code for web apps, PKCE for SPAs and native apps."
}
},
{
"@type": "Question",
"name": "Can SPAs use Multi-App Authentication without a client secret?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. SPAs register as a separate client type and PKCE is enforced on every auth request. No client secret is issued. The SPA shares the same user session as the web app without ever handling a secret."
}
},
{
"@type": "Question",
"name": "What happens when a user logs out?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Both apps configure backchannel logout URIs. When a user logs out on either surface, Scalekit sends a signed JWT notification to both endpoints. Each backend clears its own session. Logging out of one app terminates the session across all registered apps."
}
},
{
"@type": "Question",
"name": "Does Scalekit use Multi-App Authentication itself?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. app.scalekit.com and docs.scalekit.com run against the same Scalekit production environment, each registered as a separate web application. Authenticating on the dashboard means no login wall when navigating to the