Skip to content
Open
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
69 changes: 62 additions & 7 deletions fern/products/api-def/openapi-pages/auth.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Authentication
subtitle: Model auth schemes such as bearer, basic, and api key.
description: Model auth schemes such as bearer, basic, api key, and OAuth.
max-toc-depth: 2
---

Configuring authentication schemes happens in the `components.securitySchemes` section of OpenAPI. All Fern-generated SDKs support both direct configuration and environment variables for authentication credentials.
Expand Down Expand Up @@ -181,6 +182,60 @@ client = new Client({
})
```

## OAuth client credentials

<Markdown src="/snippets/pro-plan.mdx" />

Configure OAuth 2.0 client credentials in `generators.yml` rather than in the API specification:

```yaml title="generators.yml" maxLines=10
auth-schemes:
OAuth:
scheme: oauth
type: client-credentials
client-id-env: "OAUTH_CLIENT_ID"
client-secret-env: "OAUTH_CLIENT_SECRET"
get-token:
endpoint: "POST /oauth/token"
request-properties:
client-id: "client_id"
client-secret: "client_secret"
response-properties:
access-token: "access_token"
expires-in: "expires_in"
refresh-token: "refresh_token"
refresh-token:
endpoint: "POST /oauth/refresh"
request-properties:
refresh-token: "refresh_token"
response-properties:
access-token: "access_token"
expires-in: "expires_in"
api:
auth: OAuth
```

<Info title="Endpoint configuration and token refresh">
The `endpoint` values (e.g., `"POST /oauth/token"`) reference paths defined in your OpenAPI specification. When `expires-in` is returned, the SDK will automatically refresh tokens before they expire. For more details on OAuth configuration options, see the [Auth scheme reference](#oauth-authentication) below.
</Info>

The generated SDK would look like:

```ts index.ts

// Uses process.env.OAUTH_CLIENT_ID and process.env.OAUTH_CLIENT_SECRET
let client = new Client();

// Or provide credentials explicitly
client = new Client({
clientId: "your_client_id",
clientSecret: "your_client_secret"
})

// All token management happens automatically
await client.users.list();
```

## Multiple security schemes

If you would like to define multiple security schemes, simply
Expand All @@ -201,11 +256,11 @@ components:

## Override security scheme

You can use `generators.yml` to define custom authentication schemes that will take precedence when generating SDKs.
You can use `generators.yml` to define custom authentication schemes that will take precedence when generating SDKs. This is also how OAuth authentication is configured for OpenAPI specs.

First, use the `auth-schemes` property to define your authentication scheme. Then, specify your auth scheme in the `api` property to override your OpenAPI spec.

```yml title="generators.yml" {1-6, 8}
```yml title="generators.yml"
auth-schemes: # Define custom auth scheme
Bearer:
scheme: bearer
Expand All @@ -219,16 +274,16 @@ api:
### Auth scheme reference

<AccordionGroup>
<Accordion title="Header authentication">
<Accordion title="Header">
<Markdown src="/products/sdks/snippets/header-auth-params.mdx" />
</Accordion>
<Accordion title="Basic authentication">
<Accordion title="Basic">
<Markdown src="/products/sdks/snippets/basic-auth-params.mdx" />
</Accordion>
<Accordion title="Bearer token authentication">
<Accordion title="Bearer token">
<Markdown src="/products/sdks/snippets/bearer-auth-params.mdx" />
</Accordion>
<Accordion title="OAuth authentication">
<Accordion title="OAuth client credentials">
<Markdown src="/products/sdks/snippets/oauth-params.mdx" />

#### get-token
Expand Down
2 changes: 1 addition & 1 deletion fern/products/sdks/capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ layout: overview

</Card>

<Card title="OAuth Token Refresh" icon="fa-duotone fa-arrows-rotate" href="/api-definitions/ferndef/authentication#oauth-client-credentials">
<Card title="OAuth Token Refresh" icon="fa-duotone fa-arrows-rotate" href="/sdks/reference/generators-yml#oauth">
Fern supports OAuth as a first class citizen

<p className="text-(color:--grayscale-a11) font-bold mt-2 flex items-center gap-1">
Expand Down
10 changes: 7 additions & 3 deletions fern/products/sdks/reference/generators-yml-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,13 @@ groups:

## `auth-schemes`

Define authentication methods for your API that your endpoints can reference. Choose from custom headers (API keys), HTTP Basic, Bearer token, or OAuth 2.0 authentication.
Define authentication methods for your API that your endpoints can reference. Authentication schemes defined in `generators.yml` take precedence over authentication schemes defined in your spec.

Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings).
Choose from custom headers (API keys), HTTP Basic, Bearer token, or OAuth 2.0 authentication.

<Info>
Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings).
</Info>

```yaml title="generators.yml" maxLines=10
auth-schemes:
Expand Down Expand Up @@ -95,7 +99,7 @@ auth-schemes:
<Accordion title="Bearer token">
<Markdown src="/products/sdks/snippets/bearer-auth-params.mdx" />
</Accordion>
<Accordion title="OAuth">
<Accordion title="OAuth client credentials">
<Markdown src="/products/sdks/snippets/oauth-params.mdx" />

#### `get-token`
Expand Down
32 changes: 16 additions & 16 deletions fern/products/sdks/snippets/oauth-get-token.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Configuration for the token acquisition endpoint.
Specifies the endpoint that exchanges client credentials for an access token. This endpoint is called automatically when the SDK client is initialized.

```yaml
```yaml title="generators.yml"
get-token:
endpoint: "auth.get_token"
request-properties:
Expand All @@ -12,29 +12,29 @@ get-token:
```

<ParamField path="endpoint" type="string" required={true}>
The endpoint to get the access token, such as `'auth.get_token'`.
The endpoint that issues access tokens, such as `'auth.get_token'`.
</ParamField>
<ParamField path="request-properties" type="object" required={false}>
Customizes the property names used in the token request.
Maps OAuth parameter names to your API's request field names. Use this when your token endpoint expects different field names than the OAuth standard (e.g., your API uses `clientId` instead of `client_id`).
</ParamField>
<ParamField path="client-id" type="string" required={false}>
The property name for the client ID in the request.
<ParamField path="request-properties.client-id" type="string" required={false}>
The request field name for the client ID in your API (e.g., `"clientId"`, `"client_id"`).
</ParamField>
<ParamField path="client-secret" type="string" required={false}>
The property name for the client secret in the request.
<ParamField path="request-properties.client-secret" type="string" required={false}>
The request field name for the client secret in your API (e.g., `"clientSecret"`, `"client_secret"`).
</ParamField>
<ParamField path="scopes" type="string" required={false}>
The property name for the scopes in the request.
<ParamField path="request-properties.scopes" type="string" required={false}>
The request field name for scopes in your API (e.g., `"scope"`, `"scopes"`).
</ParamField>
<ParamField path="response-properties" type="object" required={false}>
Maps custom property names in your OAuth token response (e.g., if your API returns `accessToken` instead of `access_token`).
Maps your API's response field names to OAuth standard names. Use this when your API returns tokens with different field names (e.g., `accessToken` instead of `access_token`).
</ParamField>
<ParamField path="access-token" type="string" required={false}>
The property name for the access token in the response.
<ParamField path="response-properties.access-token" type="string" required={false}>
The response field name for the access token in your API (e.g., `"accessToken"`, `"access_token"`).
</ParamField>
<ParamField path="expires-in" type="string" required={false}>
The property name for the expires in property in the response.
<ParamField path="response-properties.expires-in" type="string" required={false}>
The response field name for token expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`). When present, the SDK automatically refreshes tokens before expiration.
</ParamField>
<ParamField path="refresh-token" type="string" required={false}>
The property name for the refresh token in the response.
The response field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`). Required if using the `refresh-token` flow.
</ParamField>
21 changes: 12 additions & 9 deletions fern/products/sdks/snippets/oauth-params.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
Configure OAuth 2.0 client credentials authentication.
<Note>
For Fern Definition, you can configure OAuth authentication either in `generators.yml` or [directly in your `api.yml` file](/api-definitions/ferndef/authentication#oauth-client-credentials). For OpenAPI, [OAuth must be configured in `generators.yml`](/api-definitions/openapi/authentication#oauth-client-credentials).
</Note>

```yaml
Configure OAuth 2.0 client credentials authentication. Optionally configure a `refresh-token` endpoint for token renewal without re-authentication.

```yaml title="generators.yml" maxLines=10
auth-schemes:
my-oauth: # User-defined scheme name
scheme: oauth
Expand Down Expand Up @@ -31,15 +35,14 @@ auth-schemes:
expires-in: "expires_in"
refresh-token: "refresh_token"
```

<ParamField path="scheme" type="'oauth'" required={true}>
Must be set to `"oauth"` for OAuth authentication schemes.
</ParamField>
<ParamField path="type" type="literal<'client-credentials'>" required={true}>
The OAuth flow type. Currently only `"client-credentials"` is supported.
<ParamField path="type" type="'client-credentials'" required={true}>
The OAuth 2.0 grant type. Currently only `"client-credentials"` is supported.
</ParamField>
<ParamField path="scopes" type="list<string>" required={false}>
List of OAuth scopes to request during authentication.
<ParamField path="scopes" type="list of strings" required={false}>
OAuth scopes to request when obtaining access tokens (e.g., `"read:users"`, `"write:orders"`).
</ParamField>
<ParamField path="client-id-env" type="string" required={false}>
Environment variable name containing the OAuth client ID. When specified, the generated SDK will automatically scan for this environment variable at initialization.
Expand All @@ -48,8 +51,8 @@ auth-schemes:
Environment variable name containing the OAuth client secret. When specified, the generated SDK will automatically scan for this environment variable at initialization.
</ParamField>
<ParamField path="token-prefix" type="string" default="Bearer">
Sets the token header value prefix.
Prefix added to the access token in the Authorization header (e.g., `"Bearer"` results in `"Authorization: Bearer <token>"`). Useful when your API expects a custom format.
</ParamField>
<ParamField path="token-header" type="string" default="Authorization">
Sets the token header key name.
HTTP header name used to send the access token. Defaults to `"Authorization"` but can be customized if your API uses a different header (e.g., `"X-API-Token"`).
</ParamField>
26 changes: 13 additions & 13 deletions fern/products/sdks/snippets/oauth-refresh-token.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Configuration for the token refresh endpoint.
Specifies the endpoint that exchanges a refresh token for a new access token. When configured, the SDK automatically uses this endpoint to renew expired tokens without re-sending credentials. If not configured, the SDK will re-authenticate using `get-token` when tokens expire.

```yaml
```yaml title="generators.yml"
refresh-token:
endpoint: "auth.refresh_token"
request-properties:
Expand All @@ -11,23 +11,23 @@ refresh-token:
```

<ParamField path="endpoint" type="string" required={true}>
The endpoint to refresh the access token, such as `'auth.refresh_token'`.
The endpoint that refreshes access tokens (e.g., `"POST /oauth/refresh"` or `"auth.refreshToken"`).
</ParamField>
<ParamField path="request-properties" type="object" required={false}>
Maps custom property names in your refresh token request.
Maps OAuth parameter names to your API's request field names for the refresh flow.
</ParamField>
<ParamField path="refresh-token" type="string" required={true}>
The property name for the refresh token in the request.
<ParamField path="request-properties.refresh-token" type="string" required={true}>
The request field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`).
</ParamField>
<ParamField path="response-properties" type="object" required={false}>
Maps custom property names in your refresh token response.
Maps your API's refresh response field names to OAuth standard names.
</ParamField>
<ParamField path="access-token" type="string" required={false}>
The property name for the access token in the response.
<ParamField path="response-properties.access-token" type="string" required={false}>
The response field name for the new access token (e.g., `"accessToken"`, `"access_token"`).
</ParamField>
<ParamField path="expires-in" type="string" required={false}>
The property name for the expires in property in the response.
<ParamField path="response-properties.expires-in" type="string" required={false}>
The response field name for the new token's expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`).
</ParamField>
<ParamField path="refresh-token" type="string" required={false}>
The property name for the refresh token in the response.
<ParamField path="response-properties.refresh-token" type="string" required={false}>
The response field name if your API issues a new refresh token with each refresh (token rotation).
</ParamField>