> **Building with AI coding agents?** If you're using an AI coding agent, install the official Scalekit plugin. It gives your agent full awareness of the Scalekit API — reducing hallucinations and enabling faster, more accurate code generation.
>
> - **Claude Code**: `/plugin marketplace add scalekit-inc/claude-code-authstack` then `/plugin install <auth-type>@scalekit-auth-stack`
> - **GitHub Copilot CLI**: `copilot plugin marketplace add scalekit-inc/github-copilot-authstack` then `copilot plugin install <auth-type>@scalekit-auth-stack`
> - **Codex**: run the bash installer, restart, then open Plugin Directory and enable `<auth-type>`
> - **Skills CLI** (Windsurf, Cline, 40+ agents): `npx skills add scalekit-inc/skills --list` then `--skill <skill-name>`
>
> `<auth-type>` / `<skill-name>`: `agent-auth`, `full-stack-auth`, `mcp-auth`, `modular-sso`, `modular-scim` — [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Multi-App Authentication

Register multiple applications as OAuth clients that share a single Scalekit user session. Users authenticate once and gain access everywhere across your web app, mobile app, desktop client, and documentation site. Each application gets its own OAuth client with appropriate credentials based on its type, while all apps share the same underlying session.

[Check out the example apps](https://github.com/scalekit-inc/multiapp-demo)

<br/>

Use multi-app authentication when you ship multiple apps (web, mobile, desktop, or SPA), users expect to stay signed in across surfaces, or you need centralized session control and auditability. Each app gets its own OAuth client for clearer audit logs, safer scope boundaries, and easier maintenance. This eliminates friction from repeated logins and closes security gaps from inconsistent session handling.

```d2 pad=50
shape: sequence_diagram

User
"App A"
"App B"
"Scalekit (shared session)"

User -> "App A": Click "Login"
"App A" <> "Scalekit (shared session)": "/oauth/authorize \n Redirect with code \n /oauth/token"
"Scalekit (shared session)" -> "App A": Tokens issued

User -> "App B": Open app
"App B" <> "Scalekit (shared session)": "/oauth/authorize \n Redirect with code \n /oauth/token"
"Scalekit (shared session)" -> "App B": Tokens issued

User -> "App B": Logout
"App B" -> "Scalekit (shared session)": /oidc/logout
"Scalekit (shared session)" -> "App A": Session revoked
```

## How multi-app authentication works

1. [Register](/authenticate/fsa/multiapp/manage-apps/) each application as an OAuth client in Scalekit.
2. User logs into any app.
3. Scalekit creates a session for that user.
4. Other apps detect the session and skip the login prompt.
5. Logging out of any app terminates the shared session.
**Each app must clear its own local state:** Revoking the Scalekit session does not automatically clear your application's local state. Each app must clear its own session and stored tokens. A failed **refresh token exchange** is a reliable signal that the shared session has been revoked. For proactive sign-out across all applications, configure [back-channel logout URLs](/authenticate/fsa/multiapp/manage-apps/#configure-redirect-urls) so Scalekit can notify each app when the shared session is terminated.

## Application types and authentication flows

Each application is registered separately in Scalekit and receives its own OAuth client. Choose the application type based on whether it has a backend server that can securely store credentials:

| App Type | Description | Has Backend? | Uses Secret? | Auth Flow |
|----------|-------------|:------------:|:------------:|-----------|
| [**Web app** (Express, Django, Rails)](/authenticate/fsa/multiapp/web-app) | Server-rendered or backend-driven apps with secure secrets. | ✓ | ✓ | Authorization Code |
| [**SPA** (React, Vue, Angular)](/authenticate/fsa/multiapp/single-page-app) | Frontend-only apps running fully in the browser. | ✗ | ✗ | Auth Code + PKCE |
| [**Mobile** (iOS, Android)](/authenticate/fsa/multiapp/native-app) | iOS or Android apps using system browser flows. | ✗ | ✗ | Auth Code + PKCE |
| [**Desktop** (Electron, Tauri)](/authenticate/fsa/multiapp/native-app) | Electron or native desktop apps with deep links. | ✗ | ✗ | Auth Code + PKCE |

Even though each app has a different `client_id`, they all rely on the same Scalekit user session. Separate clients per app give you clearer audit logs, safer scope boundaries, and easier long-term maintenance.

## Implementation steps

1. **Create applications in Scalekit** — [Create applications](/authenticate/fsa/multiapp/manage-apps) in Scalekit for each of your apps. During setup, select the app type based on whether it has a backend and needs client secrets.

2. **Configure redirect URLs for each app** — Redirects are registered endpoints in Scalekit that control where users are sent during authentication flows. [Configure redirect URLs](/authenticate/fsa/multiapp/manage-apps/#configure-redirect-urls) for each application.

3. **Implement login flow for each app** — Once your applications are registered, each app follows an OAuth-based authentication flow. Use the [login implementation guide](/authenticate/fsa/implement-login/) for implementing login/signup flow in your apps.

4. **Manage sessions and token refresh** — After users successfully authenticate in any of your apps, you receive session tokens that manage their access. Use the [session management guide](/authenticate/fsa/manage-session/) to manage sessions in your apps.
**Validate access tokens on each request:** Validate access tokens by checking the issuer, audience (which must include the application's `client_id`), `iat`, and `exp`. Store tokens securely, and use the `/oauth/token` endpoint with the `refresh_token` grant to obtain new access, refresh, and ID tokens when needed.

5. **Implement logout** — Initiate logout by calling the `/oidc/logout` endpoint with the relevant parameters. Clear your local application session when refresh token exchange fails, or configure back-channel logout to proactively sign users out across all applications sharing the same session. Follow the [logout implementation guide](/authenticate/fsa/logout/) to implement logout in your apps.

## Troubleshooting

<details>
<summary>Why am I getting a redirect URI mismatch error?</summary>

The exact URI (including trailing slashes and query parameters) must match what's configured in **Dashboard > Developers > Applications > [Your App] > Redirects**. Common mismatches include:

- `http` vs `https`
- Missing or extra trailing slash
- Different port numbers in development

</details>

<details>
<summary>Why aren't my apps sharing authentication state?</summary>

Verify all applications are registered in the same Scalekit environment. Apps in different environments maintain separate session pools and cannot share authentication state.

</details>

<details>
<summary>Why are users prompted to login on every app?</summary>

Check the following:

- All apps use the same Scalekit environment URL
- The browser allows third-party cookies (required for session detection)
- The user is using the same browser across apps

</details>

<details>
<summary>Why is the refresh token being rejected?</summary>

The Scalekit session may have been revoked from another application, or the refresh token has expired. Redirect the user to log in again to establish a new session.

</details>

---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
