Skip to content

Commit 1f9bb23

Browse files
authored
(api definitions) Document OpenAPI OAuth and clarify parameters (#1278)
1 parent 3992207 commit 1f9bb23

File tree

6 files changed

+107
-63
lines changed

6 files changed

+107
-63
lines changed

fern/products/api-def/openapi-pages/auth.mdx

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: Authentication
3-
subtitle: Model auth schemes such as bearer, basic, and api key.
3+
description: Model auth schemes such as bearer, basic, api key, and OAuth.
4+
max-toc-depth: 2
45
---
56

67
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.
@@ -181,31 +182,67 @@ client = new Client({
181182
})
182183
```
183184

184-
## Multiple security schemes
185+
## OAuth client credentials
186+
187+
<Markdown src="/snippets/pro-plan.mdx" />
188+
189+
Configure OAuth 2.0 client credentials in `generators.yml` rather than in the API specification:
190+
191+
```yaml title="generators.yml" maxLines=10
192+
auth-schemes:
193+
OAuth:
194+
scheme: oauth
195+
type: client-credentials
196+
client-id-env: "OAUTH_CLIENT_ID"
197+
client-secret-env: "OAUTH_CLIENT_SECRET"
198+
get-token:
199+
endpoint: "POST /oauth/token"
200+
request-properties:
201+
client-id: "client_id"
202+
client-secret: "client_secret"
203+
response-properties:
204+
access-token: "access_token"
205+
expires-in: "expires_in"
206+
refresh-token: "refresh_token"
207+
refresh-token:
208+
endpoint: "POST /oauth/refresh"
209+
request-properties:
210+
refresh-token: "refresh_token"
211+
response-properties:
212+
access-token: "access_token"
213+
expires-in: "expires_in"
214+
api:
215+
auth: OAuth
216+
```
185217

186-
If you would like to define multiple security schemes, simply
187-
list them under `components.securitySchemes`. For example, if you wanted to support
188-
`basic` and `apiKey` security schemes, see the example below:
218+
<Info title="Endpoint configuration and token refresh">
219+
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.
220+
</Info>
189221

190-
```yaml title="openapi.yml" {3,6}
191-
components:
192-
securitySchemes:
193-
BearerAuth:
194-
type: http
195-
scheme: bearer
196-
ApiKey:
197-
type: apiKey
198-
in: header
199-
name: X_API_KEY
222+
The generated SDK would look like:
223+
224+
```ts index.ts
225+
226+
// Uses process.env.OAUTH_CLIENT_ID and process.env.OAUTH_CLIENT_SECRET
227+
let client = new Client();
228+
229+
// Or provide credentials explicitly
230+
client = new Client({
231+
clientId: "your_client_id",
232+
clientSecret: "your_client_secret"
233+
})
234+
235+
// All token management happens automatically
236+
await client.users.list();
200237
```
201238

202239
## Override security scheme
203240

204-
You can use `generators.yml` to define custom authentication schemes that will take precedence when generating SDKs.
241+
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.
205242

206243
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.
207244

208-
```yml title="generators.yml" {1-6, 8}
245+
```yml title="generators.yml"
209246
auth-schemes: # Define custom auth scheme
210247
Bearer:
211248
scheme: bearer
@@ -219,16 +256,16 @@ api:
219256
### Auth scheme reference
220257

221258
<AccordionGroup>
222-
<Accordion title="Header authentication">
259+
<Accordion title="Header">
223260
<Markdown src="/products/sdks/snippets/header-auth-params.mdx" />
224261
</Accordion>
225-
<Accordion title="Basic authentication">
262+
<Accordion title="Basic">
226263
<Markdown src="/products/sdks/snippets/basic-auth-params.mdx" />
227264
</Accordion>
228-
<Accordion title="Bearer token authentication">
265+
<Accordion title="Bearer token">
229266
<Markdown src="/products/sdks/snippets/bearer-auth-params.mdx" />
230267
</Accordion>
231-
<Accordion title="OAuth authentication">
268+
<Accordion title="OAuth client credentials">
232269
<Markdown src="/products/sdks/snippets/oauth-params.mdx" />
233270

234271
#### get-token

fern/products/sdks/capabilities.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ layout: overview
9393

9494
</Card>
9595

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

9999
<p className="text-(color:--grayscale-a11) font-bold mt-2 flex items-center gap-1">

fern/products/sdks/reference/generators-yml-reference.mdx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,13 @@ groups:
5757
5858
## `auth-schemes`
5959

60-
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.
60+
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.
6161

62-
Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings).
62+
Choose from custom headers (API keys), HTTP Basic, Bearer token, or OAuth 2.0 authentication.
63+
64+
<Info>
65+
Alternatively, you can [define authentication for individual SDKs](#override-api-authentication-settings).
66+
</Info>
6367

6468
```yaml title="generators.yml" maxLines=10
6569
auth-schemes:
@@ -95,7 +99,7 @@ auth-schemes:
9599
<Accordion title="Bearer token">
96100
<Markdown src="/products/sdks/snippets/bearer-auth-params.mdx" />
97101
</Accordion>
98-
<Accordion title="OAuth">
102+
<Accordion title="OAuth client credentials">
99103
<Markdown src="/products/sdks/snippets/oauth-params.mdx" />
100104

101105
#### `get-token`
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
Configuration for the token acquisition endpoint.
1+
Specifies the endpoint that exchanges client credentials for an access token. This endpoint is called automatically when the SDK client is initialized.
22

3-
```yaml
3+
```yaml title="generators.yml"
44
get-token:
55
endpoint: "auth.get_token"
66
request-properties:
@@ -12,29 +12,29 @@ get-token:
1212
```
1313
1414
<ParamField path="endpoint" type="string" required={true}>
15-
The endpoint to get the access token, such as `'auth.get_token'`.
15+
The endpoint that issues access tokens, such as `'auth.get_token'`.
1616
</ParamField>
1717
<ParamField path="request-properties" type="object" required={false}>
18-
Customizes the property names used in the token request.
18+
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`).
1919
</ParamField>
20-
<ParamField path="client-id" type="string" required={false}>
21-
The property name for the client ID in the request.
20+
<ParamField path="request-properties.client-id" type="string" required={false}>
21+
The request field name for the client ID in your API (e.g., `"clientId"`, `"client_id"`).
2222
</ParamField>
23-
<ParamField path="client-secret" type="string" required={false}>
24-
The property name for the client secret in the request.
23+
<ParamField path="request-properties.client-secret" type="string" required={false}>
24+
The request field name for the client secret in your API (e.g., `"clientSecret"`, `"client_secret"`).
2525
</ParamField>
26-
<ParamField path="scopes" type="string" required={false}>
27-
The property name for the scopes in the request.
26+
<ParamField path="request-properties.scopes" type="string" required={false}>
27+
The request field name for scopes in your API (e.g., `"scope"`, `"scopes"`).
2828
</ParamField>
2929
<ParamField path="response-properties" type="object" required={false}>
30-
Maps custom property names in your OAuth token response (e.g., if your API returns `accessToken` instead of `access_token`).
30+
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`).
3131
</ParamField>
32-
<ParamField path="access-token" type="string" required={false}>
33-
The property name for the access token in the response.
32+
<ParamField path="response-properties.access-token" type="string" required={false}>
33+
The response field name for the access token in your API (e.g., `"accessToken"`, `"access_token"`).
3434
</ParamField>
35-
<ParamField path="expires-in" type="string" required={false}>
36-
The property name for the expires in property in the response.
35+
<ParamField path="response-properties.expires-in" type="string" required={false}>
36+
The response field name for token expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`). When present, the SDK automatically refreshes tokens before expiration.
3737
</ParamField>
3838
<ParamField path="refresh-token" type="string" required={false}>
39-
The property name for the refresh token in the response.
39+
The response field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`). Required if using the `refresh-token` flow.
4040
</ParamField>

fern/products/sdks/snippets/oauth-params.mdx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
Configure OAuth 2.0 client credentials authentication.
1+
<Note>
2+
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).
3+
</Note>
24

3-
```yaml
5+
Configure OAuth 2.0 client credentials authentication. Optionally configure a `refresh-token` endpoint for token renewal without re-authentication.
6+
7+
```yaml title="generators.yml" maxLines=10
48
auth-schemes:
59
my-oauth: # User-defined scheme name
610
scheme: oauth
@@ -31,15 +35,14 @@ auth-schemes:
3135
expires-in: "expires_in"
3236
refresh-token: "refresh_token"
3337
```
34-
3538
<ParamField path="scheme" type="'oauth'" required={true}>
3639
Must be set to `"oauth"` for OAuth authentication schemes.
3740
</ParamField>
38-
<ParamField path="type" type="literal<'client-credentials'>" required={true}>
39-
The OAuth flow type. Currently only `"client-credentials"` is supported.
41+
<ParamField path="type" type="'client-credentials'" required={true}>
42+
The OAuth 2.0 grant type. Currently only `"client-credentials"` is supported.
4043
</ParamField>
41-
<ParamField path="scopes" type="list<string>" required={false}>
42-
List of OAuth scopes to request during authentication.
44+
<ParamField path="scopes" type="list of strings" required={false}>
45+
OAuth scopes to request when obtaining access tokens (e.g., `"read:users"`, `"write:orders"`).
4346
</ParamField>
4447
<ParamField path="client-id-env" type="string" required={false}>
4548
Environment variable name containing the OAuth client ID. When specified, the generated SDK will automatically scan for this environment variable at initialization.
@@ -48,8 +51,8 @@ auth-schemes:
4851
Environment variable name containing the OAuth client secret. When specified, the generated SDK will automatically scan for this environment variable at initialization.
4952
</ParamField>
5053
<ParamField path="token-prefix" type="string" default="Bearer">
51-
Sets the token header value prefix.
54+
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.
5255
</ParamField>
5356
<ParamField path="token-header" type="string" default="Authorization">
54-
Sets the token header key name.
57+
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"`).
5558
</ParamField>
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
Configuration for the token refresh endpoint.
1+
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.
22

3-
```yaml
3+
```yaml title="generators.yml"
44
refresh-token:
55
endpoint: "auth.refresh_token"
66
request-properties:
@@ -11,23 +11,23 @@ refresh-token:
1111
```
1212
1313
<ParamField path="endpoint" type="string" required={true}>
14-
The endpoint to refresh the access token, such as `'auth.refresh_token'`.
14+
The endpoint that refreshes access tokens (e.g., `"POST /oauth/refresh"` or `"auth.refreshToken"`).
1515
</ParamField>
1616
<ParamField path="request-properties" type="object" required={false}>
17-
Maps custom property names in your refresh token request.
17+
Maps OAuth parameter names to your API's request field names for the refresh flow.
1818
</ParamField>
19-
<ParamField path="refresh-token" type="string" required={true}>
20-
The property name for the refresh token in the request.
19+
<ParamField path="request-properties.refresh-token" type="string" required={true}>
20+
The request field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`).
2121
</ParamField>
2222
<ParamField path="response-properties" type="object" required={false}>
23-
Maps custom property names in your refresh token response.
23+
Maps your API's refresh response field names to OAuth standard names.
2424
</ParamField>
25-
<ParamField path="access-token" type="string" required={false}>
26-
The property name for the access token in the response.
25+
<ParamField path="response-properties.access-token" type="string" required={false}>
26+
The response field name for the new access token (e.g., `"accessToken"`, `"access_token"`).
2727
</ParamField>
28-
<ParamField path="expires-in" type="string" required={false}>
29-
The property name for the expires in property in the response.
28+
<ParamField path="response-properties.expires-in" type="string" required={false}>
29+
The response field name for the new token's expiration time in seconds (e.g., `"expiresIn"`, `"expires_in"`).
3030
</ParamField>
31-
<ParamField path="refresh-token" type="string" required={false}>
32-
The property name for the refresh token in the response.
31+
<ParamField path="response-properties.refresh-token" type="string" required={false}>
32+
The response field name if your API issues a new refresh token with each refresh (token rotation).
3333
</ParamField>

0 commit comments

Comments
 (0)