Files
yvgude--lean-ctx/docs/guides/org-sso-setup.md
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

171 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Org Single Sign-On (OIDC) Setup
Let your team sign in to lean-ctx Cloud through your own identity provider
(Okta, Microsoft Entra ID, Google Workspace, or any OIDC-compliant OP).
Self-serve, no support ticket. Configure it once on the billing page, verify
your domain via DNS, and optionally require SSO for everyone in the org.
> **Plan:** Self-serve OIDC SSO is available on **Business** ($149/mo) and
> **Enterprise** plans. SAML SSO with SCIM provisioning is Enterprise-only.
> The org owner configures it; members just sign in.
>
> *Grandfather note:* orgs that configured OIDC while it was Team-gated
> (pre-GL #533) keep their existing SSO working. New SSO setup requires
> the `sso_oidc` entitlement (Business or Enterprise).
---
## How it works
1. You register a lean-ctx app in your IdP and paste the issuer, client ID and
client secret into **Account → Billing → Single sign-on**.
2. You prove you own the email domain by adding one DNS-TXT record.
3. Members go to the login page, click **Continue with SSO**, enter their work
email, and get redirected to your IdP. On return they have a normal
lean-ctx session — no password, account auto-provisioned and added to your
org (just-in-time).
4. Optional: flip **Require SSO** so password logins for your domain are
refused. The org owner always keeps password access (break-glass) so a
misconfigured IdP can never lock you out.
The redirect URI to register in every IdP is:
```
https://api.leanctx.com/api/auth/sso/callback
```
Required scopes: `openid email profile`. Response type: `code` (Authorization
Code flow with PKCE — lean-ctx adds PKCE automatically).
---
## Step 1 — Create the app in your IdP
### Okta
1. **Admin → Applications → Create App Integration**.
2. Sign-in method: **OIDC OpenID Connect**. Application type: **Web
Application**.
3. Sign-in redirect URI: `https://api.leanctx.com/api/auth/sso/callback`.
4. Assign the people/groups who should have access.
5. Copy **Client ID** and **Client secret**. Your **issuer** is
`https://<your-org>.okta.com` (Okta → Security → API → Authorization Servers;
use the `Issuer URI`).
### Microsoft Entra ID (Azure AD)
1. **Entra admin → App registrations → New registration**.
2. Redirect URI (type **Web**):
`https://api.leanctx.com/api/auth/sso/callback`.
3. **Certificates & secrets → New client secret**, copy the value.
4. **Overview** → copy the **Application (client) ID**.
5. Issuer:
`https://login.microsoftonline.com/<tenant-id>/v2.0`.
### Google Workspace
1. **Google Cloud Console → APIs & Services → Credentials → Create
Credentials → OAuth client ID**.
2. Application type: **Web application**.
3. Authorized redirect URI:
`https://api.leanctx.com/api/auth/sso/callback`.
4. Copy **Client ID** and **Client secret**.
5. Issuer: `https://accounts.google.com`.
> Any spec-compliant OIDC provider works. lean-ctx reads the issuer's
> `/.well-known/openid-configuration` for endpoints and JWKS, so you only need
> the issuer URL — not individual endpoint URLs.
---
## Step 2 — Configure lean-ctx
1. Sign in as the **org owner** and open **Account → Billing**.
2. In **Single sign-on (OIDC)**, fill in:
- **Email domain** — e.g. `acme.com` (the domain of your members' work
email).
- **Issuer URL** — from step 1.
- **Client ID** / **Client secret** — from step 1.
3. **Save configuration.** The secret is sealed (encrypted at rest) and never
shown again; leave the field blank on later edits to keep the stored one.
---
## Step 3 — Verify your domain
After saving, lean-ctx shows a DNS-TXT record. Add it at your DNS provider:
| Field | Value |
|-------|-------|
| Type | `TXT` |
| Name / Host | `_leanctx-sso.acme.com` |
| Value | `leanctx-sso-verify=<token shown in the dashboard>` |
Then click **Verify domain**. lean-ctx checks the record over DNS-over-HTTPS
(Cloudflare, then Google). DNS can take a few minutes to propagate — if it
isn't visible yet, wait and retry.
Domain verification is required before SSO accepts any login. It guarantees
that only the org which controls a domain can authenticate its addresses, and
that no two orgs can claim the same domain.
---
## Step 4 (optional) — Require SSO
Once the domain is verified, toggle **Require SSO for everyone in the org**.
While enabled:
- Password login and registration for your domain are refused.
- The **org owner is always exempt** (break-glass) — you can still sign in with
your password if the IdP is down.
Turn it off any time to re-enable passwords.
---
## What members experience
1. Login page → **Continue with SSO** → enter work email.
2. Redirect to your IdP, authenticate (and MFA, if your IdP enforces it).
3. Back on lean-ctx, signed in. First-time users are created automatically
(email pre-verified, no password) and added to your org.
4. They run `lean-ctx login` / configure the MCP key exactly as a
password user would — the session is identical.
---
## Security model
- **Authorization Code + PKCE (S256)** on every flow, even with a confidential
client secret.
- **ID-token verification**: JWKS signature, `iss`, `aud`, `exp`, and a
per-flow `nonce`. Tokens signed with `HS*`/`none` are rejected outright
(alg-confusion defense) — only RSA/PS/ECDSA are accepted.
- **Asserted email must be under your verified domain**, re-checked at the
callback. `email_verified:false` from the IdP is rejected.
- **Client secret** is encrypted at rest (ChaCha20-Poly1305), decrypted only
for the token exchange, never cached on the edge.
- **No API keys in URLs**: after a successful login the browser exchanges a
single-use, 60-second handoff code for the session key.
- **Owner break-glass**: enforcement never applies to the owner's email.
Full protocol contract: `docs/contracts/org-sso-oidc-v1.md`.
---
## Troubleshooting
| Symptom | Cause / fix |
|---------|-------------|
| **Continue with SSO** says no IdP found | Domain not configured or not verified yet. Finish steps 23. |
| `sso_error=verify_failed` after IdP | ID token failed validation. Check the issuer URL is exact and the client ID matches the IdP app. |
| `sso_error=idp_denied` | The IdP rejected the user (not assigned to the app, or consent denied). Assign the user/group. |
| `sso_error=expired` | The login took longer than 10 minutes, or the handoff code expired. Just start again. |
| Domain won't verify | TXT record not yet propagated, wrong host (`_leanctx-sso.<domain>`), or wrong value. Re-check and retry — DoH reads can lag your DNS edit by minutes. |
| A user can't sign in but others can | Their email domain differs from the verified domain, or the IdP reports `email_verified:false`. |
| Owner locked out with SSO required | Owners are exempt by design — use your password. If a non-owner needs in, turn off **Require SSO** temporarily. |
Still stuck? `hello@leanctx.com` or the
[Discord community](https://discord.gg/pTHkG9Hew9).