Skip to navigation

Authentication

View as Markdown

Fern Definition isn’t recommended for new customers and Fern isn’t accepting feature requests for this format. It remains supported for existing users.

Configuring authentication schemes happens in the api.yml file. All Fern-generated SDKs support both direct configuration and environment variables for authentication credentials.

fern/
├─ fern.config.json # root-level configuration
├─ generators.yml # generators you're using
└─ definition/
├─ api.yml # API-level configuration
└─ imdb.yml # endpoints, types, and errors

To add an authentication scheme, specify the authentication method under the auth-schemes section.

api.yml
auth-schemes:
AuthScheme:
...

Every scheme accepts docs, which appears in the API Reference’s Authorization section, and playground-docs, which appears only beneath the scheme’s input in the API Explorer:

api.yml
auth-schemes:
Bearer:
scheme: bearer
docs: Use your account API token.
playground-docs: Generate a short-lived token in the [dashboard](https://plantstore.example.com/tokens).

To apply an authentication scheme across all endpoints, reference the auth-scheme within the auth section of your api.yml file.

api.yml
auth: AuthScheme
auth-schemes:
AuthScheme:
...

Bearer authentication

Start by defining a Bearer authentication scheme in api.yml:

api.yml
auth: Bearer
auth-schemes:
Bearer:
scheme: bearer

This will generate an SDK where the user would have to provide a mandatory argument called token.

index.ts
const client = new Client({
token: "ey34..."
})

If you want to control variable naming and the environment variable to scan, use the configuration below:

api.yml
auth: Bearer
auth-schemes:
Bearer:
scheme: bearer
token:
name: apiKey
env: PLANTSTORE_API_KEY

The generated SDK would look like:

index.ts
// Uses process.env.PLANTSTORE_API_KEY
let client = new Client();
// token has been renamed to apiKey
client = new Client({
apiKey: "ey34..."
})

Basic authentication

Start by defining a Basic authentication scheme in api.yml:

api.yml
auth: Basic
auth-schemes:
Basic:
scheme: basic

This will generate an SDK where the user would have to provide a mandatory arguments called username and password.

index.ts
const client = new Client({
username: "joeschmoe"
password: "ey34..."
})

If you want to control variable naming and environment variables to scan, use the configuration below:

api.yml
auth: Basic
auth-schemes:
Basic:
scheme: basic
username:
name: clientId
env: PLANTSTORE_CLIENT_ID
password:
name: clientSecret
env: PLANTSTORE_CLIENT_SECRET

The generated SDK would look like:

index.ts
// Uses process.env.PLANTSTORE_CLIENT_ID and process.env.PLANTSTORE_CLIENT_SECRET
let client = new Client();
// parameters have been renamed
client = new Client({
clientId: "joeschmoe",
clientSecret: "ey34..."
})

Custom header (e.g. API key)

You can also create your own authentication scheme with customized headers.

api.yml
auth: ApiKeyAuthScheme
auth-schemes:
ApiKeyAuthScheme:
header: X-API-Key
type: string

This will generate an SDK where the user would have to provide a mandatory argument called apiKey.

index.ts
const client = new Client({
xApiKey: "ey34..."
})

If you want to control variable naming and environment variables to scan, use the configuration below:

api.yml
auth: ApiKeyAuthScheme
auth-schemes:
ApiKeyAuthScheme:
header: X-API-Key
type: string
name: apiKey
env: PLANTSTORE_API_KEY

The generated SDK would look like:

index.ts
// Uses process.env.PLANTSTORE_API_KEY
let client = new Client();
// parameters have been renamed
client = new Client({
apiKey: "ey34..."
})

OAuth client credentials

If your API uses OAuth, you can specify an oauth scheme in api.yml and define a token retrieval endpoint in a separate auth.yml file (example).

api.yml
name: api
imports:
auth: auth.yml
auth: OAuthScheme
auth-schemes:
OAuthScheme:
scheme: oauth
type: client-credentials
client-id-env: YOUR_CLIENT_ID
client-secret-env: YOUR_CLIENT_SECRET
get-token:
endpoint: auth.getTokenWithClientCredentials
request-properties:
client-id: $request.client_id # Format: parameter-name: $request.property_name
client-secret: $request.client_secret # Format: parameter-name: $request.property_name
response-properties:
access-token: $response.access_token # Format: parameter-name: $response.property_name
expires-in: $response.expires_in # Format: parameter-name: $response.property_name

The request-properties and response-properties map OAuth standard parameters to your actual endpoint’s request and response field names defined in auth.yml.

If the expires-in property is set, the generated OAuth token provider will automatically refresh the token when it expires. Otherwise, it’s assumed that the access token is valid indefinitely.

The corresponding auth.yml file (example) defines the token endpoint:

auth.yml
types:
TokenResponse:
docs: |
An OAuth token response.
properties:
access_token: string
expires_in: integer
refresh_token: optional<string>
service:
auth: false
base-path: /
endpoints:
getTokenWithClientCredentials:
path: /token
method: POST
request:
name: GetTokenRequest
body:
properties:
client_id: string
client_secret: string
audience: literal<"https://api.example.com">
grant_type: literal<"client_credentials">
scope: optional<string>
response: TokenResponse
If your OAuth server is hosted at a different URL than your main API, you can use multi-URL environments to specify separate base URLs for authentication and API calls.

With this, all of the OAuth logic happens automatically in the generated SDKs. As long as you configure these settings, your client will automatically retrieve an access token and refresh it as needed.

When using the docs playground, token-header and token-prefix can optionally be set to customize the header key name and header value prefix, to match the expected format of the API auth scheme.

For example, the following would produce a header Fern-Authorization: Fern-Bearer <token>:

api.yml
auth-schemes:
OAuthScheme:
scheme: oauth
type: client-credentials
token-header: Fern-Authorization
token-prefix: Fern-Bearer
get-token:
...