Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions integrations/user-auth/choosing-an-auth-method.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: 'Choosing an Auth Method'
description: 'How to decide which auth method is right for your docs'
---

Before your users can access personalized content, they must be authenticated. Mintlify supports two methods of authenticating users:

1. **Shared Session**: Utilize the same session token used by your dashboard to authenticate users.
2. **JWT**: Use your own login flow to send user info to your docs via a JWT in the URL.

## Prerequisites

<Tabs>
<Tab title="Shared Session">
- You have a dashboard or other user portal hosted at your domain.
- Your users' session credentials are stored as cookies.
- You can create a new API endpoint at the same origin or a subdomain of your dashboard.
- If your dashboard is at `foo.com`, the **API URL** must start with `foo.com` or `*.foo.com`
- If your dashboard is at `dash.foo.com`, the **API URL** must start with `dash.foo.com` or `*.dash.foo.com`
- Your docs are hosted at the same domain as your dashboard.
- If your dashboard is at `foo.com`, your **docs** must be hosted at `foo.com` or `*.foo.com`
- If your dashboard is at `*.foo.com`, your **docs** must be hosted at `foo.com` or `*.foo.com`
</Tab>
<Tab title="JWT">
- You have some existing login flow.
- You can add a final step in this login flow that creates a JWT and redirects to the docs.
</Tab>
</Tabs>

## Pros & Cons

<Tabs>
<Tab title="Shared Session">
Pros:

- Users that are logged into your dashboard are automatically logged into your docs
- Your users' sessions are persistent, meaning you can refresh data without requiring additional login
- Minimal setup required

Cons:

- Your docs will make a request to your backend, which may be undesirable
</Tab>
<Tab title="JWT">
Pros:

- No dashboard needed
- Reduced risk of API endpoint abuse
- Zero CORS configuration

Cons:

- Must build new functionality around your existing login flow
- Dashboard sessions and docs authentication are completely decoupled, so users will need to log in to your dashboard and your docs separately
- Every time you want to refresh user data, your users must re-login to your docs
- If your users' data changes frequently, you must require your users to log in frequently or risk having stale data in the docs
- If your users' data rarely changes, this shouldn't be a problem
</Tab>
</Tabs>
32 changes: 32 additions & 0 deletions integrations/user-auth/jwt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: 'JWT Auth'
description: 'Use a customized login flow to authenticate users'
---

If you don’t have a dashboard, or if you want to keep your dashboard and docs completely separate, you can use your own login flow to send user info to your docs via a JWT in the URL.

## Implementation

<Steps>
<Step title="Generate a private key">
Go to your [Mintlify dashboard settings](https://dashboard.mintlify.com/settings/integrations) and generate a private key. Store this key somewhere secure where it can be accessed by your backend.
</Step>
<Step title="Create a login flow">
Create a login flow that does the following:
- Authenticate the user
- Create a JWT containing the authenticated user's info in the [UserInfo](./sending-data) format
- Sign the JWT with the secret
- Create a redirect URL back to your docs, including the JWT as a query parameter with the name `user_auth`
</Step>
<Step title="Configure your User Auth settings">
Return to your [Mintlify dashboard settings](https://dashboard.mintlify.com/settings/integrations) and add the login URL to your User Auth settings.
</Step>
</Steps>

## Example

I want to set up authentication for my docs hosted at `docs.foo.com`. I want my docs to be completely separate from my dashboard (or I don’t have a dashboard at all).

To set up authentication with Mintlify, I go to my Mintlify dashboard and generate a JWT secret. I create a web URL `https://foo.com/docs-login` that initiates a login flow for my users. At the end of this login flow, once I have verified the identity of the user, I create a JWT containing the user’s custom data according to Mintlify’s specification. I sign this JWT with my Mintlify secret, create a redirect URL of the form `https://docs.foo.com?user_auth={SIGNED_JWT}`, and redirect the user.

I then go to the Mintlify dashboard settings and enter `https://foo.com/docs-login` for the Login URL field.
81 changes: 81 additions & 0 deletions integrations/user-auth/overview.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
title: 'Overview'
description: 'Give your users a personalized docs experience'
---

Sometimes, when writing docs, you wish you knew just a little bit about the person reading them. Maybe you only want to show them the information they should care about. Maybe you want to craft examples that they can use out-of-the-box.

With Mintlify, you can add User Auth to identify your users and tailor your docs content to them.

## What is User Auth

User Auth allows you to configure a method for identifying and authenticating your users. Once authenticated, you can share user-specific information that can be used to personalize the docs. This unlocks some powerful features:

1. **Customize MDX content** with a user's information, such as their name, plan, or title.
2. **Prefill API keys** in the API Playground for streamlined use.
3. <b className="text-primary">(Coming soon!)</b> **Selectively show pages** in the navigation based on a user's groups.

## What *isn't* User Auth

At this time, User Auth cannot provide any of the following:

1. **Private docs content.** While you can hide pages from unauthenticated users, those pages are still accessible by anyone who can guess the URL. If your documentation contains sensitive information, User Auth is not enough to hide it.
2. **A Mintlify-backed user database.** Mintlify does not store *any* information about your users. Rather, it relies on your existing infrastructure to serve as the source-of-truth for user data.

<Note>If you are interested in private docs content, [contact our team](sales@mintlify.com) to explore solutions.</Note>

## How to Use
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we should have a "How to Set Up" or at least like right below this "How to Use" explain that you need to choose between shared session or jwt and set it up in the dashboard?


### Customizing MDX Content

When writing content, you can use the `userContext` variable to access the information you have sent to your docs. Here's a real world example:

User Auth is an enterprise feature. {
userContext.org === undefined
? <>To access this feature, first create an account at the <a href="https://dashboard.mintlify.com/login">Mintlify dashboard</a>.</>
: userContext.org.plan !== 'enterprise'
? <>You are currently on the ${userContext.org.plan ?? 'free'} plan. To upgrade, navigate to the <a href="https://dashboard.mintlify.com/settings/billing">billing page</a> in the Mintlify dashboard.</>
: <>As an enterprise organization, you can enable this feature right now from your <a href="https://dashboard.mintlify.com/settings/integrations">Mintlify dashboard settings</a></>
}

```jsx
User Auth is an enterprise feature. {
userContext.org === undefined
? <>To access this feature, first create an account at the <a href="https://dashboard.mintlify.com/login">Mintlify dashboard</a>.</>
: userContext.org.plan !== 'enterprise'
? <>You are currently on the ${userContext.org.plan ?? 'free'} plan. To upgrade, navigate to the <a href="https://dashboard.mintlify.com/settings/billing">billing page</a> in the Mintlify dashboard.</>
: <>As an enterprise organization, you can enable this feature right now from your <a href="https://dashboard.mintlify.com/settings/integrations">Mintlify dashboard settings</a></>
}
```

<Note>
The information in `userContext` is only available after a user has logged in. For logged out users, the value of `userContext` will be `{}`. To prevent the page from crashing for logged-out users, always use optional chaining on your `userContext` fields, e.g. `{userContext.org?.plan}`
</Note>

### Prefilling API Keys

If you return API Playground inputs in the user info, they will automatically be prefilled in the API Playground. Make sure the name of the field in the user info is an exact match of the name in the API Playground.
{/*
### Showing/Hiding Pages

By default, every page is visible to every user. If you want to restrict which pages are visible to your users, you can add a `groups` field in your page metadata.
When determining which pages to show to the user, Mintlify will check which groups the user belongs to.
If the user is not in any of the groups listed in the page metadata, the page will not be shown.

```md
---
title: 'Managing Your Users'
description: 'Adding and removing users from your organization'
groups: ['admin']
---
```

Here's a table that displays whether a page is shown for different combinations of `groups` in UserInfo and page metadata:

| | `groups` not in UserInfo | `groups: []` in UserInfo | `groups: ['admin']` in UserInfo |
|:-----------------------------------|:------------------------:|:-------------------------:|:--------------------------------:|
| `groups` not in metadata | ✅ | ✅ | ✅ |
| `groups: []` in metadata | ❌ | ❌ | ❌ |
| `groups: ['admin']` in metadata | ❌ | ❌ | ✅ |

<Note>Note that an empty array in the page metadata is interpreted as "No groups should see this page."</Note> */}
50 changes: 50 additions & 0 deletions integrations/user-auth/sending-data.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: 'Sending Data'
description: 'The types and shape of user data you can send to Mintlify'
---

Depending on your authentication configuration, your API will respond with either a raw JSON object or a signed JWT. The shape of the data is the same for both:

```tsx
type UserInfo = {
expiresAt?: number;
groups?: string[];
content?: Record<string, any>;
apiPlaygroundInputs?: {
header?: Record<string, any>;
query?: Record<string, any>;
cookie?: Record<string, any>;
server?: Record<string, string>;
};
};
```

<ParamField
path="expiresAt"
type="number"
>
The time at which this information should expire, in **seconds since epoch**. If the user loads the page and the current time is after this value, the stored data will be deleted.
<Warning><b>For JWT Auth:</b> This is *not* the same as the `exp` claim of the JWT. The `exp` claim determines when a JWT should no longer be considered valid, and should be set as low as possible. In this case, it can probably be set to 10 seconds or lower. The `expiresAt` field determines when retrieved data should be considered stale, and can be anywhere from one day to several weeks.</Warning>
</ParamField>
<ParamField
path="groups"
type="string[]"
>
A list of groups that the user belongs to. This will determine which pages should be shown to this user. If any of these groups is listed in the `groups` field of a page’s metadata, that page will be shown.
</ParamField>
<ParamField
path="content"
type="object"
>
A bag of values that can be accessed from within MDX content using the `userContext` variable. For example, if you have supplied `{ firstName: 'Ronan' }` as your content field, you can use the following in your MDX: `Good morning, {userContext.firstName}!`
</ParamField>
<ParamField
path="apiPlaygroundInputs"
type="object"
>
User-specific values that will be prefilled in the API playground if supplied. For example, if each of my customers makes requests at a specific subdomain, I can send `{ server: { subdomain: 'foo' } }` as my `apiPlaygroundInputs` field, and this value will be prefilled on any API page with this `subdomain` value.

<Note>The`header`, `query`, and `cookie` fields will only be prefilled if they are part of your [security scheme](https://swagger.io/docs/specification/authentication/). Creating a standard header parameter named `Authorization` is not sufficient to enable this feature. To know if a field will be prefilled, navigate to your existing docs and check if the field is in either the `Authorization` or `Server` section.</Note>
</ParamField>


50 changes: 50 additions & 0 deletions integrations/user-auth/shared-session.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: 'Shared Session Auth'
description: 'Seamlessly share user sessions between your dashboard and your docs'
---

This method utilizes the session authentication info already stored in your user’s browser to create a seamless documentation experience.

## Implementation

<Steps>
<Step title="Create your Info API">
Create an API endpoint that uses session authentication to identify users, and responds with a JSON payload following the [UserInfo](./sending-data) format.

If the API domain does not *exactly match* the docs domain:
- Add the docs domain to your API's `Access-Control-Allow-Origin` header (must not be `*`)
- Ensure your API’s `Access-Control-Allow-Credentials` header is `true`
<Warning>
These CORS options only need to be enabled on the *single endpoint* responsible for returning user information. We do not recommend enabling these options on all dashboard endpoints.
</Warning>
</Step>
<Step title="Configure your User Auth settings">
Go to your [Mintlify dashboard settings](https://dashboard.mintlify.com/settings/integrations) and add the API URL and your Login URL to your User Auth settings.
</Step>
</Steps>

## Examples
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the examples should also go in the "choosing" page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like it makes sense to have the examples here for when people actually need to implement stuff, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense


### Dashboard at subdomain, docs at subdomain

I have a dashboard at `dash.foo.com`, which uses cookie-based session authentication. My dashboard API routes are hosted at `dash.foo.com/api`. I want to set up authentication for my docs hosted at `docs.foo.com`.

To set up authentication with Mintlify, I create another dashboard endpoint `dash.foo.com/api/docs/user-info` which identifies the user using session auth, and responds with their custom data according to Mintlify’s specification. I then add `https://docs.foo.com` to the `Access-Control-Allow-Origin` allow-list **for this route only**, and ensure my `Access-Control-Allow-Credentials` configuration is set to `true` **for this route only**.

I then go to the Mintlify dashboard settings and enter `https://dash.foo.com/api/docs/user-info` for the API URL field.

### Dashboard at subdomain, docs at root

I have a dashboard at `dash.foo.com`, which uses cookie-based session authentication. My dashboard API routes are hosted at `dash.foo.com/api`. I want to set up authentication for my docs hosted at `foo.com/docs`.

To set up authentication with Mintlify, I create another dashboard endpoint `dash.foo.com/api/docs/user-info` which identifies the user using session auth, and responds with their custom data according to Mintlify’s specification. I then add `https://foo.com` to the `Access-Control-Allow-Origin` allow-list **for this route only**, and ensure my `Access-Control-Allow-Credentials` configuration is set to `true` **for this route only**.

I then go to the Mintlify dashboard settings and enter `https://dash.foo.com/api/docs/user-info` for the API URL field.

### Dashboard at root, docs at root

I have a dashboard at `foo.com/dashboard`, which uses cookie-based session authentication. My dashboard API routes are hosted at `foo.com/api`. I want to set up authentication for my docs hosted at `foo.com/docs`.

To set up authentication with Mintlify, I create another dashboard endpoint `foo.com/api/docs/user-info` which identifies the user using session auth, and responds with their custom data according to Mintlify’s specification.

I then go to the Mintlify dashboard settings and enter `https://foo.com/api/docs/user-info` for the API URL field.
15 changes: 15 additions & 0 deletions mint.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@
"group": "SDKs",
"pages": ["integrations/sdks/speakeasy", "integrations/sdks/stainless"]
},
{
"group": "User Auth",
"pages": [
"integrations/user-auth/overview",
{
"group": "Authenticating",
"pages": [
"integrations/user-auth/choosing-an-auth-method",
"integrations/user-auth/shared-session",
"integrations/user-auth/jwt"
]
},
"integrations/user-auth/sending-data"
]
},
{
"group": "Components",
"pages": [
Expand Down