From 00ce8aaf9650a1d3c6109eb4df0d16d8be3a9858 Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:56:23 +0000 Subject: [PATCH 1/7] =?UTF-8?q?Docs:=20Re-architect=20Authentication=20?= =?UTF-8?q?=E2=80=94=20move=20API=20key=20injection=20under=20Authenticati?= =?UTF-8?q?on,=20flatten=20API=20Explorer,=20deduplicate=20RBAC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fern/docs.yml | 4 +++ .../openapi-pages/extensions/explorer.mdx | 4 +-- fern/products/docs/docs.yml | 8 ++---- .../pages/api-references/api-explorer.mdx | 2 ++ .../docs/pages/authentication/rbac.mdx | 27 +++++++++++++------ .../docs/pages/changelog/2025-11-11.mdx | 2 +- .../pages/getting-started/how-it-works.mdx | 2 +- .../pages/resources/stainless-comparison.mdx | 6 ++--- .../reference/generators-yml-reference.mdx | 2 +- 9 files changed, 35 insertions(+), 22 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index 5cbb9334c..d9bb9437f 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -402,6 +402,10 @@ redirects: destination: /learn/docs/api-references/api-explorer/:slug* - source: /learn/docs/api-references/api-playground destination: /learn/docs/api-references/api-explorer/overview + - source: /learn/docs/api-references/autopopulate-api-key + destination: /learn/docs/authentication/api-key-injection + - source: /learn/docs/api-references/autopopulate-api-key/:slug* + destination: /learn/docs/authentication/api-key-injection - source: /learn/user-feedback destination: /learn/docs/user-feedback - source: /learn/docs/customization/what-is-docs-yml diff --git a/fern/products/api-def/openapi-pages/extensions/explorer.mdx b/fern/products/api-def/openapi-pages/extensions/explorer.mdx index a3056e3b3..43c4eac45 100644 --- a/fern/products/api-def/openapi-pages/extensions/explorer.mdx +++ b/fern/products/api-def/openapi-pages/extensions/explorer.mdx @@ -4,7 +4,7 @@ headline: API Explorer control (OpenAPI) description: Enable or disable the API Explorer using `x-fern-explorer` --- -The [API Explorer](/learn/docs/api-references/api-explorer/overview) is enabled by default for all endpoints. Use `x-fern-explorer` to disable or it globally or to override it per operation. This is commonly used to disable the Explorer for destructive operations, payment processing, or admin-only endpoints. +The [API Explorer](/learn/docs/api-references/api-explorer) is enabled by default for all endpoints. Use `x-fern-explorer` to disable or it globally or to override it per operation. This is commonly used to disable the Explorer for destructive operations, payment processing, or admin-only endpoints. ## Global @@ -55,4 +55,4 @@ paths: post: operationId: charge_payment # Remains disabled (global setting applies) -``` \ No newline at end of file +``` diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index c2c8e18a6..fcf3f4176 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -255,13 +255,9 @@ navigation: path: ./pages/api-references/sdk-snippets.mdx - page: HTTP snippets path: ./pages/api-references/http-snippets.mdx - - section: API Explorer + - page: API Explorer + path: ./pages/api-references/api-explorer.mdx slug: api-explorer - contents: - - page: Overview - path: ./pages/api-references/api-explorer.mdx - - page: Auto-populate API keys - path: ./pages/api-references/autopopulate-api-key.mdx - page: Audiences path: ./pages/api-references/audiences.mdx - page: Customize API Reference layout diff --git a/fern/products/docs/pages/api-references/api-explorer.mdx b/fern/products/docs/pages/api-references/api-explorer.mdx index 9d5b29056..d0f0003ed 100644 --- a/fern/products/docs/pages/api-references/api-explorer.mdx +++ b/fern/products/docs/pages/api-references/api-explorer.mdx @@ -22,6 +22,8 @@ Once a user sets their authentication credentials, their credentials persist thr Authentication credentials are only stored client-side using cookies. No sensitive user information is collected or stored. +To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection). + ## Multiple environments When multiple server URLs are configured in [OpenAPI](/learn/api-definitions/openapi/extensions/server-names) or the [Fern Definition](/learn/api-definition/fern/api-yml/environments), users can switch between environments (e.g., production and sandbox) from a dropdown in the API Explorer. The selected environment persists as they navigate between pages. diff --git a/fern/products/docs/pages/authentication/rbac.mdx b/fern/products/docs/pages/authentication/rbac.mdx index dff955fea..d538795ce 100644 --- a/fern/products/docs/pages/authentication/rbac.mdx +++ b/fern/products/docs/pages/authentication/rbac.mdx @@ -48,13 +48,11 @@ roles: Fern uses a [browser cookie](/learn/docs/security/overview) called `fern_token` to identify authenticated users and their roles. If this cookie isn't present when a user tries to access restricted content, Fern redirects them to your login page. -You can set up this authentication using either JWT or OAuth: +RBAC uses the same `fern_token` cookie as [API key injection](/learn/docs/authentication/api-key-injection). You can combine both features in a single token. Set up authentication using either JWT or OAuth: -**You are responsible for creating and setting the `fern_token` cookie in your authentication system.** - -Upon login, set a JWT for the user using a secret key that Fern provides. The JWT must include a `fern` claim with a `roles` array: +Set a `fern_token` cookie containing a JWT signed with a secret key from Fern. The JWT must include a `fern` claim with a `roles` array: ```json { @@ -64,17 +62,30 @@ Upon login, set a JWT for the user using a secret key that Fern provides. The JW } ``` - +To also inject API keys, add a `playground` object to the same `fern` claim: + +```json +{ + "fern": { + "roles": ["partners"], + "playground": { + "initial_state": { + "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } + } + } + } +} +``` + +See [API key injection](/learn/docs/authentication/api-key-injection) for the full `fern` payload reference and a complete callback endpoint example. -When a user needs authentication, Fern initiates an OAuth flow and redirects them to your authentication endpoint. You configure your OAuth endpoints to return user role information. +Fern initiates an OAuth flow and redirects users to your authentication endpoint. Configure your OAuth endpoints to return user role information. See [Set up OAuth for RBAC](/learn/docs/authentication/set-up-oauth) for a step-by-step guide. - - diff --git a/fern/products/docs/pages/changelog/2025-11-11.mdx b/fern/products/docs/pages/changelog/2025-11-11.mdx index 424a3c923..f077e6ec8 100644 --- a/fern/products/docs/pages/changelog/2025-11-11.mdx +++ b/fern/products/docs/pages/changelog/2025-11-11.mdx @@ -28,4 +28,4 @@ Then, the API Explorer automatically displays all available authentication optio Authentication dropdown in the API Explorer -Learn more about configuring authentication in the [API Explorer documentation](/learn/docs/api-references/api-explorer/overview). +Learn more about configuring authentication in the [API Explorer documentation](/learn/docs/api-references/api-explorer). diff --git a/fern/products/docs/pages/getting-started/how-it-works.mdx b/fern/products/docs/pages/getting-started/how-it-works.mdx index 5f5bee683..b85babe09 100644 --- a/fern/products/docs/pages/getting-started/how-it-works.mdx +++ b/fern/products/docs/pages/getting-started/how-it-works.mdx @@ -105,7 +105,7 @@ The merged PR triggers a Fern GitHub Action. The action retrieves your API speci ### Deploy to hosting platform -The processed content is deployed to Vercel as a documentation site with an embedded [API explorer](/learn/docs/api-references/api-explorer/overview) that allows users to test endpoints directly within the documentation. +The processed content is deployed to Vercel as a documentation site with an embedded [API explorer](/learn/docs/api-references/api-explorer) that allows users to test endpoints directly within the documentation. Vercel Edge middleware handles the underlying routing, authentication, and performance optimization. diff --git a/fern/products/docs/pages/resources/stainless-comparison.mdx b/fern/products/docs/pages/resources/stainless-comparison.mdx index 9baa049fe..cf8baedf8 100644 --- a/fern/products/docs/pages/resources/stainless-comparison.mdx +++ b/fern/products/docs/pages/resources/stainless-comparison.mdx @@ -15,7 +15,7 @@ Choose Fern for enterprise requirements, regulated industries, or production-cri | **Maturity** | Production-ready, stable APIs | Early access, breaking changes expected | | **Authoring** | [Visual editor](/learn/docs/writing-content/fern-editor) + Git | Git only | | **Enterprise features** | [RBAC](/learn/docs/authentication/rbac), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | -| **API testing** | [Interactive explorer](/learn/docs/api-references/api-explorer/overview) | None | +| **API testing** | [Interactive explorer](/learn/docs/api-references/api-explorer) | None | | **Deployment** | Cloud + [full-stack self-hosted](/learn/docs/self-hosted/overview) | Static files only | ## Detailed feature comparison @@ -46,11 +46,11 @@ Stainless uses Git-based workflows for all content authoring. Fern supports both -Stainless doesn't provide an interactive testing environment. Fern's [API Explorer](/learn/docs/api-references/api-explorer/overview) enables in-browser endpoint testing with automatic credential injection. +Stainless doesn't provide an interactive testing environment. Fern's [API Explorer](/learn/docs/api-references/api-explorer) enables in-browser endpoint testing with automatic credential injection. | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer/overview) with [auto-populated credentials](/learn/docs/api-references/autopopulate-api-key), WebSocket, and audio streaming support | ❌ None | +| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection), WebSocket, and audio streaming support | ❌ None | | **SDK documentation** | ✅ [Multi-language support](/learn/docs/api-references/sdk-snippets) | ✅ Language-specific pages | | **API spec formats** | ✅ [OpenAPI, AsyncAPI, gRPC, OpenRPC, Fern](/learn/docs/api-references/generate-api-ref) | ⚠️ OpenAPI + Stainless config only |
diff --git a/fern/products/sdks/reference/generators-yml-reference.mdx b/fern/products/sdks/reference/generators-yml-reference.mdx index a87e409b7..273385536 100644 --- a/fern/products/sdks/reference/generators-yml-reference.mdx +++ b/fern/products/sdks/reference/generators-yml-reference.mdx @@ -60,7 +60,7 @@ groups: ## `auth-schemes` -Define authentication methods for your SDKs and the [API Explorer](/learn/docs/api-references/api-explorer/overview) that your endpoints can reference. Authentication schemes defined in `generators.yml` take precedence over authentication schemes [defined in your spec](/learn/api-definitions/openapi/authentication). +Define authentication methods for your SDKs and the [API Explorer](/learn/docs/api-references/api-explorer) that your endpoints can reference. Authentication schemes defined in `generators.yml` take precedence over authentication schemes [defined in your spec](/learn/api-definitions/openapi/authentication). After defining an authentication scheme, you must use [`api.auth`](#auth) to apply it as the default across all endpoints. Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings) if you need different auth behavior per language. From 72b18ae0f1723e6929661b7eaa7278a079bbca3e Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 20:11:19 +0000 Subject: [PATCH 2/7] Fix: capitalize 'API Explorer' casing per Vale --- fern/products/docs/pages/getting-started/how-it-works.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fern/products/docs/pages/getting-started/how-it-works.mdx b/fern/products/docs/pages/getting-started/how-it-works.mdx index b85babe09..bbdb2a6b6 100644 --- a/fern/products/docs/pages/getting-started/how-it-works.mdx +++ b/fern/products/docs/pages/getting-started/how-it-works.mdx @@ -105,7 +105,7 @@ The merged PR triggers a Fern GitHub Action. The action retrieves your API speci ### Deploy to hosting platform -The processed content is deployed to Vercel as a documentation site with an embedded [API explorer](/learn/docs/api-references/api-explorer) that allows users to test endpoints directly within the documentation. +The processed content is deployed to Vercel as a documentation site with an embedded [API Explorer](/learn/docs/api-references/api-explorer) that allows users to test endpoints directly within the documentation. Vercel Edge middleware handles the underlying routing, authentication, and performance optimization. From 60c204582e1783b5aad6a64db310712736a68b4d Mon Sep 17 00:00:00 2001 From: "fern-api[bot]" <115122769+fern-api[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 20:19:27 +0000 Subject: [PATCH 3/7] Fix: update API Explorer redirects to single-page path --- fern/docs.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index d9bb9437f..f247a2f9b 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -395,13 +395,11 @@ redirects: destination: /learn/docs/api-references/customize-api-reference-layout#configuration-options - source: /learn/docs/api-references/server-urls - destination: /learn/docs/api-references/api-explorer/overview#multiple-environments - - source: /learn/docs/api-references/api-explorer - destination: /learn/docs/api-references/api-explorer/overview + destination: /learn/docs/api-references/api-explorer#multiple-environments - source: /learn/docs/api-references/api-playground/:slug* destination: /learn/docs/api-references/api-explorer/:slug* - source: /learn/docs/api-references/api-playground - destination: /learn/docs/api-references/api-explorer/overview + destination: /learn/docs/api-references/api-explorer - source: /learn/docs/api-references/autopopulate-api-key destination: /learn/docs/authentication/api-key-injection - source: /learn/docs/api-references/autopopulate-api-key/:slug* @@ -652,7 +650,7 @@ redirects: - source: /learn/docs/alternatives/mintlify destination: /learn/docs/getting-started/overview - source: /learn/docs/api-references/api-explorer/advanced-configuration - destination: /learn/docs/api-references/api-explorer/overview + destination: /learn/docs/api-references/api-explorer - source: /learn/docs/enterprise/self-hosted destination: /learn/docs/self-hosted/overview - source: /learn/docs/content/visual-editor-beta From 6c49fc6e0b0171ba067ab7eb9e393a1bc87ab484 Mon Sep 17 00:00:00 2001 From: Devin Logan Date: Wed, 11 Feb 2026 16:38:03 -0500 Subject: [PATCH 4/7] restructure info --- fern/docs.yml | 20 +- fern/products/docs/docs.yml | 14 +- .../pages/api-references/api-explorer.mdx | 2 +- .../api-references/autopopulate-api-key.mdx | 308 ------------------ .../products/docs/pages/ask-fern/features.mdx | 2 +- .../docs/pages/ask-fern/slack-app.mdx | 2 +- .../docs/pages/ask-fern/what-is-ask-fern.mdx | 2 +- .../authentication/api-key-injection.mdx | 23 ++ .../docs/pages/authentication/jwt-setup.mdx | 234 +++++++++++++ .../{set-up-oauth.mdx => oauth-setup.mdx} | 36 +- .../docs/pages/authentication/overview.mdx | 31 +- .../docs/pages/authentication/rbac.mdx | 99 +----- .../docs/pages/changelog/2026-01-17.mdx | 2 +- .../docs/pages/changelog/2026-02-11.mdx | 4 +- .../enterprise/self-hosted-authentication.mdx | 4 +- fern/products/docs/pages/navigation/tabs.mdx | 2 +- .../pages/resources/stainless-comparison.mdx | 12 +- .../products/docs/pages/security/overview.mdx | 4 +- 18 files changed, 361 insertions(+), 440 deletions(-) delete mode 100644 fern/products/docs/pages/api-references/autopopulate-api-key.mdx create mode 100644 fern/products/docs/pages/authentication/api-key-injection.mdx create mode 100644 fern/products/docs/pages/authentication/jwt-setup.mdx rename fern/products/docs/pages/authentication/{set-up-oauth.mdx => oauth-setup.mdx} (64%) diff --git a/fern/docs.yml b/fern/docs.yml index f247a2f9b..ce1413e9a 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -351,7 +351,7 @@ redirects: - source: /learn/docs/building-and-customizing-your-docs/custom-domain destination: /learn/docs/preview-publish/setting-up-your-domain - source: /learn/docs/building-and-customizing-your-docs/rbac - destination: /learn/docs/authentication/rbac + destination: /learn/docs/authentication/rbac/overview - source: /learn/docs/building-and-customizing-your-docs/search destination: /learn/docs/customization/search @@ -400,10 +400,20 @@ redirects: destination: /learn/docs/api-references/api-explorer/:slug* - source: /learn/docs/api-references/api-playground destination: /learn/docs/api-references/api-explorer - - source: /learn/docs/api-references/autopopulate-api-key - destination: /learn/docs/authentication/api-key-injection - - source: /learn/docs/api-references/autopopulate-api-key/:slug* - destination: /learn/docs/authentication/api-key-injection + + # Authentication subsection redirects + - source: /learn/docs/authentication/rbac + destination: /learn/docs/authentication/rbac/overview + - source: /learn/docs/authentication/set-up-oauth + destination: /learn/docs/authentication/oauth-setup + - source: /learn/docs/authentication/rbac/jwt-setup + destination: /learn/docs/authentication/jwt-setup + - source: /learn/docs/authentication/rbac/oauth-setup + destination: /learn/docs/authentication/oauth-setup + - source: /learn/docs/authentication/api-key-injection/jwt-setup + destination: /learn/docs/authentication/jwt-setup + - source: /learn/docs/authentication/api-key-injection/oauth-setup + destination: /learn/docs/authentication/oauth-setup - source: /learn/user-feedback destination: /learn/docs/user-feedback - source: /learn/docs/customization/what-is-docs-yml diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index fcf3f4176..a2343bbc9 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -290,14 +290,16 @@ navigation: contents: - page: Overview path: ./pages/authentication/overview.mdx - - page: Role based access control (RBAC) + - page: Role-based access control (RBAC) path: ./pages/authentication/rbac.mdx - slug: rbac - - page: Set up OAuth for RBAC - path: ./pages/authentication/set-up-oauth.mdx - slug: set-up-oauth - page: API key injection - path: ./pages/api-references/autopopulate-api-key.mdx + path: ./pages/authentication/api-key-injection.mdx + - page: JWT setup + path: ./pages/authentication/jwt-setup.mdx + slug: jwt-setup + - page: OAuth setup + path: ./pages/authentication/oauth-setup.mdx + slug: oauth-setup - page: SSO path: ./pages/authentication/sso.mdx - page: Password protection diff --git a/fern/products/docs/pages/api-references/api-explorer.mdx b/fern/products/docs/pages/api-references/api-explorer.mdx index d0f0003ed..933fc82a0 100644 --- a/fern/products/docs/pages/api-references/api-explorer.mdx +++ b/fern/products/docs/pages/api-references/api-explorer.mdx @@ -22,7 +22,7 @@ Once a user sets their authentication credentials, their credentials persist thr Authentication credentials are only stored client-side using cookies. No sensitive user information is collected or stored. -To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection). +To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection/overview). ## Multiple environments diff --git a/fern/products/docs/pages/api-references/autopopulate-api-key.mdx b/fern/products/docs/pages/api-references/autopopulate-api-key.mdx deleted file mode 100644 index ed2383e0e..000000000 --- a/fern/products/docs/pages/api-references/autopopulate-api-key.mdx +++ /dev/null @@ -1,308 +0,0 @@ ---- -title: Autopopulate API keys -subtitle: Allow users to log in and automatically populate their API keys in the API Explorer. ---- - - - -Fern can integrate with your authentication flow, allowing users to log in and have their API key automatically populated with the click of a button. - -
- - -User credentials are stored only in browser cookies and never transmitted to Fern's servers. Learn more in the [Security overview](/learn/docs/security/overview). - - -## The `fern` payload - -API key injection works by reading a `fern` claim from a JWT stored in the user's browser. The `fern` claim contains a `playground` object that tells the API Explorer what values to pre-fill. - -The top-level structure is: - -```json -{ - "fern": { - "playground": { - "initial_state": { ... }, - "env_state": { ... } - } - } -} -``` - -| Field | Description | -|---|---| -| `initial_state` | Default values applied to all API Explorer requests. | -| `env_state` | Per-environment overrides that are merged on top of `initial_state` when the user selects a matching environment. | - -### Auth types - -The `initial_state.auth` object supports bearer token and basic authentication. - - -```json Bearer -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "eyJhbGciOiJIUzI1c" - } - } - } - } -} -``` - -```json Basic -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "basic": { - "username": "your_username", - "password": "your_password" - } - } - } - } - } -} -``` - - -### Custom headers and parameters - -You can also pre-fill headers, path parameters, and query parameters instead of (or along with) auth credentials. Values are applied to any matching fields in the API Explorer. - -```json -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "eyJhbGciOiJIUzI1c" - }, - "headers": { - "API-Version": "2024-02-02" - }, - "path_parameters": { - "plantId": "plant_1234" - }, - "query_parameters": { - "sort": "DESCENDING" - } - } - } - } -} -``` - -### Multiple API keys - -To provide multiple API keys (for example, one per application), set `bearer_token` to a JSON-encoded array of key-value objects. Each object maps an application name to its key. - -```json -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "[{\"Greenhouse app\": \"sk-greenhouse-abc123\"}, {\"Garden app\": \"sk-garden-def456\"}]" - } - } - } - } -} -``` - -The API Explorer displays a dropdown so the user can choose which application key to use for requests. - -### Per-environment keys - -Use `env_state` to provide different credentials for each environment (for example, production vs. staging). Each key in `env_state` is matched against the selected environment URL using substring matching. - -```json -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "default-token" - } - }, - "env_state": { - "prod": { - "auth": { - "bearer_token": "prod-token-abc123" - } - }, - "staging": { - "auth": { - "bearer_token": "staging-token-def456" - } - } - } - } - } -} -``` - -When the user selects an environment containing `prod` (such as `https://api.prod.example.com`), the API Explorer uses `prod-token-abc123`. The `env_state` values are merged on top of `initial_state`: auth is replaced entirely, while headers, path parameters, and query parameters are shallow-merged. - -You can combine multiple API keys with per-environment keys: - -```json -{ - "fern": { - "playground": { - "env_state": { - "prod": { - "auth": { - "bearer_token": "[{\"Greenhouse app\": \"sk-prod-abc\"}, {\"Garden app\": \"sk-prod-def\"}]" - } - }, - "dev": { - "auth": { - "bearer_token": "[{\"Greenhouse app\": \"sk-dev-abc\"}, {\"Garden app\": \"sk-dev-def\"}]" - } - } - } - } - } -} -``` - -## Integrating with your auth flow - -API key injection requires a JWT containing the `fern` payload described above to be stored in the user's browser as a cookie called `fern_token`. There are two ways to set this up: - -* **JWT:** You handle the entire auth flow and set the `fern_token` cookie yourself. -* **OAuth:** You give Fern access, and Fern initiates the OAuth handshake process directly. - - - - -1. When a user clicks the **Login** button in the API Explorer, they're redirected to your authentication page. -2. After successful authentication, your system sets a cookie called `fern_token` in the user's browser. -3. This token is a [JWT](https://jwt.io) signed with a secret key from Fern. The JWT payload contains the `fern` claim with the user's API key. - - - - - -#### Set up - -To enable API key injection with JWT: -1. Reach out to Fern to get your secret key. -1. Send Fern the URL of your authentication page. This is where users are redirected after clicking the **Login** button in the API Explorer. -1. Add logic to your service to set the `fern_token` cookie when a user logs in. - - -This Next.js endpoint handles the callback from your authentication page. It reads the `state` parameter to determine where to redirect the user, mints a `fern_token` JWT using [jose](https://github.com/panva/jose), sets it as a cookie, and redirects the user back to the docs. - -```typescript title="app/api/fern-token/route.ts" -import { SignJWT } from "jose"; -import { cookies } from "next/headers"; -import { type NextRequest, NextResponse } from "next/server"; - -export async function GET(req: NextRequest): Promise { - const domain = getDomain(req); // your logic to determine the docs domain - - // use the state param to determine redirect location - const returnTo = req.nextUrl.searchParams.get("state"); - const redirectLocation = returnTo ?? `https://${domain}`; - - // fetch the user's API key and secret (from your config or database) - const apiKey = await getApiKeyForUser(); - const secret = await getSecretForDomain(domain); - - if (!apiKey || !secret) { - // redirect with an error if credentials are missing - const url = new URL(redirectLocation); - url.searchParams.set("error", "missing_credentials"); - return NextResponse.redirect(url); - } - - // mint the JWT using the secret key - const fernToken = await mintFernToken({ secret, apiKey }); - - if (!fernToken) { - const url = new URL(redirectLocation); - url.searchParams.set("error", "token_creation_failed"); - return NextResponse.redirect(url); - } - - // set the fern_token as a cookie on the docs domain - const cookieJar = await cookies(); - cookieJar.set("fern_token", fernToken, { - httpOnly: true, - secure: true, - sameSite: "lax", - domain, - }); - - // redirect the user back to the docs - return NextResponse.redirect(redirectLocation); -} - -const encoder = new TextEncoder(); - -async function mintFernToken({ - secret, - apiKey, - payload, -}: { - secret: string; - apiKey: string; - payload?: Record; -}): Promise { - const jwtPayload = payload ?? { - fern: { - playground: { - initial_state: { - auth: { - bearer_token: apiKey, - }, - }, - }, - }, - }; - - return await new SignJWT(jwtPayload) - .setProtectedHeader({ alg: "HS256", typ: "JWT" }) - .setIssuedAt() - .setExpirationTime("1d") // set to any value - .setIssuer("https://buildwithfern.com") - .sign(encoder.encode(secret)); // sign using the secret provided by Fern -} -``` - - - - - -1. When a user clicks the **Login** button in the API Explorer, Fern initiates an OAuth flow by making a request to your authorization endpoint. -1. The user is redirected to your OAuth provider's login page where they authenticate using your existing auth system. -1. After successful authentication, your OAuth provider redirects back to Fern with an authorization code, which Fern exchanges for an access token at your token endpoint. -1. Fern sets a `fern_token` cookie containing the user's authentication credentials and automatically populates their API key in the API Explorer. - - - - - -#### Set up - -To enable API key injection with OAuth: -1. Set up an authenticated account for Fern so Fern can authorize users on your behalf. -1. Configure your OAuth application to return user API keys when Fern requests them. - -Then, send Fern the following items: -- The client ID and client secret for Fern's authenticated account -- The URL of your authentication endpoint. This is where users are redirected after clicking the **Login** button in the API Explorer. -- The URL of your token endpoint. This is where Fern exchanges codes for tokens. - - - - diff --git a/fern/products/docs/pages/ask-fern/features.mdx b/fern/products/docs/pages/ask-fern/features.mdx index 1f99277e1..e3ba154b6 100644 --- a/fern/products/docs/pages/ask-fern/features.mdx +++ b/fern/products/docs/pages/ask-fern/features.mdx @@ -63,7 +63,7 @@ https://{{PAGE_URL}}?query={{QUERY2}} ## Role-based access control -Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/rbac). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. +Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/rbac/overview). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. This works at all levels, from entire sections down to individual pages and conditional content within pages. diff --git a/fern/products/docs/pages/ask-fern/slack-app.mdx b/fern/products/docs/pages/ask-fern/slack-app.mdx index 27b80bf5f..44d16305e 100644 --- a/fern/products/docs/pages/ask-fern/slack-app.mdx +++ b/fern/products/docs/pages/ask-fern/slack-app.mdx @@ -62,7 +62,7 @@ Use the `/fern` slash command in any channel to adjust the settings: | Command | Description | Example | |---------|-------------|---------| | **respond_to** | Controls whether the Ask Fern bot responds to all messages (`all`), reponds only when directly mentioned with `@Ask Fern` (`mentions_only`), or determines when to respond to messages depending on context (`auto`). Set to `auto` by default. | `/fern respond_to all` | -| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/docs/authentication/rbac) configured) | `/fern roles developer,admin` | +| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/docs/authentication/rbac/overview) configured) | `/fern roles developer,admin` | | **show** | Show the current settings | `/fern show` | | **help** | Get help with Ask Fern slash commands | `/fern help` | diff --git a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx index 26f3bdbf1..41798996d 100644 --- a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx +++ b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx @@ -68,7 +68,7 @@ ai-search: Fern automatically processes your documentation pages and Fern-generated SDK code, breaking them into semantic chunks and converting each chunk into a vector using sentence embedding models. They're stored in a database that serves as Ask Fern's search index. - When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/rbac) configured, Ask Fern filters results based on the user's permissions. + When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/rbac/overview) configured, Ask Fern filters results based on the user's permissions. Ask Fern uses the retrieved chunks as context to generate accurate answers with [citations](/learn/docs/ai-features/ask-fern/features#citations) for the user. If the initial context isn't sufficient, it performs an additional keyword search. diff --git a/fern/products/docs/pages/authentication/api-key-injection.mdx b/fern/products/docs/pages/authentication/api-key-injection.mdx new file mode 100644 index 000000000..837494ed0 --- /dev/null +++ b/fern/products/docs/pages/authentication/api-key-injection.mdx @@ -0,0 +1,23 @@ +--- +title: Autopopulate API keys +subtitle: Allow users to log in and automatically populate their API keys in the API Explorer. +--- + + + +Fern can integrate with your authentication flow, allowing users to log in and have their API key automatically populated with the click of a button. + +
+ + +User credentials are stored only in browser cookies and never transmitted to Fern's servers. Learn more in the [Security overview](/learn/docs/security/overview). + + +## How it works + +When a user logs in, a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie is set in their browser. This token is a JWT containing a `fern.playground` claim that tells the API Explorer what values to pre-fill — API keys, headers, or other credentials. + +The token can be set in two ways: + +- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. +- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — You give Fern access, and Fern initiates the OAuth handshake process directly. diff --git a/fern/products/docs/pages/authentication/jwt-setup.mdx b/fern/products/docs/pages/authentication/jwt-setup.mdx new file mode 100644 index 000000000..b33e7181d --- /dev/null +++ b/fern/products/docs/pages/authentication/jwt-setup.mdx @@ -0,0 +1,234 @@ +--- +title: JWT setup +subtitle: Self-managed authentication for RBAC and API key injection +--- + +JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). You handle the entire auth flow and set the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie yourself, giving you full control over how users authenticate to your site, what roles they're assigned, and what API keys are injected into the API Explorer. + +## How it works + +1. When a user clicks the **Login** button, they're redirected to your authentication page. +2. After successful authentication, your system sets a cookie called `fern_token` in the user's browser. +3. This token is a [JWT](https://jwt.io) signed with a secret key from Fern. The JWT payload contains a `fern` claim with the user's roles, API keys, or both. + + + + + +## Set up + + + +Reach out to Fern to get your secret key and send them the URL of your authentication page. This is where users are redirected after clicking the **Login** button in the API Explorer. + + + +The JWT payload must include a `fern` claim. What you put inside depends on which features you're using: + + +```json RBAC only +{ + "fern": { + "roles": ["partners"] + } +} +``` + +```json API key injection only +{ + "fern": { + "playground": { + "initial_state": { + "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } + } + } + } +} +``` + +```json Both combined +{ + "fern": { + "roles": ["partners"], + "playground": { + "initial_state": { + "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } + } + } + } +} +``` + + +For [API key injection](/learn/docs/authentication/api-key-injection), the `playground` object supports bearer tokens, basic auth, custom headers, and query parameters: + +```json API key injection +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "eyJhbGciOiJIUzI1c" + }, + "headers": { + "API-Version": "2024-02-02" + }, + "path_parameters": { + "plantId": "plant_1234" + }, + "query_parameters": { + "sort": "DESCENDING" + } + } + } + } +} +``` + +You can also provide multiple API keys or per-environment keys: + + + +To provide multiple API keys (for example, one per application), set `bearer_token` to a JSON-encoded array of key-value objects. Each object maps an application name to its key. + +```json API key injection +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "[{\"Greenhouse app\": \"sk-greenhouse-abc123\"}, {\"Garden app\": \"sk-garden-def456\"}]" + } + } + } + } +} +``` + +The API Explorer displays a dropdown so the user can choose which application key to use for requests. + + + +Use `env_state` to provide different credentials for each environment (for example, production vs. staging). Each key in `env_state` is matched against the selected environment URL using substring matching. + +```json title="API key injection" +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "default-token" + } + }, + "env_state": { + "prod": { + "auth": { + "bearer_token": "prod-token-abc123" + } + }, + "staging": { + "auth": { + "bearer_token": "staging-token-def456" + } + } + } + } + } +} +``` + +When the user selects an environment containing `prod` (such as `https://api.prod.example.com`), the API Explorer uses `prod-token-abc123`. The `env_state` values are merged on top of `initial_state`: auth is replaced entirely, while headers, path parameters, and query parameters are shallow-merged. + + + + + +Add logic to your service to sign the JWT and set it as a `fern_token` cookie when a user logs in. + + +This Next.js endpoint handles the callback from your authentication page. It reads the `state` parameter to determine where to redirect the user, mints a `fern_token` JWT using [jose](https://github.com/panva/jose), sets it as a cookie, and redirects the user back to the docs. + +```typescript title="app/api/fern-token/route.ts" +import { SignJWT } from "jose"; +import { cookies } from "next/headers"; +import { type NextRequest, NextResponse } from "next/server"; + +export async function GET(req: NextRequest): Promise { + const domain = getDomain(req); // your logic to determine the docs domain + + // use the state param to determine redirect location + const returnTo = req.nextUrl.searchParams.get("state"); + const redirectLocation = returnTo ?? `https://${domain}`; + + // fetch the user's API key, roles, and secret (from your config or database) + const apiKey = await getApiKeyForUser(); + const roles = await getRolesForUser(); + const secret = await getSecretForDomain(domain); + + if (!secret) { + // redirect with an error if credentials are missing + const url = new URL(redirectLocation); + url.searchParams.set("error", "missing_credentials"); + return NextResponse.redirect(url); + } + + // mint the JWT using the secret key + const fernToken = await mintFernToken({ secret, apiKey, roles }); + + if (!fernToken) { + const url = new URL(redirectLocation); + url.searchParams.set("error", "token_creation_failed"); + return NextResponse.redirect(url); + } + + // set the fern_token as a cookie on the docs domain + const cookieJar = await cookies(); + cookieJar.set("fern_token", fernToken, { + httpOnly: true, + secure: true, + sameSite: "lax", + domain, + }); + + // redirect the user back to the docs + return NextResponse.redirect(redirectLocation); +} + +const encoder = new TextEncoder(); + +async function mintFernToken({ + secret, + apiKey, + roles, +}: { + secret: string; + apiKey?: string; + roles?: string[]; +}): Promise { + const fern: Record = {}; + + if (roles) { + fern.roles = roles; + } + + if (apiKey) { + fern.playground = { + initial_state: { + auth: { + bearer_token: apiKey, + }, + }, + }; + } + + return await new SignJWT({ fern }) + .setProtectedHeader({ alg: "HS256", typ: "JWT" }) + .setIssuedAt() + .setExpirationTime("1d") // set to any value + .setIssuer("https://buildwithfern.com") + .sign(encoder.encode(secret)); // sign using the secret provided by Fern +} +``` + + + diff --git a/fern/products/docs/pages/authentication/set-up-oauth.mdx b/fern/products/docs/pages/authentication/oauth-setup.mdx similarity index 64% rename from fern/products/docs/pages/authentication/set-up-oauth.mdx rename to fern/products/docs/pages/authentication/oauth-setup.mdx index c6bc701a0..b7d2a269d 100644 --- a/fern/products/docs/pages/authentication/set-up-oauth.mdx +++ b/fern/products/docs/pages/authentication/oauth-setup.mdx @@ -1,9 +1,22 @@ --- -title: Set up OAuth for RBAC -subtitle: Integrate your OAuth provider with Fern Docs to authenticate users and assign roles +title: OAuth setup +subtitle: Fern-managed authentication for RBAC and API key injection --- -This guide walks you through connecting your OAuth provider to Fern so that users are authenticated and assigned roles for [role-based access control (RBAC)](/learn/docs/authentication/rbac). If you haven't already, start by [defining your roles](/learn/docs/authentication/rbac#define-all-the-roles-in-your-docsyml) in `docs.yml`. +OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). You give Fern access to your OAuth provider, and Fern initiates the OAuth handshake process directly — handling the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie for you. + +## How it works + +1. When a user clicks the **Login** button, Fern initiates an OAuth flow by making a request to your authorization endpoint. +1. The user is redirected to your OAuth provider's login page where they authenticate using your existing auth system. +1. After successful authentication, your OAuth provider redirects back to Fern with an authorization code, which Fern exchanges for an access token at your token endpoint. +1. Fern sets a `fern_token` cookie containing the user's roles and credentials, enabling RBAC and automatically populating API keys in the API Explorer. + + + + + +## Set up @@ -28,7 +41,7 @@ Fern will need the following details to configure OAuth authentication: - [ ] Issuer URL (e.g. `https://`) -If your client is connected to an API, you may need to specify an audience in the authentication request. +If your client is connected to an API, you may need to specify an audience in the authentication request. The updated authorization URL may look like this: `https:///oauth2/authorize?audience=` @@ -40,8 +53,12 @@ Send these details to support@buildwithfern.com or in your dedicated Slack chann Wait for Fern to configure OAuth. You will receive a notification when the site is ready to use authentication. - -Add a custom claim to your OAuth provider's token response. This claim will be used to set the user's roles in Fern Docs. The resulting token response should look something like this: + +The final step depends on which features you're using. + + + +Add a custom claim to your OAuth provider's token response so that Fern can determine each user's roles. The resulting token response should look something like this: ```json {12-15} { @@ -91,6 +108,11 @@ To add a custom claim to Auth0, you need to create a **custom action**. This act If you are using a different OAuth provider, reach out to Fern with any questions on setting up a custom claim.
+ + +Configure your OAuth application to return user API keys when Fern requests tokens. Set up an authenticated account for Fern so Fern can authorize users on your behalf, and configure your OAuth application to return user API keys when Fern requests them. + + - \ No newline at end of file + diff --git a/fern/products/docs/pages/authentication/overview.mdx b/fern/products/docs/pages/authentication/overview.mdx index fc91e521d..fcee2c167 100644 --- a/fern/products/docs/pages/authentication/overview.mdx +++ b/fern/products/docs/pages/authentication/overview.mdx @@ -3,29 +3,32 @@ title: Overview of authentication options description: Understand the different authentication options Fern offers --- -Fern supports three ways to restrict access to your documentation: - -- **RBAC** — Control which content different users can see and supports [API key injection](/learn/docs/authentication/api-key-injection). Users authenticate via JWT or [OAuth](/learn/docs/authentication/set-up-oauth). Recommended for most use cases. -- **SSO** — Require login without role management. Good for internal docs where all users see the same content. -- **Password protection** — A single shared password for the entire site. Good for pre-release docs or basic access restriction. - - -Learn how Fern handles user credentials and authentication in the [Security overview](/learn/docs/security/overview). - - -Learn more about Fern's authentication options: +Fern offers several ways to control access to your documentation, from simple password protection to granular role-based access control. Granular access for different audiences - JWT or OAuth flows available + Autopopulate API keys in the API Explorer - Basic functionality and simple setup + Require login without role management - Shared password for simple access control + A single shared password for the entire site + +## How authentication works + +[RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection) are powered by the same mechanism: a [browser cookie](/learn/docs/security/overview) called `fern_token` that tells Fern who the user is and what they can access. + +Both features share the same token, so you can implement them together — a single `fern_token` can carry user roles for RBAC and API keys for the API Explorer at the same time. + +There are two ways to set up the `fern_token`: + +- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. +- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — Fern initiates the OAuth handshake with your provider. + +[SSO](/learn/docs/authentication/sso) also uses the `fern_token` but has its own setup process. [Password protection](/learn/docs/authentication/password-protection) works differently — it uses a shared password rather than per-user tokens. diff --git a/fern/products/docs/pages/authentication/rbac.mdx b/fern/products/docs/pages/authentication/rbac.mdx index d538795ce..ac7e77224 100644 --- a/fern/products/docs/pages/authentication/rbac.mdx +++ b/fern/products/docs/pages/authentication/rbac.mdx @@ -6,16 +6,12 @@ description: Learn how to restrict access to your documentation using role-based -## Introduction - -Fern allows you to restrict parts of your navigation to individuals with specific roles. RBAC enables you to create different levels of access for different user types within your documentation. +Fern allows you to restrict parts of your navigation to individuals with specific roles. RBAC enables you to create different levels of access for different user types within your documentation. You can combine RBAC with [API key injection](/learn/docs/authentication/api-key-injection) in a single token. When RBAC is configured, [Ask Fern](/learn/docs/ai-features/ask-fern/overview) automatically respects these permissions so users only receive answers from content they're authorized to view. ### Use cases -Role-based access control is helpful for scenarios such as: - - **Partner documentation**: Provide exclusive API documentation to integration partners while keeping internal docs private - **Beta features**: Share new features with beta users before general release - **Internal documentation**: Restrict sensitive documentation to employees only @@ -26,15 +22,11 @@ Role-based access control is helpful for scenarios such as: Every user automatically has the `everyone` role, including unauthenticated visitors. Pages marked with the `everyone` role are publicly accessible without needing to log in. -If a user visits content that requires authentication (i.e., content not marked as visible to `everyone`), Fern checks for an authentication cookie to determine the user's roles. If the user lacks the required role or isn't authenticated, Fern redirects them to the login URL you provided during setup. - -## Set up RBAC +If a user visits content that requires authentication (i.e., content not marked as visible to `everyone`), Fern checks the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to determine the user's roles. If the user lacks the required role or isn't authenticated, Fern redirects them to the login URL you provided during setup. - +## Set up -### Define all the `roles` in your docs.yml - -Start by using a `roles` key to define all the different roles: +To enable RBAC, define your roles in `docs.yml` and configure authentication: ```yml docs.yml roles: @@ -44,99 +36,44 @@ roles: - admins ``` -### Configure authentication via a `fern_token` - -Fern uses a [browser cookie](/learn/docs/security/overview) called `fern_token` to identify authenticated users and their roles. If this cookie isn't present when a user tries to access restricted content, Fern redirects them to your login page. - -RBAC uses the same `fern_token` cookie as [API key injection](/learn/docs/authentication/api-key-injection). You can combine both features in a single token. Set up authentication using either JWT or OAuth: - - - -Set a `fern_token` cookie containing a JWT signed with a secret key from Fern. The JWT must include a `fern` claim with a `roles` array: - -```json -{ - "fern": { - "roles": ["partners"] - } -} -``` - -To also inject API keys, add a `playground` object to the same `fern` claim: - -```json -{ - "fern": { - "roles": ["partners"], - "playground": { - "initial_state": { - "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } - } - } - } -} -``` - -See [API key injection](/learn/docs/authentication/api-key-injection) for the full `fern` payload reference and a complete callback endpoint example. - - - - -Fern initiates an OAuth flow and redirects users to your authentication endpoint. Configure your OAuth endpoints to return user role information. - -See [Set up OAuth for RBAC](/learn/docs/authentication/set-up-oauth) for a step-by-step guide. - - - - -### Contact Fern for setup +Then set up the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) using either method: -When you're ready to implement RBAC, contact support@buildwithfern.com. +- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. +- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. -If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), notify Fern during this step. +If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), let Fern know during setup. - +## Restricting content -### Access control within navigation +### In navigation -You can designate viewers on the following navigation items: -- `products` -- `versions` -- `tabs` -- `sections` -- `pages` -- `api references` -- `changelogs` +You can assign `viewers` to the following navigation items: `products`, `versions`, `tabs`, `sections`, `pages`, `api references`, and `changelogs`. If you don't specify viewers, the content will be visible to any _authenticated_ user. To make content publicly accessible, explicitly set viewers to `everyone`. ```yml docs.yml {6-7, 13-15} navigation: - tab: Home - layout: + layout: - page: Welcome # this page is public path: pages/welcome.mdx - viewers: - - everyone + viewers: + - everyone - tab: Documentation layout: - page: Overview # this page is visible to all logged-in users - path: pages/overview.mdx + path: pages/overview.mdx - section: Beta Release # this section is visible to beta-users and admins viewers: - beta-users - admins - contents: + contents: ... ``` Viewership is inherited. For example, if a section can only be viewed by `admins`, then all its pages and nested sections can also only be viewed by admins. -### Access control within MDX pages - -You can restrict specific content within your MDX pages to users with certain roles. This allows you to show different content to different user types on the same page. - -#### Basic usage +### In MDX pages Use the `` component to conditionally render content based on user roles: @@ -148,8 +85,6 @@ Use the `` component to conditionally render content based on user roles: ``` -#### Multiple roles - You can specify multiple roles. Content will be visible to users who have **any** of the specified roles: ```mdx diff --git a/fern/products/docs/pages/changelog/2026-01-17.mdx b/fern/products/docs/pages/changelog/2026-01-17.mdx index d27ecc662..72e6e10be 100644 --- a/fern/products/docs/pages/changelog/2026-01-17.mdx +++ b/fern/products/docs/pages/changelog/2026-01-17.mdx @@ -22,4 +22,4 @@ The `` component now supports `products` and `versions` props, allowing you You can also use the `not` prop to invert the condition, showing content when the current product or version does not match. -Learn more about the [If component](/learn/docs/authentication/rbac#access-control-within-mdx-pages). +Learn more about the [If component](/learn/docs/authentication/rbac/overview#access-control-within-mdx-pages). diff --git a/fern/products/docs/pages/changelog/2026-02-11.mdx b/fern/products/docs/pages/changelog/2026-02-11.mdx index 3f5585678..330de6061 100644 --- a/fern/products/docs/pages/changelog/2026-02-11.mdx +++ b/fern/products/docs/pages/changelog/2026-02-11.mdx @@ -1,9 +1,9 @@ ## API key injection for self-hosted docs -Self-hosted deployments support [API key injection](/learn/docs/authentication/api-key-injection) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. +Self-hosted deployments support [API key injection](/learn/docs/authentication/api-key-injection/overview) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. Learn more about [self-hosted authentication](/learn/docs/self-hosted/authentication#api-key-injection). ## Multiple API keys and per-environment keys -API key injection supports [multiple API keys](/learn/docs/authentication/api-key-injection#multiple-api-keys) and [per-environment credentials](/learn/docs/authentication/api-key-injection#per-environment-keys). Provide multiple keys as a JSON-encoded array in `bearer_token`, and use `env_state` to set different credentials per environment with substring matching. +API key injection supports [multiple API keys](/learn/docs/authentication/api-key-injection/overview#multiple-api-keys) and [per-environment credentials](/learn/docs/authentication/api-key-injection/overview#per-environment-keys). Provide multiple keys as a JSON-encoded array in `bearer_token`, and use `env_state` to set different credentials per environment with substring matching. diff --git a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx index 4886d8a80..54a640552 100644 --- a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx +++ b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx @@ -203,7 +203,7 @@ ENV FERN_AUTH_DENYLIST="/api-reference/(.*)" ## API key injection -You can enable [API key injection](/learn/docs/authentication/api-key-injection) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. +You can enable [API key injection](/learn/docs/authentication/api-key-injection/overview) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. Add `FERN_API_KEY_INJECTION_ENABLED` to your Dockerfile alongside the basic token verification variables: @@ -222,4 +222,4 @@ ENV FERN_AUTH_ALLOWLIST="/(.*)" RUN fern-generate ``` -With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/api-key-injection) for the full `fern` payload reference. +With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/api-key-injection/overview) for the full `fern` payload reference. diff --git a/fern/products/docs/pages/navigation/tabs.mdx b/fern/products/docs/pages/navigation/tabs.mdx index 3a4e4efcc..4807f309a 100644 --- a/fern/products/docs/pages/navigation/tabs.mdx +++ b/fern/products/docs/pages/navigation/tabs.mdx @@ -133,7 +133,7 @@ theme: ## Tab variants -Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/rbac). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. +Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/rbac/overview). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. Use **variants** for different perspectives on the same content area (REST vs. GraphQL, beginner vs. advanced). Use **tabs** for completely different documentation sections (guides vs. API Reference). diff --git a/fern/products/docs/pages/resources/stainless-comparison.mdx b/fern/products/docs/pages/resources/stainless-comparison.mdx index cf8baedf8..69be2a007 100644 --- a/fern/products/docs/pages/resources/stainless-comparison.mdx +++ b/fern/products/docs/pages/resources/stainless-comparison.mdx @@ -14,7 +14,7 @@ Choose Fern for enterprise requirements, regulated industries, or production-cri |------------|------|-----------| | **Maturity** | Production-ready, stable APIs | Early access, breaking changes expected | | **Authoring** | [Visual editor](/learn/docs/writing-content/fern-editor) + Git | Git only | -| **Enterprise features** | [RBAC](/learn/docs/authentication/rbac), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | +| **Enterprise features** | [RBAC](/learn/docs/authentication/rbac/overview), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | | **API testing** | [Interactive explorer](/learn/docs/api-references/api-explorer) | None | | **Deployment** | Cloud + [full-stack self-hosted](/learn/docs/self-hosted/overview) | Static files only | @@ -50,7 +50,7 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection), WebSocket, and audio streaming support | ❌ None | +| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection/overview), WebSocket, and audio streaming support | ❌ None | | **SDK documentation** | ✅ [Multi-language support](/learn/docs/api-references/sdk-snippets) | ✅ Language-specific pages | | **API spec formats** | ✅ [OpenAPI, AsyncAPI, gRPC, OpenRPC, Fern](/learn/docs/api-references/generate-api-ref) | ⚠️ OpenAPI + Stainless config only |
@@ -58,11 +58,11 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor -Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/rbac) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. +Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/rbac/overview) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/rbac) for internal vs. public sites | ❌ None | +| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/rbac/overview) for internal vs. public sites | ❌ None | | **API versioning** | ✅ [Multi-version support](/learn/docs/configuration/site-level-settings) with availability states and per-version content | ❌ None | | **Multi-product sites** | ✅ [Multiple products](/learn/docs/configuration/site-level-settings) in unified documentation | ⚠️ Basic tabs (Guides/Reference) |
@@ -87,8 +87,8 @@ Stainless's [authentication](https://www.stainless.com/docs/docs-platform/advanc | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/rbac) | ❌ None | -| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/api-references/autopopulate-api-key) | ⚠️ API keys for Stainless service only | +| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/rbac/overview) | ❌ None | +| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/authentication/api-key-injection/overview) | ⚠️ API keys for Stainless service only |
diff --git a/fern/products/docs/pages/security/overview.mdx b/fern/products/docs/pages/security/overview.mdx index 4d9caf93f..1cd530c2d 100644 --- a/fern/products/docs/pages/security/overview.mdx +++ b/fern/products/docs/pages/security/overview.mdx @@ -13,8 +13,8 @@ Fern's documentation platform is built with security as a core principle, using Fern supports [multiple authentication methods](/learn/docs/authentication/overview) to secure your documentation. All methods use a client-side `fern_token` cookie stored entirely in the browser: -- [Role-Based Access Control (RBAC)](/learn/docs/authentication/rbac) controls which users can access specific documentation content based on their roles (stores user roles) -- [API key injection](/learn/docs/authentication/api-key-injection) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) +- [Role-Based Access Control (RBAC)](/learn/docs/authentication/rbac/overview) controls which users can access specific documentation content based on their roles (stores user roles) +- [API key injection](/learn/docs/authentication/api-key-injection/overview) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) - [Single Sign-On (SSO)](/learn/docs/authentication/sso) integrates with your existing identity provider for seamless authentication (stores identity provider tokens) These cookies are managed entirely client-side and automatically cleared when the user logs out or the session expires. This approach ensures that sensitive credentials remain under your control and are never exposed to Fern's infrastructure. From 616e61ce853e001c3e708fc59606b41a02d60594 Mon Sep 17 00:00:00 2001 From: Devin Logan Date: Wed, 11 Feb 2026 21:21:05 -0500 Subject: [PATCH 5/7] clarity and structure edits --- fern/docs.yml | 14 +++++--- fern/products/docs/docs.yml | 15 ++++---- .../authentication/api-key-injection.mdx | 16 ++++----- .../docs/pages/authentication/jwt-setup.mdx | 18 +++++----- .../docs/pages/authentication/oauth-setup.mdx | 23 +++++------- .../docs/pages/authentication/overview.mdx | 4 +-- .../docs/pages/authentication/rbac.mdx | 26 +++++--------- .../docs/pages/authentication/sso.mdx | 36 ++++++------------- 8 files changed, 66 insertions(+), 86 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index ce1413e9a..ca499c8ce 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -405,15 +405,19 @@ redirects: - source: /learn/docs/authentication/rbac destination: /learn/docs/authentication/rbac/overview - source: /learn/docs/authentication/set-up-oauth - destination: /learn/docs/authentication/oauth-setup + destination: /learn/docs/authentication/auth-setup/oauth-setup + - source: /learn/docs/authentication/jwt-setup + destination: /learn/docs/authentication/auth-setup/jwt-setup + - source: /learn/docs/authentication/oauth-setup + destination: /learn/docs/authentication/auth-setup/oauth-setup - source: /learn/docs/authentication/rbac/jwt-setup - destination: /learn/docs/authentication/jwt-setup + destination: /learn/docs/authentication/auth-setup/jwt-setup - source: /learn/docs/authentication/rbac/oauth-setup - destination: /learn/docs/authentication/oauth-setup + destination: /learn/docs/authentication/auth-setup/oauth-setup - source: /learn/docs/authentication/api-key-injection/jwt-setup - destination: /learn/docs/authentication/jwt-setup + destination: /learn/docs/authentication/auth-setup/jwt-setup - source: /learn/docs/authentication/api-key-injection/oauth-setup - destination: /learn/docs/authentication/oauth-setup + destination: /learn/docs/authentication/auth-setup/oauth-setup - source: /learn/user-feedback destination: /learn/docs/user-feedback - source: /learn/docs/customization/what-is-docs-yml diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index a2343bbc9..d29152176 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -294,12 +294,15 @@ navigation: path: ./pages/authentication/rbac.mdx - page: API key injection path: ./pages/authentication/api-key-injection.mdx - - page: JWT setup - path: ./pages/authentication/jwt-setup.mdx - slug: jwt-setup - - page: OAuth setup - path: ./pages/authentication/oauth-setup.mdx - slug: oauth-setup + - section: Auth setup + slug: auth-setup + contents: + - page: JWT setup + path: ./pages/authentication/jwt-setup.mdx + slug: jwt-setup + - page: OAuth setup + path: ./pages/authentication/oauth-setup.mdx + slug: oauth-setup - page: SSO path: ./pages/authentication/sso.mdx - page: Password protection diff --git a/fern/products/docs/pages/authentication/api-key-injection.mdx b/fern/products/docs/pages/authentication/api-key-injection.mdx index 837494ed0..ce0ba9c38 100644 --- a/fern/products/docs/pages/authentication/api-key-injection.mdx +++ b/fern/products/docs/pages/authentication/api-key-injection.mdx @@ -5,19 +5,19 @@ subtitle: Allow users to log in and automatically populate their API keys in the -Fern can integrate with your authentication flow, allowing users to log in and have their API key automatically populated with the click of a button. +API key injection lets users log in and have their API keys automatically populated in the [API Explorer](/learn/docs/api-references/api-explorer). You can combine API key injection with [RBAC](/learn/docs/authentication/rbac) in a single token.
+## How it works + +When a user logs in, a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie is set in their browser containing a `fern.playground` claim that tells the API Explorer what values to pre-fill — API keys, headers, or other credentials. + User credentials are stored only in browser cookies and never transmitted to Fern's servers. Learn more in the [Security overview](/learn/docs/security/overview). -## How it works - -When a user logs in, a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie is set in their browser. This token is a JWT containing a `fern.playground` claim that tells the API Explorer what values to pre-fill — API keys, headers, or other credentials. - -The token can be set in two ways: +## Setup -- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. -- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — You give Fern access, and Fern initiates the OAuth handshake process directly. +- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. +- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — You give Fern access, and Fern initiates the OAuth handshake process directly. diff --git a/fern/products/docs/pages/authentication/jwt-setup.mdx b/fern/products/docs/pages/authentication/jwt-setup.mdx index b33e7181d..e2325b181 100644 --- a/fern/products/docs/pages/authentication/jwt-setup.mdx +++ b/fern/products/docs/pages/authentication/jwt-setup.mdx @@ -3,11 +3,11 @@ title: JWT setup subtitle: Self-managed authentication for RBAC and API key injection --- -JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). You handle the entire auth flow and set the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie yourself, giving you full control over how users authenticate to your site, what roles they're assigned, and what API keys are injected into the API Explorer. +JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With JWT setup, you handle the entire auth flow and set this cookie yourself, giving you full control over how users authenticate to your site. ## How it works -1. When a user clicks the **Login** button, they're redirected to your authentication page. +1. When a user clicks the **Login** button on your docs site (RBAC) or the API Explorer (API key injection), they're redirected to your authentication page. 2. After successful authentication, your system sets a cookie called `fern_token` in the user's browser. 3. This token is a [JWT](https://jwt.io) signed with a secret key from Fern. The JWT payload contains a `fern` claim with the user's roles, API keys, or both. @@ -15,14 +15,14 @@ JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key i -## Set up +## Configuration -Reach out to Fern to get your secret key and send them the URL of your authentication page. This is where users are redirected after clicking the **Login** button in the API Explorer. +Reach out to Fern to get your secret key and send them the URL of your authentication page. This is where users are redirected after clicking the **Login** button on your docs site or in the API Explorer. - + The JWT payload must include a `fern` claim. What you put inside depends on which features you're using: @@ -62,7 +62,7 @@ The JWT payload must include a `fern` claim. What you put inside depends on whic For [API key injection](/learn/docs/authentication/api-key-injection), the `playground` object supports bearer tokens, basic auth, custom headers, and query parameters: -```json API key injection +```json API key injection maxLines=10 startLine=5 { "fern": { "playground": { @@ -91,7 +91,7 @@ You can also provide multiple API keys or per-environment keys: To provide multiple API keys (for example, one per application), set `bearer_token` to a JSON-encoded array of key-value objects. Each object maps an application name to its key. -```json API key injection +```json API key injection maxLines=5 startLine=2 { "fern": { "playground": { @@ -111,7 +111,7 @@ The API Explorer displays a dropdown so the user can choose which application ke Use `env_state` to provide different credentials for each environment (for example, production vs. staging). Each key in `env_state` is matched against the selected environment URL using substring matching. -```json title="API key injection" +```json title="API key injection" maxLines=10 startLine=2 { "fern": { "playground": { @@ -142,7 +142,7 @@ When the user selects an environment containing `prod` (such as `https://api.pro - + Add logic to your service to sign the JWT and set it as a `fern_token` cookie when a user logs in. diff --git a/fern/products/docs/pages/authentication/oauth-setup.mdx b/fern/products/docs/pages/authentication/oauth-setup.mdx index b7d2a269d..963755e9e 100644 --- a/fern/products/docs/pages/authentication/oauth-setup.mdx +++ b/fern/products/docs/pages/authentication/oauth-setup.mdx @@ -3,11 +3,11 @@ title: OAuth setup subtitle: Fern-managed authentication for RBAC and API key injection --- -OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). You give Fern access to your OAuth provider, and Fern initiates the OAuth handshake process directly — handling the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie for you. +OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With OAuth setup, Fern handles this cookie for you — you give Fern access to your OAuth provider, and Fern initiates the handshake process directly. ## How it works -1. When a user clicks the **Login** button, Fern initiates an OAuth flow by making a request to your authorization endpoint. +1. When a user clicks the **Login** button on your docs site (RBAC) or the API Explorer (API key injection), Fern initiates an OAuth flow by making a request to your authorization endpoint. 1. The user is redirected to your OAuth provider's login page where they authenticate using your existing auth system. 1. After successful authentication, your OAuth provider redirects back to Fern with an authorization code, which Fern exchanges for an access token at your token endpoint. 1. Fern sets a `fern_token` cookie containing the user's roles and credentials, enabling RBAC and automatically populating API keys in the API Explorer. @@ -16,7 +16,7 @@ OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key -## Set up +## Configuration @@ -24,14 +24,14 @@ Go to your OAuth provider's dashboard. Create a new **web application** client. -You will need to allowlist the following callback in your OAuth provider: +Allowlist the following callback in your OAuth provider: `https:///api/fern-docs/oauth2/callback`. -Replace `` with whatever domain you are using for your Fern Docs site. If you want to authenticate both your `.docs.buildwithfern.com` and custom domain, you will need to allowlist both. +Replace `` with whatever domain you are using for your Fern Docs site. If you want to authenticate both your `.docs.buildwithfern.com` and custom domain, you must allowlist both. -Fern will need the following details to configure OAuth authentication: +Fern needs the following details to configure OAuth authentication: - [ ] Docs domain - [ ] Client ID - [ ] Client secret @@ -50,7 +50,7 @@ Send these details to support@buildwithfern.com or in your dedicated Slack chann -Wait for Fern to configure OAuth. You will receive a notification when the site is ready to use authentication. +Wait for Fern to configure OAuth. You'll receive a notification when the site is ready to use authentication. @@ -60,7 +60,7 @@ The final step depends on which features you're using. Add a custom claim to your OAuth provider's token response so that Fern can determine each user's roles. The resulting token response should look something like this: -```json {12-15} +```json {12-15} maxLines=7 startLine=10 { "iss": "https://your-tenant.us.auth0.com/", "sub": "auth0|507f1f77bcf86cd799439011", @@ -83,7 +83,6 @@ Add a custom claim to your OAuth provider's token response so that Fern can dete Some OAuth providers have strict requirements for custom claims. If you need to use a claim other than `roles`, reach out to Fern and specify which claim should be parsed for the user's roles. - To add a custom claim to Auth0, you need to create a **custom action**. This action will be used to add the custom claim to the token response. @@ -104,13 +103,9 @@ To add a custom claim to Auth0, you need to create a **custom action**. This act 5. Click **Create**. 6. Add the action to your **Post Login Flow**. - -If you are using a different OAuth provider, reach out to Fern with any questions on setting up a custom claim. - - -Configure your OAuth application to return user API keys when Fern requests tokens. Set up an authenticated account for Fern so Fern can authorize users on your behalf, and configure your OAuth application to return user API keys when Fern requests them. +Set up an authenticated account for Fern so Fern can authorize users on your behalf, and configure your OAuth application to return user API keys when Fern requests tokens. Contact support@buildwithfern.com to coordinate this setup. diff --git a/fern/products/docs/pages/authentication/overview.mdx b/fern/products/docs/pages/authentication/overview.mdx index fcee2c167..c8eade2c8 100644 --- a/fern/products/docs/pages/authentication/overview.mdx +++ b/fern/products/docs/pages/authentication/overview.mdx @@ -28,7 +28,7 @@ Both features share the same token, so you can implement them together — a sin There are two ways to set up the `fern_token`: -- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. -- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — Fern initiates the OAuth handshake with your provider. +- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. +- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — Fern initiates the OAuth handshake with your provider. [SSO](/learn/docs/authentication/sso) also uses the `fern_token` but has its own setup process. [Password protection](/learn/docs/authentication/password-protection) works differently — it uses a shared password rather than per-user tokens. diff --git a/fern/products/docs/pages/authentication/rbac.mdx b/fern/products/docs/pages/authentication/rbac.mdx index ac7e77224..dbeaf74d9 100644 --- a/fern/products/docs/pages/authentication/rbac.mdx +++ b/fern/products/docs/pages/authentication/rbac.mdx @@ -6,25 +6,15 @@ description: Learn how to restrict access to your documentation using role-based -Fern allows you to restrict parts of your navigation to individuals with specific roles. RBAC enables you to create different levels of access for different user types within your documentation. You can combine RBAC with [API key injection](/learn/docs/authentication/api-key-injection) in a single token. +RBAC lets you restrict pages, sections, and other navigation items to users with specific roles — useful for partner docs, beta features, tiered access, and internal content. You can combine RBAC with [API key injection](/learn/docs/authentication/api-key-injection) in a single token. -When RBAC is configured, [Ask Fern](/learn/docs/ai-features/ask-fern/overview) automatically respects these permissions so users only receive answers from content they're authorized to view. +## How it works -### Use cases +Every user automatically has the `everyone` role, including unauthenticated visitors. When a user visits content that requires a different role, Fern checks the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to determine their roles. If the user lacks the required role or isn't authenticated, Fern redirects them to your login page. -- **Partner documentation**: Provide exclusive API documentation to integration partners while keeping internal docs private -- **Beta features**: Share new features with beta users before general release -- **Internal documentation**: Restrict sensitive documentation to employees only -- **Tiered access**: Offer different documentation levels based on subscription tiers -- **Customer-specific content**: Show different documentation based on customer type or plan +When RBAC is configured, [Ask Fern](/learn/docs/ai-features/ask-fern/overview) automatically respects these permissions. -### How it works - -Every user automatically has the `everyone` role, including unauthenticated visitors. Pages marked with the `everyone` role are publicly accessible without needing to log in. - -If a user visits content that requires authentication (i.e., content not marked as visible to `everyone`), Fern checks the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to determine the user's roles. If the user lacks the required role or isn't authenticated, Fern redirects them to the login URL you provided during setup. - -## Set up +## Setup To enable RBAC, define your roles in `docs.yml` and configure authentication: @@ -38,13 +28,15 @@ roles: Then set up the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) using either method: -- **[JWT setup](/learn/docs/authentication/jwt-setup)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. -- **[OAuth setup](/learn/docs/authentication/oauth-setup)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. +- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. +- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), let Fern know during setup. ## Restricting content +Once RBAC is configured, use `viewers` in your navigation and the `` component in your pages to control what each role can see. + ### In navigation You can assign `viewers` to the following navigation items: `products`, `versions`, `tabs`, `sections`, `pages`, `api references`, and `changelogs`. diff --git a/fern/products/docs/pages/authentication/sso.mdx b/fern/products/docs/pages/authentication/sso.mdx index a0c5884a7..d948a5806 100644 --- a/fern/products/docs/pages/authentication/sso.mdx +++ b/fern/products/docs/pages/authentication/sso.mdx @@ -1,26 +1,19 @@ --- title: Single Sign-On -subtitle: Fern SSO enables enterprise teams to access documentation securely using corporate credentials. Supports SAML 2.0 and OIDC protocols. +subtitle: Secure access to your documentation using corporate credentials --- -Fern’s Single Sign-On (SSO) is an enterprise feature that lets your team securely access your docs through your organization’s identity provider. +SSO lets your team access your docs through your organization's identity provider using SAML 2.0 or OIDC. Like [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection), SSO uses the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to identify authenticated users. SSO unlocks the [Fern Editor](/learn/docs/writing-content/fern-editor) for browser-based editing and [authenticated preview links](/learn/docs/preview-publish/preview-changes#preview-links). -SSO does not support Role-Based Access Control or API Key Injection. - -## What SSO unlocks - -When SSO is enabled for your organization, authenticated users of Fern can: - -- **Use the Fern Editor**: Make edits to your docs from the browser -- **Send Authenticated Preview Links** Only authenticated users can view [preview links](/learn/docs/preview-publish/preview-changes#preview-links) +SSO provides login-based access control but does not support role management or API key injection. For granular access control, use [RBAC](/learn/docs/authentication/rbac) instead. ## How it works -Fern's SSO integration allows your team to use their existing corporate credentials to access your Fern Docs site. +When a user clicks **Login**, Fern redirects them to your identity provider. After authenticating with their corporate credentials, the identity provider redirects back to Fern with a `fern_token`, granting access to your docs. -### Architecture diagram + ```mermaid sequenceDiagram @@ -29,25 +22,18 @@ sequenceDiagram participant F as Fern Docs participant I as Identity Provider - U->>F: Click "Login" + U->>F: Click "Login" F->>I: Redirect to SSO login - + Note over I: User authenticates with corporate credentials - + I->>I: Validate user credentials I->>F: Redirect back with fern_token F->>F: Grant access to organizational features F->>U: Show docs site ``` + -## Supported identity providers - -Fern supports SSO integration with any identity provider that implements industry-standard protocols: - -- **SAML 2.0**: Compatible with providers like Okta, OneLogin, Azure AD, and others -- **OIDC (OpenID Connect)**: Works with Google Workspace, Auth0, and other OIDC-compliant providers - -## Setting up SSO - -Reach out via Slack or [contact our team](https://buildwithfern.com/contact) to begin the SSO setup process. Fern will work with one of your security administrators to connect to your identity provider. +## Setup +Fern supports any SAML 2.0 or OIDC provider (Okta, Google Workspace, Auth0, Azure AD, OneLogin, etc.). [Contact Fern](https://buildwithfern.com/contact) or reach out via Slack. Fern will work with your security team to connect to your identity provider. From c8470a2542f295ab8e71fe32144f62086aab6d63 Mon Sep 17 00:00:00 2001 From: Devin Logan Date: Thu, 12 Feb 2026 12:59:43 -0500 Subject: [PATCH 6/7] more structure/clarity edits --- fern/docs.yml | 26 ++++++++++++------- fern/products/docs/docs.yml | 21 ++++++++------- .../pages/api-references/api-explorer.mdx | 2 +- .../products/docs/pages/ask-fern/features.mdx | 2 +- .../docs/pages/ask-fern/slack-app.mdx | 2 +- .../docs/pages/ask-fern/what-is-ask-fern.mdx | 2 +- .../authentication/api-key-injection.mdx | 10 ++++--- .../docs/pages/authentication/jwt-setup.mdx | 4 +-- .../docs/pages/authentication/oauth-setup.mdx | 4 +-- .../docs/pages/authentication/overview.mdx | 16 ++++++------ .../docs/pages/authentication/rbac.mdx | 6 ++--- .../docs/pages/changelog/2026-01-17.mdx | 2 +- .../docs/pages/changelog/2026-02-11.mdx | 4 +-- .../enterprise/self-hosted-authentication.mdx | 4 +-- fern/products/docs/pages/navigation/tabs.mdx | 2 +- .../pages/resources/stainless-comparison.mdx | 12 ++++----- .../products/docs/pages/security/overview.mdx | 4 +-- 17 files changed, 66 insertions(+), 57 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index ca499c8ce..5d92641c2 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -351,7 +351,7 @@ redirects: - source: /learn/docs/building-and-customizing-your-docs/custom-domain destination: /learn/docs/preview-publish/setting-up-your-domain - source: /learn/docs/building-and-customizing-your-docs/rbac - destination: /learn/docs/authentication/rbac/overview + destination: /learn/docs/authentication/rbac - source: /learn/docs/building-and-customizing-your-docs/search destination: /learn/docs/customization/search @@ -402,22 +402,28 @@ redirects: destination: /learn/docs/api-references/api-explorer # Authentication subsection redirects - - source: /learn/docs/authentication/rbac - destination: /learn/docs/authentication/rbac/overview + - source: /learn/docs/authentication/rbac/overview + destination: /learn/docs/authentication/rbac + - source: /learn/docs/authentication/api-key-injection/overview + destination: /learn/docs/authentication/api-key-injection - source: /learn/docs/authentication/set-up-oauth - destination: /learn/docs/authentication/auth-setup/oauth-setup + destination: /learn/docs/authentication/setup/oauth - source: /learn/docs/authentication/jwt-setup - destination: /learn/docs/authentication/auth-setup/jwt-setup + destination: /learn/docs/authentication/setup/jwt - source: /learn/docs/authentication/oauth-setup - destination: /learn/docs/authentication/auth-setup/oauth-setup + destination: /learn/docs/authentication/setup/oauth + - source: /learn/docs/authentication/auth-setup/jwt-setup + destination: /learn/docs/authentication/setup/jwt + - source: /learn/docs/authentication/auth-setup/oauth-setup + destination: /learn/docs/authentication/setup/oauth - source: /learn/docs/authentication/rbac/jwt-setup - destination: /learn/docs/authentication/auth-setup/jwt-setup + destination: /learn/docs/authentication/setup/jwt - source: /learn/docs/authentication/rbac/oauth-setup - destination: /learn/docs/authentication/auth-setup/oauth-setup + destination: /learn/docs/authentication/setup/oauth - source: /learn/docs/authentication/api-key-injection/jwt-setup - destination: /learn/docs/authentication/auth-setup/jwt-setup + destination: /learn/docs/authentication/setup/jwt - source: /learn/docs/authentication/api-key-injection/oauth-setup - destination: /learn/docs/authentication/auth-setup/oauth-setup + destination: /learn/docs/authentication/setup/oauth - source: /learn/user-feedback destination: /learn/docs/user-feedback - source: /learn/docs/customization/what-is-docs-yml diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index d29152176..9a0736629 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -290,23 +290,24 @@ navigation: contents: - page: Overview path: ./pages/authentication/overview.mdx + - page: Password protection + path: ./pages/authentication/password.mdx + - page: SSO + path: ./pages/authentication/sso.mdx - page: Role-based access control (RBAC) path: ./pages/authentication/rbac.mdx + slug: rbac - page: API key injection path: ./pages/authentication/api-key-injection.mdx - - section: Auth setup - slug: auth-setup + - section: Setup + slug: setup contents: - - page: JWT setup + - page: JWT path: ./pages/authentication/jwt-setup.mdx - slug: jwt-setup - - page: OAuth setup + slug: jwt + - page: OAuth path: ./pages/authentication/oauth-setup.mdx - slug: oauth-setup - - page: SSO - path: ./pages/authentication/sso.mdx - - page: Password protection - path: ./pages/authentication/password.mdx + slug: oauth - section: Security collapsed: true contents: diff --git a/fern/products/docs/pages/api-references/api-explorer.mdx b/fern/products/docs/pages/api-references/api-explorer.mdx index 933fc82a0..d0f0003ed 100644 --- a/fern/products/docs/pages/api-references/api-explorer.mdx +++ b/fern/products/docs/pages/api-references/api-explorer.mdx @@ -22,7 +22,7 @@ Once a user sets their authentication credentials, their credentials persist thr Authentication credentials are only stored client-side using cookies. No sensitive user information is collected or stored. -To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection/overview). +To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection). ## Multiple environments diff --git a/fern/products/docs/pages/ask-fern/features.mdx b/fern/products/docs/pages/ask-fern/features.mdx index e3ba154b6..1f99277e1 100644 --- a/fern/products/docs/pages/ask-fern/features.mdx +++ b/fern/products/docs/pages/ask-fern/features.mdx @@ -63,7 +63,7 @@ https://{{PAGE_URL}}?query={{QUERY2}} ## Role-based access control -Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/rbac/overview). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. +Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/rbac). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. This works at all levels, from entire sections down to individual pages and conditional content within pages. diff --git a/fern/products/docs/pages/ask-fern/slack-app.mdx b/fern/products/docs/pages/ask-fern/slack-app.mdx index 44d16305e..27b80bf5f 100644 --- a/fern/products/docs/pages/ask-fern/slack-app.mdx +++ b/fern/products/docs/pages/ask-fern/slack-app.mdx @@ -62,7 +62,7 @@ Use the `/fern` slash command in any channel to adjust the settings: | Command | Description | Example | |---------|-------------|---------| | **respond_to** | Controls whether the Ask Fern bot responds to all messages (`all`), reponds only when directly mentioned with `@Ask Fern` (`mentions_only`), or determines when to respond to messages depending on context (`auto`). Set to `auto` by default. | `/fern respond_to all` | -| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/docs/authentication/rbac/overview) configured) | `/fern roles developer,admin` | +| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/docs/authentication/rbac) configured) | `/fern roles developer,admin` | | **show** | Show the current settings | `/fern show` | | **help** | Get help with Ask Fern slash commands | `/fern help` | diff --git a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx index 41798996d..26f3bdbf1 100644 --- a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx +++ b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx @@ -68,7 +68,7 @@ ai-search: Fern automatically processes your documentation pages and Fern-generated SDK code, breaking them into semantic chunks and converting each chunk into a vector using sentence embedding models. They're stored in a database that serves as Ask Fern's search index. - When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/rbac/overview) configured, Ask Fern filters results based on the user's permissions. + When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/rbac) configured, Ask Fern filters results based on the user's permissions. Ask Fern uses the retrieved chunks as context to generate accurate answers with [citations](/learn/docs/ai-features/ask-fern/features#citations) for the user. If the initial context isn't sufficient, it performs an additional keyword search. diff --git a/fern/products/docs/pages/authentication/api-key-injection.mdx b/fern/products/docs/pages/authentication/api-key-injection.mdx index ce0ba9c38..2ee6efcdd 100644 --- a/fern/products/docs/pages/authentication/api-key-injection.mdx +++ b/fern/products/docs/pages/authentication/api-key-injection.mdx @@ -1,11 +1,11 @@ --- -title: Autopopulate API keys +title: API key injection subtitle: Allow users to log in and automatically populate their API keys in the API Explorer. --- -API key injection lets users log in and have their API keys automatically populated in the [API Explorer](/learn/docs/api-references/api-explorer). You can combine API key injection with [RBAC](/learn/docs/authentication/rbac) in a single token. +API key injection lets users log in and have their API keys automatically populated in the [API Explorer](/learn/docs/api-references/api-explorer). You can combine API key injection with [RBAC](/learn/docs/authentication/rbac) with a single token.
@@ -19,5 +19,7 @@ User credentials are stored only in browser cookies and never transmitted to Fer ## Setup -- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. -- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — You give Fern access, and Fern initiates the OAuth handshake process directly. +Set up the `fern_token` using either method: + +- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. +- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — You give Fern access, and Fern initiates the OAuth handshake process directly. diff --git a/fern/products/docs/pages/authentication/jwt-setup.mdx b/fern/products/docs/pages/authentication/jwt-setup.mdx index e2325b181..dfdc1ee11 100644 --- a/fern/products/docs/pages/authentication/jwt-setup.mdx +++ b/fern/products/docs/pages/authentication/jwt-setup.mdx @@ -1,9 +1,9 @@ --- -title: JWT setup +title: Set up JWT subtitle: Self-managed authentication for RBAC and API key injection --- -JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With JWT setup, you handle the entire auth flow and set this cookie yourself, giving you full control over how users authenticate to your site. +JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that contains a signed [JWT](https://jwt.io). Fern reads the token to identify a user's roles and API keys. With JWT setup, you build and sign this token yourself, giving you full control over the auth flow and what goes in the payload. ## How it works diff --git a/fern/products/docs/pages/authentication/oauth-setup.mdx b/fern/products/docs/pages/authentication/oauth-setup.mdx index 963755e9e..7a1e9fea0 100644 --- a/fern/products/docs/pages/authentication/oauth-setup.mdx +++ b/fern/products/docs/pages/authentication/oauth-setup.mdx @@ -1,9 +1,9 @@ --- -title: OAuth setup +title: Set up OAuth subtitle: Fern-managed authentication for RBAC and API key injection --- -OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With OAuth setup, Fern handles this cookie for you — you give Fern access to your OAuth provider, and Fern initiates the handshake process directly. +OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With OAuth setup, Fern handles this token for you — you give Fern access to your OAuth provider, and Fern initiates the handshake process directly. ## How it works diff --git a/fern/products/docs/pages/authentication/overview.mdx b/fern/products/docs/pages/authentication/overview.mdx index c8eade2c8..8899a4349 100644 --- a/fern/products/docs/pages/authentication/overview.mdx +++ b/fern/products/docs/pages/authentication/overview.mdx @@ -6,18 +6,18 @@ description: Understand the different authentication options Fern offers Fern offers several ways to control access to your documentation, from simple password protection to granular role-based access control. + + A single shared password for the entire site + + + Require login without role management + Granular access for different audiences Autopopulate API keys in the API Explorer - - Require login without role management - - - A single shared password for the entire site - ## How authentication works @@ -28,7 +28,7 @@ Both features share the same token, so you can implement them together — a sin There are two ways to set up the `fern_token`: -- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the `fern_token` cookie yourself. -- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — Fern initiates the OAuth handshake with your provider. +- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the `fern_token` cookie yourself. +- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — Fern initiates the OAuth handshake with your provider. [SSO](/learn/docs/authentication/sso) also uses the `fern_token` but has its own setup process. [Password protection](/learn/docs/authentication/password-protection) works differently — it uses a shared password rather than per-user tokens. diff --git a/fern/products/docs/pages/authentication/rbac.mdx b/fern/products/docs/pages/authentication/rbac.mdx index dbeaf74d9..b1563e94a 100644 --- a/fern/products/docs/pages/authentication/rbac.mdx +++ b/fern/products/docs/pages/authentication/rbac.mdx @@ -26,10 +26,10 @@ roles: - admins ``` -Then set up the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) using either method: +Then, set up the `fern_token` using either method: -- **[JWT setup](/learn/docs/authentication/auth-setup/jwt-setup)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. -- **[OAuth setup](/learn/docs/authentication/auth-setup/oauth-setup)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. +- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. +- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), let Fern know during setup. diff --git a/fern/products/docs/pages/changelog/2026-01-17.mdx b/fern/products/docs/pages/changelog/2026-01-17.mdx index 72e6e10be..9c472000f 100644 --- a/fern/products/docs/pages/changelog/2026-01-17.mdx +++ b/fern/products/docs/pages/changelog/2026-01-17.mdx @@ -22,4 +22,4 @@ The `` component now supports `products` and `versions` props, allowing you You can also use the `not` prop to invert the condition, showing content when the current product or version does not match. -Learn more about the [If component](/learn/docs/authentication/rbac/overview#access-control-within-mdx-pages). +Learn more about the [If component](/learn/docs/authentication/rbac#in-mdx-pages). diff --git a/fern/products/docs/pages/changelog/2026-02-11.mdx b/fern/products/docs/pages/changelog/2026-02-11.mdx index 330de6061..de8df33df 100644 --- a/fern/products/docs/pages/changelog/2026-02-11.mdx +++ b/fern/products/docs/pages/changelog/2026-02-11.mdx @@ -1,9 +1,9 @@ ## API key injection for self-hosted docs -Self-hosted deployments support [API key injection](/learn/docs/authentication/api-key-injection/overview) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. +Self-hosted deployments support [API key injection](/learn/docs/authentication/api-key-injection) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. Learn more about [self-hosted authentication](/learn/docs/self-hosted/authentication#api-key-injection). ## Multiple API keys and per-environment keys -API key injection supports [multiple API keys](/learn/docs/authentication/api-key-injection/overview#multiple-api-keys) and [per-environment credentials](/learn/docs/authentication/api-key-injection/overview#per-environment-keys). Provide multiple keys as a JSON-encoded array in `bearer_token`, and use `env_state` to set different credentials per environment with substring matching. +API key injection supports [multiple API keys](/learn/docs/authentication/setup/jwt#build-the-fern-claim) and [per-environment credentials](/learn/docs/authentication/setup/jwt#build-the-fern-claim). Provide multiple keys as a JSON-encoded array in `bearer_token`, and use `env_state` to set different credentials per environment with substring matching. diff --git a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx index 54a640552..4886d8a80 100644 --- a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx +++ b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx @@ -203,7 +203,7 @@ ENV FERN_AUTH_DENYLIST="/api-reference/(.*)" ## API key injection -You can enable [API key injection](/learn/docs/authentication/api-key-injection/overview) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. +You can enable [API key injection](/learn/docs/authentication/api-key-injection) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. Add `FERN_API_KEY_INJECTION_ENABLED` to your Dockerfile alongside the basic token verification variables: @@ -222,4 +222,4 @@ ENV FERN_AUTH_ALLOWLIST="/(.*)" RUN fern-generate ``` -With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/api-key-injection/overview) for the full `fern` payload reference. +With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/api-key-injection) for the full `fern` payload reference. diff --git a/fern/products/docs/pages/navigation/tabs.mdx b/fern/products/docs/pages/navigation/tabs.mdx index 4807f309a..3a4e4efcc 100644 --- a/fern/products/docs/pages/navigation/tabs.mdx +++ b/fern/products/docs/pages/navigation/tabs.mdx @@ -133,7 +133,7 @@ theme: ## Tab variants -Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/rbac/overview). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. +Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/rbac). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. Use **variants** for different perspectives on the same content area (REST vs. GraphQL, beginner vs. advanced). Use **tabs** for completely different documentation sections (guides vs. API Reference). diff --git a/fern/products/docs/pages/resources/stainless-comparison.mdx b/fern/products/docs/pages/resources/stainless-comparison.mdx index 69be2a007..e912ce63b 100644 --- a/fern/products/docs/pages/resources/stainless-comparison.mdx +++ b/fern/products/docs/pages/resources/stainless-comparison.mdx @@ -14,7 +14,7 @@ Choose Fern for enterprise requirements, regulated industries, or production-cri |------------|------|-----------| | **Maturity** | Production-ready, stable APIs | Early access, breaking changes expected | | **Authoring** | [Visual editor](/learn/docs/writing-content/fern-editor) + Git | Git only | -| **Enterprise features** | [RBAC](/learn/docs/authentication/rbac/overview), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | +| **Enterprise features** | [RBAC](/learn/docs/authentication/rbac), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | | **API testing** | [Interactive explorer](/learn/docs/api-references/api-explorer) | None | | **Deployment** | Cloud + [full-stack self-hosted](/learn/docs/self-hosted/overview) | Static files only | @@ -50,7 +50,7 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection/overview), WebSocket, and audio streaming support | ❌ None | +| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection), WebSocket, and audio streaming support | ❌ None | | **SDK documentation** | ✅ [Multi-language support](/learn/docs/api-references/sdk-snippets) | ✅ Language-specific pages | | **API spec formats** | ✅ [OpenAPI, AsyncAPI, gRPC, OpenRPC, Fern](/learn/docs/api-references/generate-api-ref) | ⚠️ OpenAPI + Stainless config only |
@@ -58,11 +58,11 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor -Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/rbac/overview) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. +Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/rbac) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/rbac/overview) for internal vs. public sites | ❌ None | +| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/rbac) for internal vs. public sites | ❌ None | | **API versioning** | ✅ [Multi-version support](/learn/docs/configuration/site-level-settings) with availability states and per-version content | ❌ None | | **Multi-product sites** | ✅ [Multiple products](/learn/docs/configuration/site-level-settings) in unified documentation | ⚠️ Basic tabs (Guides/Reference) |
@@ -87,8 +87,8 @@ Stainless's [authentication](https://www.stainless.com/docs/docs-platform/advanc | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/rbac/overview) | ❌ None | -| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/authentication/api-key-injection/overview) | ⚠️ API keys for Stainless service only | +| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/rbac) | ❌ None | +| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/authentication/api-key-injection) | ⚠️ API keys for Stainless service only |
diff --git a/fern/products/docs/pages/security/overview.mdx b/fern/products/docs/pages/security/overview.mdx index 1cd530c2d..4d9caf93f 100644 --- a/fern/products/docs/pages/security/overview.mdx +++ b/fern/products/docs/pages/security/overview.mdx @@ -13,8 +13,8 @@ Fern's documentation platform is built with security as a core principle, using Fern supports [multiple authentication methods](/learn/docs/authentication/overview) to secure your documentation. All methods use a client-side `fern_token` cookie stored entirely in the browser: -- [Role-Based Access Control (RBAC)](/learn/docs/authentication/rbac/overview) controls which users can access specific documentation content based on their roles (stores user roles) -- [API key injection](/learn/docs/authentication/api-key-injection/overview) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) +- [Role-Based Access Control (RBAC)](/learn/docs/authentication/rbac) controls which users can access specific documentation content based on their roles (stores user roles) +- [API key injection](/learn/docs/authentication/api-key-injection) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) - [Single Sign-On (SSO)](/learn/docs/authentication/sso) integrates with your existing identity provider for seamless authentication (stores identity provider tokens) These cookies are managed entirely client-side and automatically cleared when the user logs out or the session expires. This approach ensures that sensitive credentials remain under your control and are never exposed to Fern's infrastructure. From b0fe6a8938b94b542da5ebf78eed761167c56295 Mon Sep 17 00:00:00 2001 From: Devin Logan Date: Thu, 12 Feb 2026 20:10:05 -0500 Subject: [PATCH 7/7] restructure based on feedback --- fern/docs.yml | 22 +++- fern/products/docs/docs.yml | 21 ++-- .../pages/api-references/api-explorer.mdx | 2 +- .../products/docs/pages/ask-fern/features.mdx | 2 +- .../docs/pages/ask-fern/slack-app.mdx | 2 +- .../docs/pages/ask-fern/what-is-ask-fern.mdx | 2 +- .../authentication/api-key-injection.mdx | 96 ++++++++++++-- .../docs/pages/authentication/jwt-setup.mdx | 118 ++++-------------- .../docs/pages/authentication/oauth-setup.mdx | 34 ++--- .../docs/pages/authentication/overview.mdx | 32 ++--- .../docs/pages/authentication/rbac.mdx | 17 +-- .../docs/pages/authentication/sso.mdx | 4 +- .../docs/pages/changelog/2026-01-17.mdx | 2 +- .../docs/pages/changelog/2026-02-11.mdx | 2 +- .../enterprise/self-hosted-authentication.mdx | 4 +- .../docs/pages/enterprise/self-hosted.mdx | 2 +- fern/products/docs/pages/navigation/tabs.mdx | 2 +- .../pages/resources/stainless-comparison.mdx | 14 +-- .../products/docs/pages/security/overview.mdx | 6 +- 19 files changed, 208 insertions(+), 176 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index 5d92641c2..44384fd0a 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -351,7 +351,7 @@ redirects: - source: /learn/docs/building-and-customizing-your-docs/custom-domain destination: /learn/docs/preview-publish/setting-up-your-domain - source: /learn/docs/building-and-customizing-your-docs/rbac - destination: /learn/docs/authentication/rbac + destination: /learn/docs/authentication/features/rbac - source: /learn/docs/building-and-customizing-your-docs/search destination: /learn/docs/customization/search @@ -401,11 +401,25 @@ redirects: - source: /learn/docs/api-references/api-playground destination: /learn/docs/api-references/api-explorer - # Authentication subsection redirects + # Authentication redirects — old locations → new Setup/Features structure + - source: /learn/docs/authentication/password-protection + destination: /learn/docs/authentication/setup/password-protection + - source: /learn/docs/authentication/sso + destination: /learn/docs/authentication/setup/sso + - source: /learn/docs/authentication/jwt + destination: /learn/docs/authentication/setup/jwt + - source: /learn/docs/authentication/oauth + destination: /learn/docs/authentication/setup/oauth + - source: /learn/docs/authentication/rbac + destination: /learn/docs/authentication/features/rbac + - source: /learn/docs/authentication/api-key-injection + destination: /learn/docs/authentication/features/api-key-injection + + # Authentication redirects — legacy paths - source: /learn/docs/authentication/rbac/overview - destination: /learn/docs/authentication/rbac + destination: /learn/docs/authentication/features/rbac - source: /learn/docs/authentication/api-key-injection/overview - destination: /learn/docs/authentication/api-key-injection + destination: /learn/docs/authentication/features/api-key-injection - source: /learn/docs/authentication/set-up-oauth destination: /learn/docs/authentication/setup/oauth - source: /learn/docs/authentication/jwt-setup diff --git a/fern/products/docs/docs.yml b/fern/products/docs/docs.yml index 9a0736629..c0b58dd19 100644 --- a/fern/products/docs/docs.yml +++ b/fern/products/docs/docs.yml @@ -290,24 +290,27 @@ navigation: contents: - page: Overview path: ./pages/authentication/overview.mdx - - page: Password protection - path: ./pages/authentication/password.mdx - - page: SSO - path: ./pages/authentication/sso.mdx - - page: Role-based access control (RBAC) - path: ./pages/authentication/rbac.mdx - slug: rbac - - page: API key injection - path: ./pages/authentication/api-key-injection.mdx - section: Setup slug: setup contents: + - page: Password protection + path: ./pages/authentication/password.mdx + - page: SSO + path: ./pages/authentication/sso.mdx - page: JWT path: ./pages/authentication/jwt-setup.mdx slug: jwt - page: OAuth path: ./pages/authentication/oauth-setup.mdx slug: oauth + - section: Features + slug: features + contents: + - page: Role-based access control (RBAC) + path: ./pages/authentication/rbac.mdx + slug: rbac + - page: API key injection + path: ./pages/authentication/api-key-injection.mdx - section: Security collapsed: true contents: diff --git a/fern/products/docs/pages/api-references/api-explorer.mdx b/fern/products/docs/pages/api-references/api-explorer.mdx index d0f0003ed..501f97bce 100644 --- a/fern/products/docs/pages/api-references/api-explorer.mdx +++ b/fern/products/docs/pages/api-references/api-explorer.mdx @@ -22,7 +22,7 @@ Once a user sets their authentication credentials, their credentials persist thr Authentication credentials are only stored client-side using cookies. No sensitive user information is collected or stored. -To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/api-key-injection). +To automatically populate API keys for logged-in users, see [API key injection](/learn/docs/authentication/features/api-key-injection). ## Multiple environments diff --git a/fern/products/docs/pages/ask-fern/features.mdx b/fern/products/docs/pages/ask-fern/features.mdx index 1f99277e1..d38c1b6fc 100644 --- a/fern/products/docs/pages/ask-fern/features.mdx +++ b/fern/products/docs/pages/ask-fern/features.mdx @@ -63,7 +63,7 @@ https://{{PAGE_URL}}?query={{QUERY2}} ## Role-based access control -Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/rbac). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. +Ask Fern automatically respects the [role-based access control (RBAC) settings configured in your documentation](/learn/docs/authentication/features/rbac). When users query Ask Fern, they only receive answers from documentation they have permission to access based on their assigned roles. This works at all levels, from entire sections down to individual pages and conditional content within pages. diff --git a/fern/products/docs/pages/ask-fern/slack-app.mdx b/fern/products/docs/pages/ask-fern/slack-app.mdx index 27b80bf5f..19a635df8 100644 --- a/fern/products/docs/pages/ask-fern/slack-app.mdx +++ b/fern/products/docs/pages/ask-fern/slack-app.mdx @@ -62,7 +62,7 @@ Use the `/fern` slash command in any channel to adjust the settings: | Command | Description | Example | |---------|-------------|---------| | **respond_to** | Controls whether the Ask Fern bot responds to all messages (`all`), reponds only when directly mentioned with `@Ask Fern` (`mentions_only`), or determines when to respond to messages depending on context (`auto`). Set to `auto` by default. | `/fern respond_to all` | -| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/docs/authentication/rbac) configured) | `/fern roles developer,admin` | +| **roles** | Specifies which RBAC roles (comma-separated) should be used to filter Ask Fern responses (if you have [role-based access control](/learn/docs/authentication/features/rbac) configured) | `/fern roles developer,admin` | | **show** | Show the current settings | `/fern show` | | **help** | Get help with Ask Fern slash commands | `/fern help` | diff --git a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx index 26f3bdbf1..5c3f961dd 100644 --- a/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx +++ b/fern/products/docs/pages/ask-fern/what-is-ask-fern.mdx @@ -68,7 +68,7 @@ ai-search: Fern automatically processes your documentation pages and Fern-generated SDK code, breaking them into semantic chunks and converting each chunk into a vector using sentence embedding models. They're stored in a database that serves as Ask Fern's search index.
- When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/rbac) configured, Ask Fern filters results based on the user's permissions. + When users ask questions, Ask Fern vectorizes their query and searches the database to find the most relevant documentation and code chunks. If you have [role-based access control](/learn/docs/authentication/features/rbac) configured, Ask Fern filters results based on the user's permissions. Ask Fern uses the retrieved chunks as context to generate accurate answers with [citations](/learn/docs/ai-features/ask-fern/features#citations) for the user. If the initial context isn't sufficient, it performs an additional keyword search. diff --git a/fern/products/docs/pages/authentication/api-key-injection.mdx b/fern/products/docs/pages/authentication/api-key-injection.mdx index 2ee6efcdd..5159bc695 100644 --- a/fern/products/docs/pages/authentication/api-key-injection.mdx +++ b/fern/products/docs/pages/authentication/api-key-injection.mdx @@ -1,25 +1,103 @@ --- title: API key injection -subtitle: Allow users to log in and automatically populate their API keys in the API Explorer. +subtitle: Automatically populate API keys in the API Explorer for logged-in users. --- -API key injection lets users log in and have their API keys automatically populated in the [API Explorer](/learn/docs/api-references/api-explorer). You can combine API key injection with [RBAC](/learn/docs/authentication/rbac) with a single token. +API key injection is a feature of [JWT](/learn/docs/authentication/setup/jwt) and [OAuth](/learn/docs/authentication/setup/oauth) authentication. When a user logs in, a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie is set in their browser with a `fern.playground` claim that tells the [API Explorer](/learn/docs/api-references/api-explorer) what values to pre-fill — API keys, headers, or other credentials. You can combine it with [RBAC](/learn/docs/authentication/features/rbac) in a single token.
-## How it works - -When a user logs in, a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie is set in their browser containing a `fern.playground` claim that tells the API Explorer what values to pre-fill — API keys, headers, or other credentials. - User credentials are stored only in browser cookies and never transmitted to Fern's servers. Learn more in the [Security overview](/learn/docs/security/overview). ## Setup -Set up the `fern_token` using either method: +To enable API key injection, follow the [JWT](/learn/docs/authentication/setup/jwt) or [OAuth](/learn/docs/authentication/setup/oauth) setup guide. + +### Advanced payload configuration + +With [JWT setup](/learn/docs/authentication/setup/jwt), you have full control over the `fern.playground` payload. These options let you go beyond a single bearer token — pre-filling custom headers, supporting multiple API keys, or varying credentials by environment. These options are not available with OAuth, where Fern manages the token. + + + +You can pre-fill headers, path parameters, and query parameters alongside auth credentials: + +```json maxLines=10 startLine=5 +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "eyJhbGciOiJIUzI1c" + }, + "headers": { + "API-Version": "2024-02-02" + }, + "path_parameters": { + "plantId": "plant_1234" + }, + "query_parameters": { + "sort": "DESCENDING" + } + } + } + } +} +``` + + + +To provide multiple API keys (for example, one per application), set `bearer_token` to a JSON-encoded array of key-value objects. Each object maps an application name to its key. + +```json maxLines=5 startLine=2 +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "[{\"Greenhouse app\": \"sk-greenhouse-abc123\"}, {\"Garden app\": \"sk-garden-def456\"}]" + } + } + } + } +} +``` + +The API Explorer displays a dropdown so the user can choose which application key to use for requests. + + + +Use `env_state` to provide different credentials for each environment (for example, production vs. staging). Each key in `env_state` is matched against the selected environment URL using substring matching. + +```json maxLines=10 startLine=2 +{ + "fern": { + "playground": { + "initial_state": { + "auth": { + "bearer_token": "default-token" + } + }, + "env_state": { + "prod": { + "auth": { + "bearer_token": "prod-token-abc123" + } + }, + "staging": { + "auth": { + "bearer_token": "staging-token-def456" + } + } + } + } + } +} +``` -- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the `fern_token` cookie yourself. Supports advanced configuration like custom headers, per-environment keys, and multiple API keys. -- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — You give Fern access, and Fern initiates the OAuth handshake process directly. +When the user selects an environment containing `prod` (such as `https://api.prod.example.com`), the API Explorer uses `prod-token-abc123`. The `env_state` values are merged on top of `initial_state`: auth is replaced entirely, while headers, path parameters, and query parameters are shallow-merged. + + diff --git a/fern/products/docs/pages/authentication/jwt-setup.mdx b/fern/products/docs/pages/authentication/jwt-setup.mdx index dfdc1ee11..0d1ab2de7 100644 --- a/fern/products/docs/pages/authentication/jwt-setup.mdx +++ b/fern/products/docs/pages/authentication/jwt-setup.mdx @@ -1,15 +1,19 @@ --- title: Set up JWT -subtitle: Self-managed authentication for RBAC and API key injection +subtitle: Self-managed authentication integrated with your login system --- -JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that contains a signed [JWT](https://jwt.io). Fern reads the token to identify a user's roles and API keys. With JWT setup, you build and sign this token yourself, giving you full control over the auth flow and what goes in the payload. +With JWT, you manage the entire auth flow. This involves building and signing a [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie that integrates your docs with your existing login system. Like [OAuth](/learn/docs/authentication/setup/oauth), JWT enables: + +- **Login only** — gate docs behind authentication +- **[RBAC](/learn/docs/authentication/features/rbac)** — restrict content by user role +- **[API key injection](/learn/docs/authentication/features/api-key-injection)** — pre-fill API keys in the [API Explorer](/learn/docs/api-references/api-explorer) ## How it works -1. When a user clicks the **Login** button on your docs site (RBAC) or the API Explorer (API key injection), they're redirected to your authentication page. -2. After successful authentication, your system sets a cookie called `fern_token` in the user's browser. -3. This token is a [JWT](https://jwt.io) signed with a secret key from Fern. The JWT payload contains a `fern` claim with the user's roles, API keys, or both. +1. A user clicks **Login** on your docs site and is redirected to your authentication page. +2. After authentication, your system signs a [JWT](https://jwt.io) with a secret key from Fern and sets it as a `fern_token` cookie. +3. Fern reads the token to determine the user's access and credentials. @@ -19,37 +23,30 @@ JWT setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key i -Reach out to Fern to get your secret key and send them the URL of your authentication page. This is where users are redirected after clicking the **Login** button on your docs site or in the API Explorer. +Reach out to Fern to get your secret key and send them the URL of your authentication page. This is where users are redirected after clicking **Login**. -The JWT payload must include a `fern` claim. What you put inside depends on which features you're using: +The JWT payload must include a `fern` claim. What you include in the token's `fern` claim controls which features are enabled: login only, RBAC, or API key injection. -```json RBAC only +```json Login only { - "fern": { - "roles": ["partners"] - } + "fern": {} } ``` -```json API key injection only +```json RBAC { "fern": { - "playground": { - "initial_state": { - "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } - } - } + "roles": ["partners"] } } ``` -```json Both combined +```json API key injection { "fern": { - "roles": ["partners"], "playground": { "initial_state": { "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } @@ -58,88 +55,20 @@ The JWT payload must include a `fern` claim. What you put inside depends on whic } } ``` - - -For [API key injection](/learn/docs/authentication/api-key-injection), the `playground` object supports bearer tokens, basic auth, custom headers, and query parameters: -```json API key injection maxLines=10 startLine=5 -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "eyJhbGciOiJIUzI1c" - }, - "headers": { - "API-Version": "2024-02-02" - }, - "path_parameters": { - "plantId": "plant_1234" - }, - "query_parameters": { - "sort": "DESCENDING" - } - } - } - } -} -``` - -You can also provide multiple API keys or per-environment keys: - - - -To provide multiple API keys (for example, one per application), set `bearer_token` to a JSON-encoded array of key-value objects. Each object maps an application name to its key. - -```json API key injection maxLines=5 startLine=2 -{ - "fern": { - "playground": { - "initial_state": { - "auth": { - "bearer_token": "[{\"Greenhouse app\": \"sk-greenhouse-abc123\"}, {\"Garden app\": \"sk-garden-def456\"}]" - } - } - } - } -} -``` - -The API Explorer displays a dropdown so the user can choose which application key to use for requests. - - - -Use `env_state` to provide different credentials for each environment (for example, production vs. staging). Each key in `env_state` is matched against the selected environment URL using substring matching. - -```json title="API key injection" maxLines=10 startLine=2 +```json API key injection + RBAC { "fern": { + "roles": ["partners"], "playground": { "initial_state": { - "auth": { - "bearer_token": "default-token" - } - }, - "env_state": { - "prod": { - "auth": { - "bearer_token": "prod-token-abc123" - } - }, - "staging": { - "auth": { - "bearer_token": "staging-token-def456" - } - } + "auth": { "bearer_token": "eyJhbGciOiJIUzI1c" } } } } } ``` - -When the user selects an environment containing `prod` (such as `https://api.prod.example.com`), the API Explorer uses `prod-token-abc123`. The `env_state` values are merged on top of `initial_state`: auth is replaced entirely, while headers, path parameters, and query parameters are shallow-merged. - - + @@ -231,4 +160,11 @@ async function mintFernToken({ ```
+ + +Once your `fern_token` is working, configure the features you need: + +- **[Role-based access control](/learn/docs/authentication/features/rbac)** — define roles in `docs.yml` and restrict navigation items or page content by role. +- **[API key injection](/learn/docs/authentication/features/api-key-injection)** — configure the `playground` payload, including custom headers, multiple API keys, and per-environment credentials. +
diff --git a/fern/products/docs/pages/authentication/oauth-setup.mdx b/fern/products/docs/pages/authentication/oauth-setup.mdx index 7a1e9fea0..541105642 100644 --- a/fern/products/docs/pages/authentication/oauth-setup.mdx +++ b/fern/products/docs/pages/authentication/oauth-setup.mdx @@ -1,16 +1,19 @@ --- title: Set up OAuth -subtitle: Fern-managed authentication for RBAC and API key injection +subtitle: Fern-managed authentication integrated with your login system --- -OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection). The [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) is a browser cookie that Fern reads to identify a user's roles and API keys. With OAuth setup, Fern handles this token for you — you give Fern access to your OAuth provider, and Fern initiates the handshake process directly. +With OAuth, Fern manages the auth flow for you. You give Fern access to your OAuth provider, and Fern handles the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie that integrates your docs with your existing login system. Like [JWT](/learn/docs/authentication/setup/jwt), OAuth enables: + +- **[RBAC](/learn/docs/authentication/features/rbac)** — restrict content by user role +- **[API key injection](/learn/docs/authentication/features/api-key-injection)** — pre-fill API keys in the [API Explorer](/learn/docs/api-references/api-explorer) ## How it works -1. When a user clicks the **Login** button on your docs site (RBAC) or the API Explorer (API key injection), Fern initiates an OAuth flow by making a request to your authorization endpoint. -1. The user is redirected to your OAuth provider's login page where they authenticate using your existing auth system. -1. After successful authentication, your OAuth provider redirects back to Fern with an authorization code, which Fern exchanges for an access token at your token endpoint. -1. Fern sets a `fern_token` cookie containing the user's roles and credentials, enabling RBAC and automatically populating API keys in the API Explorer. +1. A user clicks **Login** on your docs site and Fern initiates an OAuth flow with your provider. +1. The user authenticates on your OAuth provider's login page. +1. Your provider redirects back to Fern with an authorization code, which Fern exchanges for an access token. +1. Fern sets a `fern_token` cookie containing the user's access and credentials. @@ -20,18 +23,19 @@ OAuth setup is used by both [RBAC](/learn/docs/authentication/rbac) and [API key -Go to your OAuth provider's dashboard. Create a new **web application** client. This is the client that will be used by Fern to authenticate users with your OAuth provider. +Go to your OAuth provider's dashboard and create a new **web application** client. Allowlist the following callback in your OAuth provider: `https:///api/fern-docs/oauth2/callback`. -Replace `` with whatever domain you are using for your Fern Docs site. If you want to authenticate both your `.docs.buildwithfern.com` and custom domain, you must allowlist both. +Replace `` with your Fern Docs domain. If you use both a `.docs.buildwithfern.com` and a custom domain, allowlist both. -Fern needs the following details to configure OAuth authentication: +Send the following to support@buildwithfern.com or your dedicated Slack channel: + - [ ] Docs domain - [ ] Client ID - [ ] Client secret @@ -45,16 +49,14 @@ If your client is connected to an API, you may need to specify an audience in th The updated authorization URL may look like this: `https:///oauth2/authorize?audience=` - -Send these details to support@buildwithfern.com or in your dedicated Slack channel. -Wait for Fern to configure OAuth. You'll receive a notification when the site is ready to use authentication. +Fern will configure OAuth on your site. You'll receive a notification when authentication is ready. - -The final step depends on which features you're using. + +Once OAuth is working, configure the features you need: @@ -103,11 +105,15 @@ To add a custom claim to Auth0, you need to create a **custom action**. This act 5. Click **Create**. 6. Add the action to your **Post Login Flow**. + Set up an authenticated account for Fern so Fern can authorize users on your behalf, and configure your OAuth application to return user API keys when Fern requests tokens. Contact support@buildwithfern.com to coordinate this setup. + +Once your token response includes roles, define those roles in `docs.yml` and assign them to navigation items and page content. See [Role-based access control](/learn/docs/authentication/features/rbac) for the full setup. + diff --git a/fern/products/docs/pages/authentication/overview.mdx b/fern/products/docs/pages/authentication/overview.mdx index 8899a4349..936378245 100644 --- a/fern/products/docs/pages/authentication/overview.mdx +++ b/fern/products/docs/pages/authentication/overview.mdx @@ -3,32 +3,34 @@ title: Overview of authentication options description: Understand the different authentication options Fern offers --- -Fern offers several ways to control access to your documentation, from simple password protection to granular role-based access control. +Fern offers four ways to authenticate users on your documentation site. - + A single shared password for the entire site - - Require login without role management + + Corporate credentials for internal docs - - Granular access for different audiences + + Self-managed auth integrated with your login system - - Autopopulate API keys in the API Explorer + + Fern-managed auth via your OAuth provider -## How authentication works +## Which option should I use? -[RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection) are powered by the same mechanism: a [browser cookie](/learn/docs/security/overview) called `fern_token` that tells Fern who the user is and what they can access. +- **[Password protection](/learn/docs/authentication/setup/password-protection)** — You need quick gating with a single shared password. No per-user accounts, no setup beyond `docs.yml`. +- **[SSO](/learn/docs/authentication/setup/sso)** — Your team should log in with corporate credentials (Okta, Google Workspace, etc.) for internal docs or wikis. +- **[JWT](/learn/docs/authentication/setup/jwt)** — You want to integrate with your existing login system and control the entire auth flow yourself. Enables [role-based access control](/learn/docs/authentication/features/rbac) and [API key injection](/learn/docs/authentication/features/api-key-injection). +- **[OAuth](/learn/docs/authentication/setup/oauth)** — You want to integrate with your existing login system but have Fern manage the auth flow via your OAuth provider. Enables [role-based access control](/learn/docs/authentication/features/rbac) and [API key injection](/learn/docs/authentication/features/api-key-injection). -Both features share the same token, so you can implement them together — a single `fern_token` can carry user roles for RBAC and API keys for the API Explorer at the same time. +JWT and OAuth share the same capabilities — the difference is who manages the auth flow. Both can be used for login-only gating, or combined with [RBAC](/learn/docs/authentication/features/rbac) and [API key injection](/learn/docs/authentication/features/api-key-injection) for granular access control and pre-filled API keys. -There are two ways to set up the `fern_token`: +## How authentication works -- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the `fern_token` cookie yourself. -- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — Fern initiates the OAuth handshake with your provider. +JWT, OAuth, and SSO are all powered by a [browser cookie](/learn/docs/security/overview) called `fern_token` that tells Fern who the user is and what they can access. The token can carry user roles for [RBAC](/learn/docs/authentication/features/rbac), API keys for the [API Explorer](/learn/docs/api-references/api-explorer), or simply verify that a user is logged in. -[SSO](/learn/docs/authentication/sso) also uses the `fern_token` but has its own setup process. [Password protection](/learn/docs/authentication/password-protection) works differently — it uses a shared password rather than per-user tokens. +[Password protection](/learn/docs/authentication/setup/password-protection) works differently — it uses a shared password rather than per-user tokens. diff --git a/fern/products/docs/pages/authentication/rbac.mdx b/fern/products/docs/pages/authentication/rbac.mdx index b1563e94a..112ca73d0 100644 --- a/fern/products/docs/pages/authentication/rbac.mdx +++ b/fern/products/docs/pages/authentication/rbac.mdx @@ -6,17 +6,15 @@ description: Learn how to restrict access to your documentation using role-based -RBAC lets you restrict pages, sections, and other navigation items to users with specific roles — useful for partner docs, beta features, tiered access, and internal content. You can combine RBAC with [API key injection](/learn/docs/authentication/api-key-injection) in a single token. +RBAC is a feature of [JWT](/learn/docs/authentication/setup/jwt) and [OAuth](/learn/docs/authentication/setup/oauth) authentication. Once a user logs in through either method, Fern checks the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to determine their roles and controls access to pages, sections, and other navigation items accordingly. -## How it works +RBAC is useful for partner docs, beta features, tiered access, and internal content. You can combine it with [API key injection](/learn/docs/authentication/features/api-key-injection) in a single token. When RBAC is configured, [Ask Fern](/learn/docs/ai-features/ask-fern/overview) automatically respects these permissions. -Every user automatically has the `everyone` role, including unauthenticated visitors. When a user visits content that requires a different role, Fern checks the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to determine their roles. If the user lacks the required role or isn't authenticated, Fern redirects them to your login page. - -When RBAC is configured, [Ask Fern](/learn/docs/ai-features/ask-fern/overview) automatically respects these permissions. +If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), let Fern know during setup. ## Setup -To enable RBAC, define your roles in `docs.yml` and configure authentication: +To enable RBAC, follow the [JWT](/learn/docs/authentication/setup/jwt) or [OAuth](/learn/docs/authentication/setup/oauth) setup guide, then define your roles in `docs.yml`: ```yml docs.yml roles: @@ -26,12 +24,7 @@ roles: - admins ``` -Then, set up the `fern_token` using either method: - -- **[JWT setup](/learn/docs/authentication/setup/jwt)** — You handle the entire auth flow and set the cookie yourself, including a `fern.roles` array in the JWT payload. -- **[OAuth setup](/learn/docs/authentication/setup/oauth)** — Fern initiates an OAuth flow with your provider. Configure your token response to include user roles. - -If you'd like restricted pages to be visible but locked to unauthenticated users (rather than completely hidden), let Fern know during setup. +Every user automatically has the `everyone` role, including unauthenticated visitors. If a user lacks the required role or isn't authenticated, Fern redirects them to your login page. ## Restricting content diff --git a/fern/products/docs/pages/authentication/sso.mdx b/fern/products/docs/pages/authentication/sso.mdx index d948a5806..23af85bce 100644 --- a/fern/products/docs/pages/authentication/sso.mdx +++ b/fern/products/docs/pages/authentication/sso.mdx @@ -5,9 +5,9 @@ subtitle: Secure access to your documentation using corporate credentials -SSO lets your team access your docs through your organization's identity provider using SAML 2.0 or OIDC. Like [RBAC](/learn/docs/authentication/rbac) and [API key injection](/learn/docs/authentication/api-key-injection), SSO uses the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to identify authenticated users. SSO unlocks the [Fern Editor](/learn/docs/writing-content/fern-editor) for browser-based editing and [authenticated preview links](/learn/docs/preview-publish/preview-changes#preview-links). +SSO lets your team access your docs through your organization's identity provider using SAML 2.0 or OIDC. Like [RBAC](/learn/docs/authentication/features/rbac) and [API key injection](/learn/docs/authentication/features/api-key-injection), SSO uses the [`fern_token`](/learn/docs/authentication/overview#how-authentication-works) cookie to identify authenticated users. SSO unlocks the [Fern Editor](/learn/docs/writing-content/fern-editor) for browser-based editing and [authenticated preview links](/learn/docs/preview-publish/preview-changes#preview-links). -SSO provides login-based access control but does not support role management or API key injection. For granular access control, use [RBAC](/learn/docs/authentication/rbac) instead. +SSO provides login-based access control but does not support role management or API key injection. For granular access control, use [RBAC](/learn/docs/authentication/features/rbac) instead. ## How it works diff --git a/fern/products/docs/pages/changelog/2026-01-17.mdx b/fern/products/docs/pages/changelog/2026-01-17.mdx index 9c472000f..e369cbb0b 100644 --- a/fern/products/docs/pages/changelog/2026-01-17.mdx +++ b/fern/products/docs/pages/changelog/2026-01-17.mdx @@ -22,4 +22,4 @@ The `` component now supports `products` and `versions` props, allowing you You can also use the `not` prop to invert the condition, showing content when the current product or version does not match. -Learn more about the [If component](/learn/docs/authentication/rbac#in-mdx-pages). +Learn more about the [If component](/learn/docs/authentication/features/rbac#in-mdx-pages). diff --git a/fern/products/docs/pages/changelog/2026-02-11.mdx b/fern/products/docs/pages/changelog/2026-02-11.mdx index de8df33df..02e188d38 100644 --- a/fern/products/docs/pages/changelog/2026-02-11.mdx +++ b/fern/products/docs/pages/changelog/2026-02-11.mdx @@ -1,6 +1,6 @@ ## API key injection for self-hosted docs -Self-hosted deployments support [API key injection](/learn/docs/authentication/api-key-injection) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. +Self-hosted deployments support [API key injection](/learn/docs/authentication/features/api-key-injection) via environment variables. Enable `FERN_API_KEY_INJECTION_ENABLED` to show a **Login** button in the API Explorer without requiring login for the entire site. Use `FERN_AUTH_ALLOWLIST` and `FERN_AUTH_DENYLIST` to control page-level access. Learn more about [self-hosted authentication](/learn/docs/self-hosted/authentication#api-key-injection). diff --git a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx index 4886d8a80..7f66a719b 100644 --- a/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx +++ b/fern/products/docs/pages/enterprise/self-hosted-authentication.mdx @@ -203,7 +203,7 @@ ENV FERN_AUTH_DENYLIST="/api-reference/(.*)" ## API key injection -You can enable [API key injection](/learn/docs/authentication/api-key-injection) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. +You can enable [API key injection](/learn/docs/authentication/features/api-key-injection) in the API Explorer for self-hosted deployments. This shows a **Login** button in the API Explorer so users can authenticate and have their API keys auto-populated, without requiring login for the entire documentation site. Add `FERN_API_KEY_INJECTION_ENABLED` to your Dockerfile alongside the basic token verification variables: @@ -222,4 +222,4 @@ ENV FERN_AUTH_ALLOWLIST="/(.*)" RUN fern-generate ``` -With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/api-key-injection) for the full `fern` payload reference. +With `FERN_AUTH_ALLOWLIST="/(.*)"`, all doc pages are publicly accessible (no login wall), but the API Explorer still shows the **Login** button. When a user logs in, their JWT's `fern` payload is read and the API key is injected into the API Explorer. See [Autopopulate API keys](/learn/docs/authentication/features/api-key-injection) for the full `fern` payload reference. diff --git a/fern/products/docs/pages/enterprise/self-hosted.mdx b/fern/products/docs/pages/enterprise/self-hosted.mdx index aa849bab8..f67121ece 100644 --- a/fern/products/docs/pages/enterprise/self-hosted.mdx +++ b/fern/products/docs/pages/enterprise/self-hosted.mdx @@ -21,7 +21,7 @@ Unless you have specific requirements that prevent using Fern's default hosting, Self-hosted deployments include core Fern documentation website features like auto-generated API references, interactive documentation, SDK code snippets, search, and customizable branding. -However, features requiring external connections aren't supported, including [Ask Fern](/learn/docs/ai-features/ask-fern/overview) (AI chat), [analytics](/learn/docs/integrations/overview), and [SSO integrations](/learn/docs/authentication/sso). +However, features requiring external connections aren't supported, including [Ask Fern](/learn/docs/ai-features/ask-fern/overview) (AI chat), [analytics](/learn/docs/integrations/overview), and [SSO integrations](/learn/docs/authentication/setup/sso). **PDF export** and **offline AI chat functionality** are not yet available on any plan but are in development for enterprise self-hosted deployments. [Email us](mailto:support@buildwithfern.com) if you're interested in these features. diff --git a/fern/products/docs/pages/navigation/tabs.mdx b/fern/products/docs/pages/navigation/tabs.mdx index 3a4e4efcc..ebd41e5ec 100644 --- a/fern/products/docs/pages/navigation/tabs.mdx +++ b/fern/products/docs/pages/navigation/tabs.mdx @@ -133,7 +133,7 @@ theme: ## Tab variants -Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/rbac). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. +Tab variants let you display different content variations within a single tab, and [support RBAC](/learn/docs/authentication/features/rbac). This is useful for showing different user types, implementation approaches, or experience levels without creating separate tabs. Use **variants** for different perspectives on the same content area (REST vs. GraphQL, beginner vs. advanced). Use **tabs** for completely different documentation sections (guides vs. API Reference). diff --git a/fern/products/docs/pages/resources/stainless-comparison.mdx b/fern/products/docs/pages/resources/stainless-comparison.mdx index e912ce63b..745d24857 100644 --- a/fern/products/docs/pages/resources/stainless-comparison.mdx +++ b/fern/products/docs/pages/resources/stainless-comparison.mdx @@ -14,7 +14,7 @@ Choose Fern for enterprise requirements, regulated industries, or production-cri |------------|------|-----------| | **Maturity** | Production-ready, stable APIs | Early access, breaking changes expected | | **Authoring** | [Visual editor](/learn/docs/writing-content/fern-editor) + Git | Git only | -| **Enterprise features** | [RBAC](/learn/docs/authentication/rbac), [SSO](/learn/docs/authentication/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | +| **Enterprise features** | [RBAC](/learn/docs/authentication/features/rbac), [SSO](/learn/docs/authentication/setup/sso), [versioning](/learn/docs/configuration/site-level-settings) | None | | **API testing** | [Interactive explorer](/learn/docs/api-references/api-explorer) | None | | **Deployment** | Cloud + [full-stack self-hosted](/learn/docs/self-hosted/overview) | Static files only | @@ -50,7 +50,7 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/api-key-injection), WebSocket, and audio streaming support | ❌ None | +| **API Explorer** | ✅ [Full playground](/learn/docs/api-references/api-explorer) with [auto-populated credentials](/learn/docs/authentication/features/api-key-injection), WebSocket, and audio streaming support | ❌ None | | **SDK documentation** | ✅ [Multi-language support](/learn/docs/api-references/sdk-snippets) | ✅ Language-specific pages | | **API spec formats** | ✅ [OpenAPI, AsyncAPI, gRPC, OpenRPC, Fern](/learn/docs/api-references/generate-api-ref) | ⚠️ OpenAPI + Stainless config only |
@@ -58,11 +58,11 @@ Stainless doesn't provide an interactive testing environment. Fern's [API Explor -Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/rbac) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. +Stainless doesn't offer audience-specific content filtering, multi-version APIs, or unified multi-product sites. Fern provides [RBAC](/learn/docs/authentication/features/rbac) and [versioning](/learn/docs/configuration/site-level-settings) capabilities for complex API portfolios. | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/rbac) for internal vs. public sites | ❌ None | +| **RBAC** | ✅ [Audience-based content filtering](/learn/docs/authentication/features/rbac) for internal vs. public sites | ❌ None | | **API versioning** | ✅ [Multi-version support](/learn/docs/configuration/site-level-settings) with availability states and per-version content | ❌ None | | **Multi-product sites** | ✅ [Multiple products](/learn/docs/configuration/site-level-settings) in unified documentation | ⚠️ Basic tabs (Guides/Reference) |
@@ -83,12 +83,12 @@ Stainless offers RAG-based search. Fern provides additional AI features includin -Stainless's [authentication](https://www.stainless.com/docs/docs-platform/advanced/stainless-authentication/) focuses on API keys for their service. Fern's [WorkOS integration](/learn/docs/authentication/sso) provides enterprise SSO (SAML/OIDC) for end-user authentication with role-based content visibility. +Stainless's [authentication](https://www.stainless.com/docs/docs-platform/advanced/stainless-authentication/) focuses on API keys for their service. Fern's [WorkOS integration](/learn/docs/authentication/setup/sso) provides enterprise SSO (SAML/OIDC) for end-user authentication with role-based content visibility. | Feature | Fern Docs | Stainless Docs | |---------|-----------|----------------| -| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/rbac) | ❌ None | -| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/authentication/api-key-injection) | ⚠️ API keys for Stainless service only | +| **Enterprise SSO** | ✅ [WorkOS](/learn/docs/authentication/setup/sso) (SAML/OIDC/SCIM) with [RBAC](/learn/docs/authentication/features/rbac) | ❌ None | +| **Authenticated pages** | ✅ [Login-protected documentation](/learn/docs/authentication/overview) with [auto-populated credentials](/learn/docs/authentication/features/api-key-injection) | ⚠️ API keys for Stainless service only |
diff --git a/fern/products/docs/pages/security/overview.mdx b/fern/products/docs/pages/security/overview.mdx index 4d9caf93f..7423e36cf 100644 --- a/fern/products/docs/pages/security/overview.mdx +++ b/fern/products/docs/pages/security/overview.mdx @@ -13,9 +13,9 @@ Fern's documentation platform is built with security as a core principle, using Fern supports [multiple authentication methods](/learn/docs/authentication/overview) to secure your documentation. All methods use a client-side `fern_token` cookie stored entirely in the browser: -- [Role-Based Access Control (RBAC)](/learn/docs/authentication/rbac) controls which users can access specific documentation content based on their roles (stores user roles) -- [API key injection](/learn/docs/authentication/api-key-injection) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) -- [Single Sign-On (SSO)](/learn/docs/authentication/sso) integrates with your existing identity provider for seamless authentication (stores identity provider tokens) +- [Role-Based Access Control (RBAC)](/learn/docs/authentication/features/rbac) controls which users can access specific documentation content based on their roles (stores user roles) +- [API key injection](/learn/docs/authentication/features/api-key-injection) automatically populates code examples with user-specific API keys for a personalized experience (stores authentication tokens via JWT or OAuth) +- [Single Sign-On (SSO)](/learn/docs/authentication/setup/sso) integrates with your existing identity provider for seamless authentication (stores identity provider tokens) These cookies are managed entirely client-side and automatically cleared when the user logs out or the session expires. This approach ensures that sensitive credentials remain under your control and are never exposed to Fern's infrastructure.