diff --git a/docs/server/security/authentication/assets/certificates-list.png b/docs/server/security/authentication/assets/certificates-list.png
new file mode 100644
index 0000000000..ad504427a5
Binary files /dev/null and b/docs/server/security/authentication/assets/certificates-list.png differ
diff --git a/docs/server/security/authentication/assets/certificates-manage-dropdown.png b/docs/server/security/authentication/assets/certificates-manage-dropdown.png
new file mode 100644
index 0000000000..8c5c54298a
Binary files /dev/null and b/docs/server/security/authentication/assets/certificates-manage-dropdown.png differ
diff --git a/docs/server/security/authentication/assets/register-sso-server-modal.png b/docs/server/security/authentication/assets/register-sso-server-modal.png
new file mode 100644
index 0000000000..d3041f1ef1
Binary files /dev/null and b/docs/server/security/authentication/assets/register-sso-server-modal.png differ
diff --git a/docs/server/security/authentication/assets/register-sso-user-modal.png b/docs/server/security/authentication/assets/register-sso-user-modal.png
new file mode 100644
index 0000000000..9f6fdf4f3b
Binary files /dev/null and b/docs/server/security/authentication/assets/register-sso-user-modal.png differ
diff --git a/docs/server/security/authentication/sso-certificates.mdx b/docs/server/security/authentication/sso-certificates.mdx
new file mode 100644
index 0000000000..94269c338c
--- /dev/null
+++ b/docs/server/security/authentication/sso-certificates.mdx
@@ -0,0 +1,200 @@
+---
+title: "Authentication: SSO Certificates and Users"
+sidebar_label: SSO Certificates & Users
+description: "Register an SSO server certificate and SSO user entries in RavenDB, and keep SSO authentication working across certificate renewals by reusing the same key."
+sidebar_position: 6
+---
+
+import Admonition from '@theme/Admonition';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import CodeBlock from '@theme/CodeBlock';
+
+# Authentication: SSO Certificates and Users
+
+RavenDB can authenticate users who arrive through an [SSO reverse-proxy application](../sso/overview.mdx)
+— GitHub, Google, Microsoft/Entra ID, or Windows/Kerberos — instead of issuing one X.509 client certificate
+per user. The cluster needs to know two things to do this:
+
+- **Which SSO servers to trust** — registered as certificates with `Usage = SsoServer`.
+- **How to map an SSO identity to RavenDB permissions** — stored as **SSO user entries** with
+ `Usage = SsoClient`.
+
+Both are managed from **Manage Server → Certificates** in the Studio, and live in the same certificate
+list as your regular server and client certificates.
+
+
+SSO is a commercial feature gated by the RavenDB license. Registering an SSO server certificate requires
+**Cluster Admin** clearance; SSO user entries can be managed by **Operator** clearance and above.
+
+
+For end-to-end deployment of the SSO application itself, see the
+[SSO section](../sso/overview.mdx). This page focuses on the certificate-management side of the workflow.
+
+## Register an SSO server certificate
+
+The SSO server presents its public certificate to clients on `https://`. Registering that
+certificate in RavenDB tells the cluster "trust SSO identities forwarded by this server." Identification
+is by **public-key pinning hash**, not by the certificate file itself.
+
+### Studio
+
+1. Open **Manage Server → Certificates**.
+2. Click **Register SSO server**.
+3. Either upload the certificate (PEM/PFX) or paste the SSO URL — the cluster will fetch the certificate
+ from `https:///api/certificate`, validate it, and show the parsed details for confirmation.
+4. Give it a name and save.
+
+Open the **Manage user access** dropdown to find the SSO actions:
+
+
+
+**Upload SSO certificate** opens the registration modal — either fetch the certificate from the SSO URL or
+upload a file directly:
+
+
+
+Once registered, the SSO server certificate appears under a dedicated **SSO** section of the certificates
+list, alongside any existing SSO user entries:
+
+
+
+### HTTP API
+
+```http
+PUT /admin/certificates
+Content-Type: application/json
+
+{
+ "Name": "production-sso",
+ "Certificate": "",
+ "Usage": "SsoServer",
+ "SecurityClearance": "ValidUser",
+ "Permissions": {}
+}
+```
+
+To let the cluster fetch the certificate for you:
+
+```http
+GET /admin/certificates/sso/server/fetch?url=https://sso.example.com
+```
+
+This downloads `https://sso.example.com/api/certificate`, validates it, and returns the base64 bytes —
+hand them to `PUT /admin/certificates` above. The fetch is limited to **1 MB** and times out after
+**10 seconds**.
+
+
+SSO server certificates cannot be generated by RavenDB — they belong to the SSO deployment and must be
+imported. `POST /admin/certificates` with `Usage = SsoServer` is rejected.
+
+
+## Register an SSO user entry
+
+An SSO user entry is a mapping from one or more **SSO identities** to a RavenDB security clearance and
+database permissions. Each identity is a `(Provider, Domain, Identifier)` tuple:
+
+| Field | Type | Example |
+|---|---|---|
+| `Provider` | `Github` | `Google` | `Microsoft` | `Windows` | `Windows` |
+| `Domain` | string | Kerberos realm — only used when `Provider = Windows`; leave empty otherwise. |
+| `Identifier` | string | `alice@example.com`, GitHub username, etc. |
+
+Each entry must trust the SSO servers it accepts identities from. You can either:
+
+- list one or more `SsoServerPublicKeyPinningHashes` from registered SSO servers, **or**
+- set `AllowAnySsoServer = true` to accept the identity from any SSO server registered in the cluster.
+
+Listing multiple pinning hashes is how you give one user access through several SSO deployments
+(production + staging, for example) without duplicating the entry.
+
+### Studio
+
+1. **Manage Server → Certificates → Register SSO user**.
+2. Enter a **Name**, choose a **Security Clearance**, and pick the **Permissions** per database.
+3. Add one or more SSO identifiers (provider + identifier, plus a domain when the provider is
+ Windows — the Kerberos realm).
+4. Pick the trust model — either tick **Allow any SSO server**, or select the SSO servers you registered
+ above.
+5. Save.
+
+The modal collects all the entry's fields on one screen — display name, identifiers, security clearance,
+trust scope (per-server pinning or any SSO server), and per-database permissions:
+
+
+
+### HTTP API
+
+```http
+PUT /admin/certificates/sso/user
+Content-Type: application/json
+
+{
+ "Name": "alice",
+ "Usage": "SsoClient",
+ "SsoIdentifiers": [
+ { "Provider": "Google", "Domain": "", "Identifier": "alice@example.com" }
+ ],
+ "SsoServerPublicKeyPinningHashes": [""],
+ "AllowAnySsoServer": false,
+ "SecurityClearance": "ValidUser",
+ "Permissions": { "Northwind": "ReadWrite" }
+}
+```
+
+Validation rules enforced by the endpoint:
+
+- `Name` and at least one entry in `SsoIdentifiers` are required.
+- Either `AllowAnySsoServer = true` **or** at least one pinning hash.
+- Every pinning hash must reference a previously registered SSO server. Otherwise the request fails with
+ a message pointing you back to the SSO server registration step.
+- Each `(Provider, Domain, Identifier)` tuple is **unique cluster-wide** — edit the existing entry instead
+ of creating a second one for the same identity.
+
+## Renewing the SSO server certificate
+
+
+RavenDB identifies trusted SSO servers by their **public key pinning hash**, not by the certificate file.
+Every SSO user entry that doesn't have `AllowAnySsoServer = true` is pinned to one or more specific
+hashes. **If you renew the SSO server certificate with a new key pair, the hash changes and every
+non-`AllowAnySsoServer` entry stops accepting logins through that server until you re-register the new
+certificate and update each user entry's pinning list.**
+
+To keep SSO authentication working continuously across renewals, always renew the SSO server certificate
+with **the same private key** (the same Certificate Signing Request). The public key — and therefore the
+pinning hash — stays identical, and every existing SSO user entry keeps working without any change in
+RavenDB.
+
+
+This is the same mechanism RavenDB uses for [implicit trust between server and client certificates](./certificate-renewal-and-rotation.mdx#implicit-trust-by-public-key-pinning-hash) — see that section
+for the underlying details.
+
+Practical guidance:
+
+- **Let's Encrypt via the bundled SSO `certbot`** — already pins `--key-type rsa` and `--reuse-key`,
+ so renewals automatically keep the public key stable. No action is needed on the RavenDB side.
+- **Manually managed certificates** — when generating a renewal, re-use the existing CSR or private key
+ rather than creating a fresh key pair. Most ACME clients and CAs accept a CSR-based renewal explicitly
+ for this reason.
+- **If you must rotate the key** — register the new SSO server certificate as a second `SsoServer` entry
+ before retiring the old one. Update every SSO user entry to include the new pinning hash alongside the
+ old one. Once all clients are on the new certificate, you can remove the old `SsoServer` entry and the
+ old hash from the user entries.
+
+## Supported providers
+
+| `SsoProvider` | Typical `Identifier` | When to set `Domain` |
+|---|---|---|
+| `Github` | GitHub username | Not used — leave empty. |
+| `Google` | Email address | Not used — leave empty. |
+| `Microsoft` | Email or object id | Not used — leave empty. |
+| `Windows` | `user@DOMAIN` | **Required** — set to the Kerberos realm. |
+
+`Domain` is only consulted when `Provider = Windows`. For the OAuth providers it is ignored — leave it
+empty (or omit it from the JSON payload).
+
+## Related reading
+
+- [SSO Overview](../sso/overview.mdx) — what the SSO application does and how the auth flow works.
+- [Deploying the SSO application](../sso/deploying-sso-app.mdx) — installer and Docker Compose setup.
+- [Certificate Renewal & Rotation](./certificate-renewal-and-rotation.mdx#implicit-trust-by-public-key-pinning-hash) — the public-key pinning hash mechanism that underpins SSO server trust.
diff --git a/docs/server/security/overview.mdx b/docs/server/security/overview.mdx
index 8f3c0d6489..3d35841c12 100644
--- a/docs/server/security/overview.mdx
+++ b/docs/server/security/overview.mdx
@@ -47,6 +47,21 @@ In Studio, administrators can use the [Certificates View](../../server/security/
+## Single Sign-On (SSO)
+
+RavenDB can accept users authenticated by GitHub, Google, Microsoft/Entra ID, or Windows/Kerberos through a
+dedicated SSO reverse-proxy application. The cluster maps each SSO identity to a security clearance and per-database
+permissions, without distributing X.509 client certificates per user.
+
+**Read more:**
+
+- [SSO Overview](../../server/security/sso/overview.mdx)
+- [Deploying the SSO Application](../../server/security/sso/deploying-sso-app.mdx)
+- [SSO Configuration Reference](../../server/security/sso/sso-configuration.mdx)
+- [Configuring RavenDB for SSO](../../server/security/sso/configuring-ravendb-for-sso.mdx)
+
+
+
## Authorization
Authorization in RavenDB is based on the same X.509 certificates.
diff --git a/docs/server/security/sso/_category_.json b/docs/server/security/sso/_category_.json
new file mode 100644
index 0000000000..24d142addc
--- /dev/null
+++ b/docs/server/security/sso/_category_.json
@@ -0,0 +1,4 @@
+{
+ "position": 5,
+ "label": "SSO"
+}
diff --git a/docs/server/security/sso/assets/clusters-page-multiple.png b/docs/server/security/sso/assets/clusters-page-multiple.png
new file mode 100644
index 0000000000..67f789d71b
Binary files /dev/null and b/docs/server/security/sso/assets/clusters-page-multiple.png differ
diff --git a/docs/server/security/sso/assets/login-page-all-providers.png b/docs/server/security/sso/assets/login-page-all-providers.png
new file mode 100644
index 0000000000..ed3d6eb41a
Binary files /dev/null and b/docs/server/security/sso/assets/login-page-all-providers.png differ
diff --git a/docs/server/security/sso/configuring-ravendb-for-sso.mdx b/docs/server/security/sso/configuring-ravendb-for-sso.mdx
new file mode 100644
index 0000000000..d3f7dc31a5
--- /dev/null
+++ b/docs/server/security/sso/configuring-ravendb-for-sso.mdx
@@ -0,0 +1,44 @@
+---
+title: "SSO: Configuring RavenDB"
+sidebar_label: Configuring RavenDB
+description: "Where to find the cluster-side configuration steps for SSO — registering the SSO server certificate and creating SSO user entries."
+sidebar_position: 4
+---
+
+import Admonition from '@theme/Admonition';
+
+# SSO: Configuring RavenDB
+
+Once the [SSO application](./deploying-sso-app.mdx) is deployed, a RavenDB cluster needs two things to
+accept users coming through it:
+
+1. The **SSO server's public certificate**, registered with `Usage = SsoServer`.
+2. One or more **SSO user entries** (`Usage = SsoClient`) that map an upstream identity to a security
+ clearance and database permissions.
+
+Both are managed from **Manage Server → Certificates** in the Studio (or through the admin certificates
+HTTP API), alongside the cluster's regular server and client certificates. The full procedure — Studio
+flow, HTTP payloads, validation rules, supported providers, and the certificate-renewal caveat — is
+documented on a single page:
+
+
+[Authentication: SSO Certificates and Users](../authentication/sso-certificates.mdx)
+
+
+## End-to-end checklist
+
+1. Deploy the SSO application (see [Deploying the SSO Application](./deploying-sso-app.mdx)).
+2. As a **Cluster Admin**, [register the SSO server certificate](../authentication/sso-certificates.mdx#register-an-sso-server-certificate) —
+ either by fetching it from the SSO URL or by uploading it directly.
+3. As an **Operator** or higher, [create SSO user entries](../authentication/sso-certificates.mdx#register-an-sso-user-entry)
+ for each user or group, choosing the right provider, identifier, and database permissions.
+4. Users now log in at `https://./studio/`. They authenticate through the
+ provider; the SSO server issues a short-lived client certificate carrying their SSO identity; RavenDB
+ matches that identity against the registered SSO user entry and applies its permissions.
+
+
+SSO server trust is pinned by **public key**. Renewing the SSO certificate with a new key pair changes
+the pinning hash and breaks every SSO user entry pinned to the old hash. See
+[Renewing the SSO server certificate](../authentication/sso-certificates.mdx#renewing-the-sso-server-certificate)
+for the rationale and the key-rotation workaround.
+
diff --git a/docs/server/security/sso/deploying-sso-app.mdx b/docs/server/security/sso/deploying-sso-app.mdx
new file mode 100644
index 0000000000..f15d102958
--- /dev/null
+++ b/docs/server/security/sso/deploying-sso-app.mdx
@@ -0,0 +1,375 @@
+---
+title: "SSO: Deploying the SSO Application"
+sidebar_label: Deploying the SSO Application
+description: "Deploy the RavenDB SSO reverse proxy with Docker — DNS, TLS via Let's Encrypt, OAuth2 provider registration, and Kerberos/AD setup."
+sidebar_position: 2
+---
+
+import Admonition from '@theme/Admonition';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import CodeBlock from '@theme/CodeBlock';
+
+# SSO: Deploying the SSO Application
+
+The SSO application is distributed as a single Docker image (`ravendb/sso`) that bundles Nginx, the
+authentication sidecar, and `oauth2-proxy`. The [ravendb/sso](https://github.com/ravendb/sso) repository
+ships with an **interactive installer** (`install.sh` for Linux/macOS, `install.ps1` for Windows) that
+asks all the questions, pre-flights DNS and host permissions, generates a complete deployment directory,
+and optionally starts the stack. This is the recommended way to set up a new SSO server.
+
+
+Unless you have a specific reason to assemble the deployment by hand (for example because you're
+integrating into existing automation), run `install.sh` / `install.ps1`. It produces the same artifacts
+that the manual setup below describes, but with secrets generated for you, file permissions set, and DNS
+sanity-checked.
+
+
+## Prerequisites
+
+- Docker (Compose v2).
+- A public domain you control, with the ability to create DNS records.
+- At least one of:
+ - OAuth credentials for **GitHub**, **Google**, or **Microsoft/Entra ID**, or
+ - A Kerberos keytab for an Active Directory service principal.
+- For the bundled Let's Encrypt option: an **AWS account** with **Route53** hosting the SSO domain and an
+ IAM user authorized to create TXT records (DNS-01 challenge). The installer can also wire up a
+ manually-supplied certificate instead.
+
+## DNS setup
+
+The SSO server is reached at a base domain (e.g. `sso.example.com`). Each RavenDB cluster behind it is
+exposed at `.` — for example `my-cluster.sso.example.com`. You therefore need
+both an apex record and a wildcard for sub-aliases:
+
+| Type | Name | Value |
+|---|---|---|
+| `A` | `sso.example.com` | your server's public IP |
+| `CNAME` | `*.sso.example.com` | `sso.example.com` |
+
+The installer probes both records before continuing and will warn (but not block) if they are missing.
+
+## Recommended: interactive installer
+
+The installer is a single self-contained script — every template it writes (including `nlog.config` and
+the `docker-compose.yml`) is embedded inline, so you can download and run it directly without cloning the
+repository.
+
+
+
+
+Download and run:
+
+```bash
+curl -fsSL https://raw.githubusercontent.com/ravendb/sso/main/install.sh -o install.sh
+chmod +x install.sh
+./install.sh
+```
+
+Or pipe directly into Bash:
+
+```bash
+bash <(curl -fsSL https://raw.githubusercontent.com/ravendb/sso/main/install.sh)
+```
+
+
+
+
+Download and run:
+
+```powershell
+Invoke-WebRequest -Uri https://raw.githubusercontent.com/ravendb/sso/main/install.ps1 -OutFile install.ps1
+.\install.ps1
+```
+
+Or run directly from the URL:
+
+```powershell
+iex (irm https://raw.githubusercontent.com/ravendb/sso/main/install.ps1)
+```
+
+
+
+
+If you'd rather have the rest of the repository (for the manual `example/` deployment, source, or tests),
+clone it and run the script from there instead:
+
+```bash
+git clone https://github.com/ravendb/sso.git && cd sso && ./install.sh
+```
+
+The script walks through the following steps:
+
+1. **Output directory** — defaults to `./sso-deploy`. Must be empty.
+2. **Host user check** *(Linux only)* — verifies that UID `10000` exists; offers to create the
+ `ravendb-sso` system user (the SSO container runs as `10000:10000`).
+3. **SSO URL** — your public `https://sso.example.com`.
+4. **DNS sanity check** — resolves the apex `A` record and probes a random subdomain to confirm the
+ wildcard `CNAME` is in place.
+5. **TLS certificate strategy** — pick `certbot-route53` (automated Let's Encrypt via Route53 DNS-01) or
+ `manual` (you supply `fullchain.pem` and `privkey.pem`).
+6. **Authentication providers** — multi-select between GitHub, Google, Microsoft/Entra ID, and Kerberos.
+ Each selected provider expands into its own credential prompts.
+7. **Kerberos files** *(if Kerberos was chosen)* — paths to `krb5.conf` and `krb5.keytab`. On Linux the
+ script verifies that UID `10000` can read both files and offers to apply an ACL (`setfacl -m u:10000:r`)
+ if not.
+8. **Clusters** — for each RavenDB cluster, an alias (lowercase letters, digits, hyphens) and one or more
+ node URLs (HTTPS only).
+9. **Summary and confirmation**, then file generation.
+
+### What the installer produces
+
+```
+sso-deploy/
+ sso.env # SSO secrets — mode 600
+ certbot.env # AWS creds + LE email (only if cert mode = certbot) — mode 600
+ docker-compose.yml # Two services if certbot, one if manual certs
+ config/
+ settings.json # Generated cluster topology
+ nlog.config # Copied from the example
+ certs/ # Pre-created, owned by UID 10000 (populated by certbot or pre-staged)
+ logs/ # Pre-created, owned by UID 10000
+ README-deploy.md # Per-deployment quick reference
+```
+
+`OAUTH2_PROXY_COOKIE_SECRET` is generated automatically (32 hex chars). `config/`, `certs/`, and `logs/`
+are chowned to `10000:10000` so the container can write to them. After the script finishes, start the
+stack from the generated directory:
+
+```bash
+cd sso-deploy
+docker compose up -d
+```
+
+The script also offers to run that command for you as its final step.
+
+## Manual deployment with Docker Compose
+
+If you can't or don't want to run the installer, the example under `Raven.Sso/example/` in the
+[ravendb/sso](https://github.com/ravendb/sso) repository is the same layout the installer generates, just
+filled in by hand. It runs two containers:
+
+- **`certbot`** — `certbot/dns-route53`. Obtains the wildcard certificate on first start and renews every 12 hours.
+- **`sso`** — `ravendb/sso:latest`. Starts once `certbot` has produced a valid certificate, and reloads Nginx
+ every 6 hours to pick up renewals.
+
+### 1. Copy and fill the environment files
+
+The example splits environment variables into two files so AWS credentials aren't exposed to the SSO container:
+
+```bash
+cp sso.env.example sso.env
+cp certbot.env.example certbot.env
+```
+
+Edit each file with your domain, OAuth credentials, and AWS keys. The complete list of variables is on the
+[SSO application configuration](./sso-configuration.mdx) page.
+
+### 2. (Optional) Configure clusters via `settings.json`
+
+The list of RavenDB clusters the SSO server should proxy can live in `config/settings.json`:
+
+```json
+{
+ "Clusters": [
+ {
+ "ClusterUrls": ["https://a.my-cluster.example.com"],
+ "ClusterAlias": "my-cluster"
+ }
+ ]
+}
+```
+
+Alternatively, set `RAVENDBSSO_Clusters` in `sso.env` to the same JSON array — environment variables override
+file values.
+
+### 3. Start the stack
+
+```bash
+docker compose up -d
+```
+
+On first run, `certbot` requests the wildcard certificate from Let's Encrypt; this can take 1–2 minutes
+while the DNS TXT record propagates. The SSO container's `depends_on` waits for `certbot` to report healthy
+before starting Nginx.
+
+
+The example's `certbot` entrypoint pins `--key-type rsa`. RavenDB's certificate utilities only support RSA;
+do not switch this to ECDSA.
+
+
+### 4. Volumes and on-host layout
+
+```
+example/
+ sso.env # SSO env vars
+ certbot.env # certbot env vars
+ docker-compose.yml
+ config/
+ settings.json # optional — clusters can come from env vars instead
+ nlog.config # optional — logging configuration (autoReload)
+ certs/ # populated by certbot
+ live//
+ fullchain.pem
+ privkey.pem
+ logs/ # SSO + Nginx logs
+```
+
+## Quick start (single container)
+
+For local testing without Let's Encrypt, build the image directly and pass credentials on the command line:
+
+```bash
+docker build -t auth-proxy .
+
+docker run --rm -it \
+ -p 8080:8080 \
+ -e OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -base64 32) \
+ -e GITHUB_CLIENT_ID=... \
+ -e GITHUB_CLIENT_SECRET=... \
+ -e GOOGLE_CLIENT_ID=... \
+ -e GOOGLE_CLIENT_SECRET=... \
+ -e MICROSOFT_CLIENT_ID=... \
+ -e MICROSOFT_CLIENT_SECRET=... \
+ -e MICROSOFT_TENANT=common \
+ -v /path/to/app.keytab:/etc/nginx/app.keytab:ro \
+ -v /path/to/krb5.conf:/etc/krb5.conf:ro \
+ auth-proxy
+```
+
+Any combination of providers can run concurrently. Volumes for the keytab and `krb5.conf` are only needed
+when using Kerberos.
+
+After login, the SSO portal lists the clusters the user can reach — each cluster is exposed under its own
+sub-alias of the SSO domain:
+
+
+
+## Registering OAuth providers
+
+For every OAuth provider you enable, the redirect URI is
+`https:///oauth2//callback`.
+
+### GitHub
+
+1. Open [GitHub Settings → Developer settings → OAuth Apps](https://github.com/settings/developers).
+2. **New OAuth App**.
+3. Set **Homepage URL** to your SSO URL and **Authorization callback URL** to
+ `https:///oauth2/github/callback`.
+4. Generate a client secret. Set `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET`.
+
+### Google
+
+1. In [Google Cloud Console](https://console.cloud.google.com/) → **APIs & Services → Credentials**, create
+ an **OAuth 2.0 Client ID** of type **Web application**.
+2. Add `https:///oauth2/google/callback` to **Authorized redirect URIs**.
+3. Set `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`.
+
+### Microsoft / Entra ID
+
+The SSO image uses oauth2-proxy's `entra-id` provider, which supports both single-tenant and multi-tenant
+apps.
+
+1. In [Azure Portal → App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade),
+ click **New registration**.
+2. Pick **Supported account types** — single-tenant, multi-tenant, or multi-tenant + personal accounts.
+ This must match the `MICROSOFT_TENANT` value you choose.
+3. Set **Redirect URI** (Web) to `https:///oauth2/microsoft/callback`.
+4. Under **Token configuration**, add `email` as an **optional claim** for the ID token — organizational
+ accounts don't emit it by default, and the SSO server uses it as the username.
+5. Under **Certificates & secrets**, create a client secret.
+6. Set `MICROSOFT_CLIENT_ID`, `MICROSOFT_CLIENT_SECRET`, and `MICROSOFT_TENANT`:
+ - **Single-tenant**: your tenant GUID.
+ - **Multi-tenant (orgs only)**: `organizations`.
+ - **Multi-tenant + personal accounts**: `common`.
+7. For multi-tenant apps, scope access by setting `MICROSOFT_ALLOWED_TENANTS` (comma-separated tenant
+ GUIDs) and / or `MICROSOFT_ALLOWED_EMAIL_DOMAINS`. Without these allowlists a multi-tenant app accepts
+ **any** organization's users.
+
+### Cookie secret
+
+`oauth2-proxy` requires an encryption key for its session cookie.
+
+```bash
+# Single-container quick-start (32-byte base64):
+openssl rand -base64 32
+
+# docker-compose example (16/24/32-char hex):
+openssl rand -hex 16
+```
+
+Set the result as `OAUTH2_PROXY_COOKIE_SECRET`.
+
+## Kerberos / Active Directory
+
+On a domain controller (or with delegated rights):
+
+```powershell
+# 1. Create a service account, e.g. svc_docker, then map an SPN to it:
+setspn -A HTTP/app.domain.com svc_docker
+
+# 2. Export a keytab:
+ktpass /princ HTTP/app.domain.com@DOMAIN.COM `
+ /mapuser DOMAIN\svc_docker `
+ /pass YourPassword123 `
+ /out C:\temp\app.keytab `
+ /crypto All `
+ /ptype KRB5_NT_PRINCIPAL
+```
+
+Mount the keytab at `/etc/nginx/app.keytab` and supply a Kerberos client config at `/etc/krb5.conf`:
+
+```ini
+[libdefaults]
+ default_realm = DOMAIN.COM
+ dns_lookup_kdc = true
+ dns_lookup_realm = false
+
+[realms]
+ DOMAIN.COM = {
+ kdc = dc01.domain.com
+ admin_server = dc01.domain.com
+ }
+
+[domain_realm]
+ .domain.com = DOMAIN.COM
+ domain.com = DOMAIN.COM
+```
+
+If Kerberos auth fails or isn't available, Nginx falls back to OAuth automatically.
+
+## Logs
+
+All logs are written under `/app/logs/` inside the container — mount the directory to keep them on the host:
+
+| File | Source | Content |
+|---|---|---|
+| `app.log` | NLog (rotating, 7-day retention) | Startup, certificate generation, cluster polling, errors |
+| `audit.log` | NLog (rotating, 30-day retention) | Login success/failure, access denied, logout — with user and client IP |
+| `app.out.log` | stdout | Raw .NET process stdout |
+| `app.err.log` | stderr | Raw .NET process stderr |
+| `nginx-access.log` | Nginx | Standard combined access log |
+| `nginx-error.log` | Nginx | Errors and warnings |
+| `nginx-audit.log` | Nginx | Per-request audit log — real client IP, authenticated user, target host, status, response time |
+
+`nlog.config` is loaded from `/app/config/nlog.config` at startup with `autoReload="true"`, so log levels
+can be changed without restarting the container.
+
+## Troubleshooting
+
+| Symptom | Likely cause |
+|---|---|
+| `certbot` fails with a Route53 error | AWS credentials or the DNS zone isn't actually in Route53. |
+| `sso` container exits immediately | `RAVENDBSSO_Url` not set in `sso.env`. |
+| `502 Bad Gateway` shortly after startup | The .NET sidecar on `127.0.0.1:3000` is still warming up — retry. |
+| Login loops back to the provider | Wrong callback URL registered, or `OAUTH2_PROXY_COOKIE_SECRET` length is invalid (must be 16, 24, or 32 chars). |
+
+```bash
+docker logs ravendb-sso # nginx + .NET app
+docker logs certbot # certificate issues
+```
+
+## Next steps
+
+Once the SSO server is up, register its certificate and create SSO user entries in your RavenDB cluster
+following [Configuring RavenDB for SSO](./configuring-ravendb-for-sso.mdx).
diff --git a/docs/server/security/sso/overview.mdx b/docs/server/security/sso/overview.mdx
new file mode 100644
index 0000000000..c122199dbb
--- /dev/null
+++ b/docs/server/security/sso/overview.mdx
@@ -0,0 +1,71 @@
+---
+title: "SSO: Overview"
+sidebar_label: Overview
+description: "Authenticate RavenDB users through GitHub, Google, Microsoft/Entra ID, or Kerberos/AD via the RavenDB SSO reverse proxy."
+sidebar_position: 1
+---
+
+import Admonition from '@theme/Admonition';
+
+# SSO: Overview
+
+RavenDB SSO lets users access a cluster using their existing identity provider — GitHub, Google,
+Microsoft/Entra ID, or Windows/Kerberos — instead of distributing X.509 client certificates per user.
+Authentication is handled by a dedicated **SSO application** (an authenticating reverse proxy) that sits
+in front of one or more RavenDB clusters. RavenDB itself only needs to know which SSO servers it trusts
+and how to map an SSO identity to a security clearance and database permissions.
+
+
+
+## Components
+
+| Component | Role |
+|---|---|
+| **SSO application** | Nginx + .NET 10 sidecar packaged as `ravendb/sso`. Terminates TLS, runs OAuth2 / Kerberos, issues a per-user ECDSA client certificate, and proxies to RavenDB over mTLS. |
+| **`oauth2-proxy`** | Bundled inside the SSO image. Handles the OAuth2 dance for GitHub, Google, and Microsoft. |
+| **RavenDB cluster** | Trusts the SSO server's certificate and resolves the SSO identity (embedded in the per-user cert) to a registered SSO user entry. |
+
+## Authentication flow
+
+1. The browser hits the SSO URL — for example `https://my-cluster.sso.example.com/studio/`.
+2. Nginx checks for a valid JWT cookie. If none is present, it redirects to upstream auth:
+ - `/auth` — Kerberos/AD (`auth_gss`), or
+ - `/oauth` — `oauth2-proxy` for GitHub, Google, or Microsoft.
+3. After upstream auth succeeds, Nginx forwards the authenticated username to the .NET sidecar at `/auth`
+ via the `X-Auth-User` header.
+4. The sidecar generates a unique ECDSA client certificate for that user (cached by thumbprint) and issues
+ a JWT cookie containing the certificate and key paths.
+5. Nginx validates the JWT and uses the referenced certificate to open an mTLS connection to RavenDB.
+6. RavenDB sees a client certificate whose subject carries an **SSO identity extension**
+ (`Provider`, `Domain`, `Identifier` — `Domain` is only populated when `Provider = Windows`, where it
+ carries the Kerberos realm). It looks up a matching **SSO user entry** in the cluster and applies that
+ entry's security clearance and database permissions.
+
+## Trust model
+
+Two new certificate kinds are stored in the cluster:
+
+- **`Usage = SsoServer`** — the public certificate of a trusted SSO deployment. Registered once per SSO server.
+- **`Usage = SsoClient`** — an **SSO user entry**: one or more `SsoIdentifier` tuples
+ (`Provider` + `Domain` + `Identifier`, where `Domain` is only used for Windows/Kerberos) plus the
+ RavenDB permissions to grant. Each entry either:
+ - pins to specific SSO servers via `SsoServerPublicKeyPinningHashes`, or
+ - sets `AllowAnySsoServer = true` to accept the identity from any trusted SSO server.
+
+This means a single SSO user entry can grant the same RavenDB permissions to a user who logs in through
+multiple SSO deployments (production and staging, for example) by listing several pinning hashes.
+
+## Licensing
+
+
+SSO is gated by the RavenDB license. Both registering an SSO server certificate and creating an SSO user
+entry will fail with a license error if your license does not permit SSO. Registering an SSO server
+certificate also requires the **Cluster Admin** security clearance — creating SSO user entries only requires
+**Operator** clearance.
+
+
+## Next steps
+
+- [Deploying the SSO application](./deploying-sso-app.mdx) — interactive `install.sh` / `install.ps1` installer (recommended), plus the equivalent manual Docker Compose setup.
+- [SSO application configuration](./sso-configuration.mdx) — full reference of `settings.json` keys and `RAVENDBSSO_*` environment variables.
+- [Configuring RavenDB for SSO](./configuring-ravendb-for-sso.mdx) — registering SSO server certificates and SSO user entries in your cluster.
diff --git a/docs/server/security/sso/sso-configuration.mdx b/docs/server/security/sso/sso-configuration.mdx
new file mode 100644
index 0000000000..65759be073
--- /dev/null
+++ b/docs/server/security/sso/sso-configuration.mdx
@@ -0,0 +1,149 @@
+---
+title: "SSO: Configuration Reference"
+sidebar_label: Configuration Reference
+description: "Full reference of settings.json keys and RAVENDBSSO_* environment variables consumed by the RavenDB SSO application."
+sidebar_position: 3
+---
+
+import Admonition from '@theme/Admonition';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# SSO: Configuration Reference
+
+The SSO application reads its configuration from two sources, layered in this order (later sources override
+earlier ones):
+
+1. `config/settings.json` (optional).
+2. Environment variables prefixed with `RAVENDBSSO_` (or `RAVENDBSSO.`).
+
+In addition, the bundled `oauth2-proxy` and `certbot` containers read their own environment variables.
+
+## Environment-variable convention
+
+Every SSO setting can be expressed as a `RAVENDBSSO_*` environment variable. The mapping rules are:
+
+- Strip the `RAVENDBSSO_` (or `RAVENDBSSO.`) prefix.
+- Each remaining underscore becomes a `:` to denote a nested configuration key.
+- If the value parses as a JSON object or array, it is automatically flattened into nested keys.
+
+For example, `RAVENDBSSO_Clusters` containing a JSON array is equivalent to a top-level `Clusters` entry in
+`settings.json`.
+
+## SSO application settings
+
+These map to properties on `SsoSettings`:
+
+| Setting | Environment variable | Default | Required | Description |
+|---|---|---|---|---|
+| `Url` | `RAVENDBSSO_Url` | — | **Yes** | Public SSO URL, e.g. `https://sso.example.com`. Used as the CORS origin and as the basis for the host log messages. |
+| `CertificatePath` | `RAVENDBSSO_CertificatePath` | _falls back to Let's Encrypt certs in `./certs`_ | No | Path to the TLS certificate (PEM, full chain). |
+| `CertificateKeyPath` | `RAVENDBSSO_CertificateKeyPath` | _falls back to Let's Encrypt certs in `./certs`_ | No | Path to the TLS private key. |
+| `CertificateFlags` | `RAVENDBSSO_CertificateFlags` | — | No | `X509KeyStorageFlags` to use when loading the certificate. |
+| `Clusters` | `RAVENDBSSO_Clusters` | `[]` | **At least one** | List of clusters to proxy. Each entry: `{ ClusterUrls: ["https://a.host", ...], ClusterAlias: "alias" }`. Each cluster is exposed at `.`. |
+| `UserCertsDir` | `RAVENDBSSO_UserCertsDir` | `/app/users-certs` | No | Directory where per-user ECDSA client certificates are written. |
+| `JwtKeyPath` | `RAVENDBSSO_JwtKeyPath` | `/app/certs/jwt/jwt.key` | No | Path to the JWT signing (private) key. |
+| `JwtPubPath` | `RAVENDBSSO_JwtPubPath` | `/app/certs/jwt/jwt.pub` | No | Path to the JWT verification (public) key. |
+| `InternalAuthSecret` | `RAVENDBSSO_InternalAuthSecret` | _injected by `start.sh`_ | No | Shared secret that Nginx attaches as the `X-Internal-Auth` header on internal mint/validate endpoints. When set, the sidecar rejects requests that don't present it; left empty in local/dev/test runs without Nginx, in which case the check is skipped. Generated automatically inside the container — you don't normally set this yourself. |
+
+### Defining clusters
+
+
+
+
+```bash
+# single cluster
+RAVENDBSSO_Clusters=[{"ClusterUrls":["https://a.my-cluster.example.com"],"ClusterAlias":"my-cluster"}]
+
+# multiple clusters
+RAVENDBSSO_Clusters=[{"ClusterUrls":["https://a.prod.example.com"],"ClusterAlias":"prod"},{"ClusterUrls":["https://a.dev.example.com"],"ClusterAlias":"dev"}]
+```
+
+
+
+
+```json
+{
+ "Clusters": [
+ {
+ "ClusterUrls": ["https://a.my-cluster.example.com"],
+ "ClusterAlias": "my-cluster"
+ }
+ ]
+}
+```
+
+
+
+
+
+On Linux the SSO process rejects `JwtKeyPath`, `JwtPubPath`, `UserCertsDir`, `CertificatePath`, and
+`CertificateKeyPath` if they resolve outside `/app` (the SSO image's working tree) or `/etc/nginx`. This
+prevents environment-variable path injection — keep your customized paths under those directories.
+
+
+### CLI flags
+
+| Flag | Purpose |
+|---|---|
+| `--generate-keys` | Generate the JWT keypair at `JwtKeyPath` / `JwtPubPath` and exit. Used once during initial setup or when rotating keys. |
+
+## OAuth2 / `oauth2-proxy` environment variables
+
+| Variable | Required | Description |
+|---|---|---|
+| `OAUTH2_PROXY_COOKIE_SECRET` | **Yes** | Cookie-encryption secret. **16, 24, or 32 characters** (or a 32-byte base64 value for the single-container quick-start). Generate with `openssl rand -hex 16` or `openssl rand -base64 32`. |
+| `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` | One of three providers | GitHub OAuth app credentials. |
+| `GITHUB_ALLOWED_ORGANIZATIONS` | No | Comma-separated GitHub org slugs (e.g. `my-org,another-org`). Users must be public org members, or the OAuth app must be approved via GitHub's *OAuth App Access Policy*. Empty = allow all. |
+| `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET` | One of three providers | Google OAuth credentials. |
+| `GOOGLE_ALLOWED_EMAIL_DOMAINS` | No | Comma-separated permitted email domains (e.g. `example.com,corp.example.com`). Empty = allow all. |
+| `MICROSOFT_CLIENT_ID` / `MICROSOFT_CLIENT_SECRET` | One of three providers | Azure AD / Entra ID app credentials. The SSO image uses oauth2-proxy's `entra-id` provider. |
+| `MICROSOFT_TENANT` | One of three providers | A tenant GUID for **single-tenant** apps, or `common` / `organizations` / `consumers` for **multi-tenant**. `common` accepts any organization plus personal Microsoft accounts; `organizations` accepts any org but excludes personal accounts. Multi-tenant values automatically disable OIDC issuer verification (tokens come from many issuers). The Azure app registration's *Supported account types* must match, and `email` must be added as an optional ID-token claim so organizational accounts emit it (it becomes the username). |
+| `MICROSOFT_ALLOWED_TENANTS` | No | Optional tenant allowlist for multi-tenant apps — comma-separated tenant GUIDs. Empty = allow all. The personal-accounts tenant id is `9188040d-6c67-4c5b-b112-36a304b66dad`. |
+| `MICROSOFT_ALLOWED_EMAIL_DOMAINS` | No | Comma-separated permitted email domains for Microsoft sign-in. With a multi-tenant `MICROSOFT_TENANT` and an empty allowlist, **any organization's users can log in** — combine this with `MICROSOFT_ALLOWED_TENANTS` to scope access. |
+
+At least one OAuth provider must be configured unless you exclusively use Kerberos (see
+[Deploying the SSO Application](./deploying-sso-app.mdx#kerberos--active-directory)).
+
+## Certbot environment variables (Let's Encrypt example)
+
+These are read by the bundled `certbot/dns-route53` container in `Raven.Sso/example/docker-compose.yml`.
+
+| Variable | Required | Description |
+|---|---|---|
+| `SSO_DOMAIN` | **Yes** | Must resolve to the same host as `RAVENDBSSO_Url`. |
+| `CERT_EMAIL` | **Yes** | Email registered with Let's Encrypt. |
+| `AWS_ACCESS_KEY_ID` | **Yes** | AWS access key for the Route53 DNS-01 challenge. |
+| `AWS_SECRET_ACCESS_KEY` | **Yes** | Matching secret key. |
+| `AWS_SESSION_TOKEN` | No | Only for temporary AWS credentials. |
+| `AWS_REGION` | No | Default `us-east-1`. |
+| `LETSENCRYPT_STAGING` | No | Set to `true` to use Let's Encrypt's staging issuer for testing (avoids production rate limits). |
+
+## Putting it together
+
+A minimal `sso.env` for a production deployment using Google and Microsoft sign-in:
+
+```bash
+RAVENDBSSO_Url=https://sso.example.com
+RAVENDBSSO_Clusters=[{"ClusterUrls":["https://a.my-cluster.example.com"],"ClusterAlias":"my-cluster"}]
+
+OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -hex 16)
+
+GOOGLE_CLIENT_ID=...
+GOOGLE_CLIENT_SECRET=...
+GOOGLE_ALLOWED_EMAIL_DOMAINS=example.com
+
+MICROSOFT_CLIENT_ID=...
+MICROSOFT_CLIENT_SECRET=...
+MICROSOFT_TENANT=common
+MICROSOFT_ALLOWED_EMAIL_DOMAINS=example.com
+```
+
+And the matching `certbot.env`:
+
+```bash
+SSO_DOMAIN=https://sso.example.com
+CERT_EMAIL=ops@example.com
+AWS_ACCESS_KEY_ID=...
+AWS_SECRET_ACCESS_KEY=...
+```