mirror of
https://github.com/mintlify/docs.git
synced 2026-09-14 13:35:46 +08:00
391 lines
14 KiB
Plaintext
391 lines
14 KiB
Plaintext
---
|
|
title: "Authentication setup"
|
|
description: "Control access to your documentation by authenticating users."
|
|
keywords: ['authentication', 'auth', 'OAuth', 'JWT', 'password']
|
|
---
|
|
|
|
<Info>
|
|
[Pro plans](https://mintlify.com/pricing?ref=authentication) include password authentication.
|
|
|
|
[Enterprise plans](https://mintlify.com/pricing?ref=authentication) include all authentication methods.
|
|
</Info>
|
|
|
|
Authentication requires users to log in before accessing your documentation. You can configure specific pages or groups as public while keeping other pages protected.
|
|
|
|
## Configure authentication
|
|
|
|
<Tabs>
|
|
<Tab title="Password">
|
|
<Info>
|
|
Password authentication provides access control only and does **not** support user-specific features like group-based access control or API playground pre-filling.
|
|
</Info>
|
|
|
|
### Prerequisites
|
|
|
|
* Your security requirements allow sharing passwords among users.
|
|
|
|
### Set up
|
|
|
|
<Steps>
|
|
<Step title="Create a password.">
|
|
1. In your dashboard, go to [Authentication](https://dashboard.mintlify.com/products/authentication).
|
|
2. Enable authentication.
|
|
3. In the **Password Protection** section, enter a secure password
|
|
|
|
After you enter a password, your site redeploys. When it finishes deploying, anyone who visits your site must enter the password to access your content.
|
|
</Step>
|
|
<Step title="Distribute access.">
|
|
Securely share the password and documentation URL with authorized users.
|
|
</Step>
|
|
</Steps>
|
|
|
|
</Tab>
|
|
<Tab title="Mintlify dashboard">
|
|
### Prerequisites
|
|
|
|
* Everyone who needs to access your documentation must be a member of your Mintlify organization.
|
|
|
|
### Set up
|
|
|
|
<Steps>
|
|
<Step title="Enable Mintlify dashboard authentication.">
|
|
1. In your dashboard, go to [Authentication](https://dashboard.mintlify.com/products/authentication).
|
|
2. Enable authentication.
|
|
3. In the **Custom Authentication** section, click **Mintlify Auth**.
|
|
4. Click **Enable Mintlify Auth**.
|
|
|
|
After you enable Mintlify authentication, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your Mintlify organization to access your content.
|
|
</Step>
|
|
<Step title="Add authorized users.">
|
|
1. In your dashboard, go to [Members](https://dashboard.mintlify.com/settings/organization/members).
|
|
2. Add each person who should have access to your documentation.
|
|
3. Assign appropriate roles based on their editing permissions.
|
|
</Step>
|
|
</Steps>
|
|
|
|
</Tab>
|
|
<Tab title="OAuth 2.0">
|
|
### Prerequisites
|
|
|
|
* An OAuth or OIDC server that supports the Authorization Code Flow.
|
|
* Ability to create an API endpoint accessible by OAuth access tokens (optional, to enable group-based access control).
|
|
|
|
### Set up
|
|
|
|
<Steps>
|
|
<Step title="Configure your OAuth settings.">
|
|
1. In your dashboard, go to [Authentication](https://dashboard.mintlify.com/products/authentication).
|
|
2. Enable authentication.
|
|
3. In the **Custom Authentication** section, click **OAuth**.
|
|
4. Configure these fields:
|
|
* **Authorization URL**: Your OAuth endpoint.
|
|
* **Client ID**: Your OAuth 2.0 client identifier.
|
|
* **Client Secret**: Your OAuth 2.0 client secret.
|
|
* **Scopes** (optional): Permissions to request.
|
|
* **Additional authorization parameters** (optional): Additional query parameters to add to the initial authorization request.
|
|
* **Token URL**: Your OAuth token exchange endpoint.
|
|
* **Info API URL** (optional): Endpoint on your server that Mintlify calls to retrieve user info. Required for group-based access control.
|
|
* **Logout URL** (optional): The native logout URL for your OAuth provider. If not configured, users redirect to `/login`.
|
|
* **Redirect URL** (optional): The URL to redirect users to after authentication.
|
|
5. Click **Save changes**.
|
|
|
|
After you configure your OAuth settings, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your OAuth provider to access your content.
|
|
</Step>
|
|
<Step title="Configure your OAuth server.">
|
|
1. Copy the **Redirect URL** from your [authentication settings](https://dashboard.mintlify.com/products/authentication).
|
|
2. Add the redirect URL as an authorized redirect URL for your OAuth server.
|
|
</Step>
|
|
<Step title="Create your user info endpoint (optional).">
|
|
To enable group-based access control, create an API endpoint that:
|
|
* Responds to `GET` requests.
|
|
* Accepts an `Authorization: Bearer <access_token>` header for authentication.
|
|
* Returns user data in the `User` format. See [User data format](#user-data-format) for more information.
|
|
|
|
Mintlify calls this endpoint with the OAuth access token to retrieve user information.
|
|
|
|
Add this endpoint URL to the **Info API URL** field in your [authentication settings](https://dashboard.mintlify.com/products/authentication).
|
|
</Step>
|
|
</Steps>
|
|
|
|
<Note>
|
|
Control session length with the `expiresAt` field in your user info response. This is a Unix timestamp (seconds since epoch) indicating when the session should expire. See [User data format](#user-data-format) for more details.
|
|
</Note>
|
|
|
|
</Tab>
|
|
<Tab title="JWT">
|
|
### Prerequisites
|
|
|
|
* An authentication system that can generate and sign JWTs.
|
|
* A backend service that can create redirect URLs.
|
|
|
|
### Set up
|
|
|
|
<Steps>
|
|
<Step title="Generate a private key.">
|
|
1. In your dashboard, go to [Authentication](https://dashboard.mintlify.com/products/authentication).
|
|
2. Enable authentication.
|
|
3. In the **Custom Authentication** section, click **JWT**.
|
|
4. Enter the URL of your existing login flow.
|
|
5. Click **Save changes**.
|
|
6. Click **Generate new key**.
|
|
7. Store your key securely where it can be accessed by your backend.
|
|
|
|
After you generate a private key, your site redeploys. When it finishes deploying, anyone who visits your site must log in to your JWT authentication system to access your content.
|
|
</Step>
|
|
<Step title="Integrate Mintlify authentication into your login flow.">
|
|
Modify your existing login flow to include these steps after user authentication:
|
|
|
|
* Create a JWT containing the authenticated user's info in the `User` format. See [User data format](#user-data-format) for more information.
|
|
* Sign the JWT with your secret key, using the EdDSA algorithm.
|
|
* Create a redirect URL back to the `/login/jwt-callback` path of your docs, including the JWT as the hash.
|
|
</Step>
|
|
</Steps>
|
|
|
|
### Example
|
|
|
|
After verifying user credentials, generate a JWT with user data and redirect to `https://docs.foo.com/login/jwt-callback#{SIGNED_JWT}`.
|
|
|
|
<CodeGroup>
|
|
```ts TypeScript
|
|
import * as jose from 'jose';
|
|
import { Request, Response } from 'express';
|
|
|
|
const TWO_WEEKS_IN_MS = 1000 * 60 * 60 * 24 * 7 * 2;
|
|
|
|
const signingKey = await jose.importPKCS8(process.env.MINTLIFY_PRIVATE_KEY, 'EdDSA');
|
|
|
|
export async function handleRequest(req: Request, res: Response) {
|
|
const user = {
|
|
expiresAt: Math.floor((Date.now() + TWO_WEEKS_IN_MS) / 1000), // 2 week session expiration
|
|
groups: res.locals.user.groups,
|
|
apiPlaygroundInputs: {
|
|
header: {
|
|
"Authorization": `Bearer ${res.locals.user.apiKey}`,
|
|
},
|
|
},
|
|
};
|
|
|
|
const jwt = await new jose.SignJWT(user)
|
|
.setProtectedHeader({ alg: 'EdDSA' })
|
|
.setExpirationTime('10 s') // 10 second JWT expiration
|
|
.sign(signingKey);
|
|
|
|
return res.redirect(`https://docs.foo.com/login/jwt-callback#${jwt}`);
|
|
}
|
|
```
|
|
|
|
```python Python
|
|
import jwt # pyjwt
|
|
import os
|
|
|
|
from datetime import datetime, timedelta
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
private_key = os.getenv(MINTLIFY_JWT_PEM_SECRET_NAME, '')
|
|
|
|
@router.get('/auth')
|
|
async def return_mintlify_auth_status(current_user):
|
|
jwt_token = jwt.encode(
|
|
payload={
|
|
'exp': int((datetime.now() + timedelta(seconds=10)).timestamp()), # 10 second JWT expiration
|
|
'expiresAt': int((datetime.now() + timedelta(weeks=2)).timestamp()), # 2 week session expiration
|
|
'groups': ['admin'] if current_user.is_admin else [],
|
|
'apiPlaygroundInputs': {
|
|
'header': {
|
|
'Authorization': f'Bearer {current_user.api_key}',
|
|
},
|
|
},
|
|
},
|
|
key=private_key,
|
|
algorithm='EdDSA'
|
|
)
|
|
|
|
return RedirectResponse(url=f'https://docs.foo.com/login/jwt-callback#{jwt_token}', status_code=302)
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Redirect unauthenticated users
|
|
|
|
When an unauthenticated user tries to access a protected page, the redirect to your login URL preserves the user's intended destination.
|
|
|
|
1. User attempts to visit a protected page: `https://docs.foo.com/quickstart`.
|
|
2. Redirect to your login URL with a redirect query parameter: `https://foo.com/docs-login?redirect=%2Fquickstart`.
|
|
3. After authentication, redirect to `https://docs.foo.com/login/jwt-callback?redirect=%2Fquickstart#{SIGNED_JWT}`.
|
|
4. User lands in their original destination.
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## Make pages public
|
|
|
|
When using authentication, all pages require authentication by default. You can make specific pages viewable without authentication at the page or group level with the `public` property.
|
|
|
|
### Individual pages
|
|
|
|
Add `public: true` to the page's frontmatter.
|
|
|
|
```mdx Public page example
|
|
---
|
|
title: "Public page"
|
|
public: true
|
|
---
|
|
```
|
|
|
|
### Groups of pages
|
|
|
|
Add `"public": true` beneath the group's name in the `navigation` object of your `docs.json`.
|
|
|
|
```json Public group example
|
|
{
|
|
"navigation": {
|
|
"groups": [
|
|
{
|
|
"group": "Public group",
|
|
"public": true,
|
|
"icon": "play",
|
|
"pages": [
|
|
"quickstart",
|
|
"installation",
|
|
"settings"
|
|
]
|
|
},
|
|
{
|
|
"group": "Private group",
|
|
"icon": "pause",
|
|
"pages": [
|
|
"private-information",
|
|
"secret-settings"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Control access with groups
|
|
|
|
When you use OAuth or JWT authentication, you can restrict specific pages to certain user groups. Manage groups through user data passed during authentication. See [User data format](#user-data-format) for details.
|
|
|
|
```json Example user info
|
|
{
|
|
"groups": ["admin", "beta-users"],
|
|
"expiresAt": 1735689600
|
|
}
|
|
```
|
|
|
|
Specify which groups can access specific pages using the `groups` property in frontmatter.
|
|
|
|
```mdx Example page restricted to the admin group highlight={3}
|
|
---
|
|
title: "Admin dashboard"
|
|
groups: ["admin"]
|
|
---
|
|
```
|
|
|
|
Users must belong to at least one of the listed groups to access the page. If a user tries to access a page without the required group, they'll receive a 404 error.
|
|
|
|
### How groups interact with public pages
|
|
|
|
- All pages require authentication by default.
|
|
- Pages with a `groups` property are only accessible to authenticated users in those groups.
|
|
- Pages without a `groups` property are accessible to all authenticated users.
|
|
- Pages with `public: true` and no `groups` property are accessible to everyone.
|
|
|
|
<CodeGroup>
|
|
|
|
```mdx Public page
|
|
---
|
|
title: "Public guide"
|
|
public: true
|
|
---
|
|
```
|
|
|
|
```mdx Protected page
|
|
---
|
|
title: "API reference"
|
|
---
|
|
```
|
|
|
|
```mdx Protected page with groups
|
|
---
|
|
title: "Advanced configurations"
|
|
groups: ["pro", "enterprise"]
|
|
---
|
|
```
|
|
</CodeGroup>
|
|
|
|
## User data format
|
|
|
|
When using OAuth or JWT authentication, your system returns user data that controls session length, group membership, and [content personalization](/create/personalization).
|
|
|
|
<CodeGroup>
|
|
```tsx Format
|
|
type User = {
|
|
expiresAt?: number;
|
|
groups?: string[];
|
|
content?: Record<string, any>;
|
|
apiPlaygroundInputs?: {
|
|
server?: Record<string, string>;
|
|
header?: Record<string, unknown>;
|
|
query?: Record<string, unknown>;
|
|
cookie?: Record<string, unknown>;
|
|
};
|
|
};
|
|
```
|
|
|
|
```json Example
|
|
{
|
|
"expiresAt": 1735689600,
|
|
"groups": ["admin", "beta-users"],
|
|
"content": {
|
|
"firstName": "Jane",
|
|
"company": "Acme Corp"
|
|
},
|
|
"apiPlaygroundInputs": {
|
|
"header": {
|
|
"Authorization": "Bearer user_abc123"
|
|
},
|
|
"server": {
|
|
"baseUrl": "https://api.foo.com"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
</CodeGroup>
|
|
|
|
<ParamField path="expiresAt" type="number">
|
|
Session expiration time in seconds since epoch. When the current time passes this value, the user must re-authenticate.
|
|
|
|
<Warning>**For JWT:** This differs from the JWT's `exp` claim, which determines when a JWT is considered invalid. Set the JWT `exp` claim to a short duration (10 seconds or less) for security. Use `expiresAt` for the actual session length (hours to weeks).</Warning>
|
|
</ParamField>
|
|
|
|
<ParamField path="groups" type="string[]">
|
|
List of groups the user belongs to. Pages with matching `groups` in their frontmatter are accessible to this user.
|
|
|
|
**Example**: A user with `groups: ["admin", "engineering"]` can access pages tagged with either the `admin` or `engineering` groups.
|
|
</ParamField>
|
|
|
|
<ParamField path="content" type="Record<string, any>">
|
|
Custom data accessible in MDX pages via the `user` variable for [personalized content](/create/personalization#dynamic-mdx-content).
|
|
</ParamField>
|
|
|
|
<ParamField path="apiPlaygroundInputs" type="object">
|
|
Pre-fills API playground fields with user-specific values. When a user authenticates, these values populate the corresponding input fields in the API playground. Users can override pre-filled values, and their overrides persist in local storage.
|
|
|
|
Only values that match the current endpoint's security scheme are applied.
|
|
|
|
<Expandable title="properties">
|
|
<ParamField path="header" type="Record<string, unknown>">
|
|
Header values to pre-fill, keyed by header name.
|
|
</ParamField>
|
|
<ParamField path="query" type="Record<string, unknown>">
|
|
Query parameter values to pre-fill, keyed by parameter name.
|
|
</ParamField>
|
|
<ParamField path="cookie" type="Record<string, unknown>">
|
|
Cookie values to pre-fill, keyed by cookie name.
|
|
</ParamField>
|
|
<ParamField path="server" type="Record<string, string>">
|
|
Server variable values to pre-fill, keyed by variable name.
|
|
</ParamField>
|
|
</Expandable>
|
|
</ParamField>
|