# Apply globally across all endpoints
security:
  - AuthScheme: []
```

All Fern-generated SDKs support both direct configuration and environment variables for authentication credentials. Authentication schemes are also automatically supported in the [API Explorer](/learn/docs/api-references/api-explorer/overview#authentication), including multiple schemes and combinations.

## Bearer security scheme

Define a `bearer` security scheme in your `openapi.yml`:

```yml title="openapi.yml" {3-5}
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
```

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

```ts 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:

```yaml title="openapi.yml" {6-8}
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      x-fern-bearer: 
        name: apiKey
        env: PLANTSTORE_API_KEY
```

The generated SDK would look like:

```ts index.ts

// Uses process.env.PLANTSTORE_API_KEY
let client = new Client(); 

// token has been renamed to apiKey
client = new Client({
  apiKey: "ey34..."
})
```

## Basic security scheme

Define a `basic` security scheme in your `openapi.yml`:

```yaml title="openapi.yml" {3-5}
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
```

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

```ts 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:

```yaml title="openapi.yml" {6-12}
components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      x-fern-basic:
        username:
          name: clientId
          env: PLANTSTORE_CLIENT_ID
        password:
          name: clientSecret
          env: PLANTSTORE_CLIENT_SECRET
```

The generated SDK would look like:

```ts 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..."
})
```

## ApiKey security scheme

Define an `apiKey` security scheme in your `openapi.yml`:

```yml title="openapi.yml" {3-5}
components: 
  securitySchemes: 
    ApiKey: 
      type: apiKey
      in: header
      name: X_API_KEY
```

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

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

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

```yaml title="openapi.yml" {7-10}
components: 
  securitySchemes: 
    ApiKey: 
      type: apiKey
      in: header
      name: X_API_KEY
      x-fern-header:
        name: apiToken
        env: PLANTSTORE_API_KEY
        prefix: "Token " # Optional      
```

<Info>
  The `prefix` option lets you automatically add a prefix to API keys. This is useful when your API expects tokens in a specific format like `"Bearer abc123"` or `"Token abc123"`.
</Info>

The generated SDK would look like:

```ts index.ts

// Uses process.env.PLANTSTORE_API_KEY
let client = new Client(); 

// parameters have been renamed
client = new Client({
  apiToken: "ey34..."
})
```

## OAuth client credentials

<Warning title="Pro and Enterprise feature">
  This feature is available only for the [Pro and Enterprise plans](https://buildwithfern.com/pricing). To get started, reach out to [support@buildwithfern.com](mailto:support@buildwithfern.com).
</Warning>

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](#auth-scheme-reference) 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 authentication schemes

You can configure endpoints to support multiple authentication schemes or combinations of schemes. In the `security` section, multiple security requirement objects (top-level list items) are treated as OR options, while multiple schemes within a single object are combined with AND.

```yaml title="openapi.yml"
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
    basicAuth:
      type: http
      scheme: basic
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
/plant/search/status:
  get:
    summary: Search plants by status
    security:
      - bearerAuth: []           # Option 1: Bearer token only (OR)
      - basicAuth: []            # Option 2: Basic auth AND API key (combined)
        apiKey: []
```

In this example, users can authenticate with either a bearer token OR with both basic auth and an API key together.

<Note>
  When using [OAuth client credentials](#oauth-client-credentials) with multiple authentication schemes, ensure the scheme name in your OpenAPI spec's `security` section matches the name defined in your `generators.yml` auth-schemes configuration.
</Note>

## Override security scheme

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"
auth-schemes:
  bearerAuth:                  # Must match the name used in your OpenAPI security section
    scheme: bearer
    token:
      name: apiKey             # Custom parameter name in the SDK
      env: YOUR_TOKEN_NAME     # Environment variable to auto-scan
api:
  auth: bearerAuth             # Reference the same name from your OpenAPI spec
```

<Warning>
  When overriding a security scheme in `generators.yml`, the name must match the scheme name referenced in your OpenAPI spec's `security` section. For example, if your OpenAPI spec uses `security: - bearerAuth: []`, then use `auth: bearerAuth` in generators.yml.
</Warning>

### Auth scheme reference

<AccordionGroup>
  <Accordion title="Header">
    Configure authentication using custom HTTP headers, such as API keys or tokens.

    ```yaml
    auth-schemes:
      api-key: # User-defined scheme name
        name: "API Key Authentication"
        header: "X-API-Key"
        type: "string"
        prefix: "ApiKey "
        env: "MY_API_KEY" # SDK will auto-scan this environment variable
    ```

    <ParamField path="header" type="string" required={true}>
      The name of the HTTP header to use for authentication.
    </ParamField>

    <ParamField path="name" type="string" required={false}>
      A descriptive name for this authentication scheme.
    </ParamField>

    <ParamField path="type" type="string" default="string">
      The type of the header value.
    </ParamField>

    <ParamField path="prefix" type="string" required={false}>
      A prefix to prepend to the header value (e.g., `"Bearer "` or `"Token "`).
    </ParamField>

    <ParamField path="env" type="string" required={false}>
      Environment variable name containing the authentication value. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>
  </Accordion>

  <Accordion title="Basic">
    Configure HTTP Basic authentication using username and password credentials.

    ```yaml
    auth-schemes:
      basic-auth: # User-defined scheme name
        scheme: basic
        username:
          name: "Username"
          env: "BASIC_AUTH_USERNAME" # SDK will auto-scan this environment variable
        password:
          name: "Password"
          env: "BASIC_AUTH_PASSWORD" # SDK will auto-scan this environment variable
    ```

    <ParamField path="scheme" type="'basic'" required={true}>
      Must be set to `"basic"` for Basic authentication schemes.
    </ParamField>

    <ParamField path="username" type="object" required={false}>
      Configuration for the username credential.
    </ParamField>

    <ParamField path="username.name" type="string" required={false}>
      Custom parameter name for the username in the generated SDK. If not specified, defaults to `"username"`. Use this to provide more descriptive or domain-specific parameter names like `"clientId"`, `"userEmail"`, or `"merchantId"`.
    </ParamField>

    <ParamField path="password" type="object" required={false}>
      Configuration for the password credential.
    </ParamField>

    <ParamField path="password.name" type="string" required={false}>
      Custom parameter name for the password in the generated SDK. If not specified, defaults to `"password"`. Use this to provide more descriptive or domain-specific parameter names like `"clientSecret"`, `"apiKey"`, or `"merchantKey"`.
    </ParamField>

    <ParamField path="username.env, password.env" type="string" required={false}>
      Environment variable name that the SDK will automatically scan for the username or password value. When this environment variable is present, users don't need to explicitly provide the username parameter. Follow naming conventions like `YOUR_APP_USERNAME` or `SERVICE_CLIENT_ID`.
    </ParamField>
  </Accordion>

  <Accordion title="Bearer token">
    Configure Bearer token authentication for API access.

    ```yaml
    auth-schemes:
      bearer-token: # User-defined scheme name
        scheme: bearer
        token:
          name: "Access Token"
          env: "BEARER_TOKEN" # SDK will auto-scan this environment variable
    ```

    <ParamField path="scheme" type="'bearer'" required={true}>
      Must be set to `"bearer"` for Bearer token authentication schemes.
    </ParamField>

    <ParamField path="token" type="object" required={false}>
      Configuration for the bearer token.
    </ParamField>

    <ParamField path="token.name" type="string" required={false}>
      A descriptive name for the token.
    </ParamField>

    <ParamField path="token.env" type="string" required={false}>
      Environment variable name containing the bearer token. When specified, the generated SDK will automatically scan for this environment variable at initialization.
    </ParamField>
  </Accordion>

  <Accordion title="OAuth client credentials">
    <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>

    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
        type: client-credentials
        scopes:
          - "read:users"
          - "write:users"
        client-id-env: "OAUTH_CLIENT_ID" # SDK will auto-scan this environment variable
        client-secret-env: "OAUTH_CLIENT_SECRET" # SDK will auto-scan this environment variable
        token-prefix: "Bearer"
        token-header: "Authorization"
        get-token:
          endpoint: "auth.get_token"
          request-properties:
            client-id: "clientId"
            client-secret: "clientSecret"
            scopes: "scope"
          response-properties:
            access-token: "access_token"
            expires-in: "expires_in"
            refresh-token: "refresh_token"
        refresh-token:
          endpoint: "auth.refresh_token"
          request-properties:
            refresh-token: "refreshToken"
          response-properties:
            access-token: "access_token"
            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="'client-credentials'" required={true}>
      The OAuth 2.0 grant type. Currently only `"client-credentials"` is supported.
    </ParamField>

    <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.
    </ParamField>

    <ParamField path="client-secret-env" type="string" required={false}>
      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">
      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">
      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>

    #### get-token

    Specifies the endpoint that exchanges client credentials for an access token. This endpoint is called automatically when the SDK client is initialized.

    ```yaml title="generators.yml"
    get-token:
      endpoint: "auth.get_token"
      request-properties:
        client-id: "clientId"
        client-secret: "clientSecret"
      response-properties:
        access-token: "access_token"
        expires-in: "expires_in"
    ```

    <ParamField path="endpoint" type="string" required={true}>
      The endpoint that issues access tokens, such as `'auth.get_token'`.
    </ParamField>

    <ParamField path="request-properties" type="object" required={false}>
      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="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="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="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 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="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="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 response field name for the refresh token in your API (e.g., `"refreshToken"`, `"refresh_token"`). Required if using the `refresh-token` flow.
    </ParamField>

    #### refresh-token

    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 title="generators.yml"
    refresh-token:
      endpoint: "auth.refresh_token"
      request-properties:
        refresh-token: "refreshToken"
      response-properties:
        access-token: "access_token"
        expires-in: "expires_in"
    ```

    <ParamField path="endpoint" type="string" required={true}>
      The endpoint that refreshes access tokens (e.g., `"POST /oauth/refresh"` or `"auth.refreshToken"`).
    </ParamField>

    <ParamField path="request-properties" type="object" required={false}>
      Maps OAuth parameter names to your API's request field names for the refresh flow.
    </ParamField>

    <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 your API's refresh response field names to OAuth standard names.
    </ParamField>

    <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="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="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>
  </Accordion>
</AccordionGroup>