Customize Security & Authentication

Authentication Overview

Speakeasy-created SDKs have authentication configured automatically based on the securitySchemes defined in your OpenAPI specification.

For APIs authenticated by long-lived tokens (API keys), these should work out of the box. For APIs authenticated by short-lived tokens (OAuth), extra configuration is required to minimize your users' effort.

Support for securitySchemes

In your OpenAPI specification, define the securitySchemes object according to your API's authentication mechanism.

Authentication MechanismLanguage Support
HTTP Basic Authentication✅ All Languages
API Key [header]✅ All Languages
API Key [cookie]✅ All Languages
API Key [query param]✅ All Languages
API Key [Bearer]✅ All Languages
OAuth Implicit Flow✅ All Languages
OAuth Refresh Token Flow🏗️ Partial
OAuth Client Credentials Flow🏗️ Partial
mTLS🏗️ Partial

HTTP Basic Authentication

Supported in all languages. Defining basic authentication will prompt users for a username and password when instantiating the SDK.


paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks.
description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
tags:
- drinks
components:
securitySchemes:
auth:
type: http
scheme: basic
security:
- auth: []


const s = sdk.SDK(
(security = shared.Security(
(username = "..MY_USER.."),
(password = "..MY_PASSWORD..")
))
);
await s.list_drinks();

API Key Authentication

Supported in all languages. Defining api_key authentication will prompt users for a key when instantiating the SDK. How the key is passed to your API will be abstracted from your users. Speakeasy supports passing the key as a header, cookie, query param, or bearer token.


paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks.
description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
tags:
- drinks
components:
securitySchemes:
api_key:
type: apiKey
name: api_key
in: header
security:
- api_key: []


const s = new SDK({ security: { apiKey: "..MY_KEY.." } });
await s.drinks.listDrinks();

OAuth

Speakeasy supports OAuth authentication in the most popular languages. Support for additional languages is coming soon.

TypescriptPythonGoC#JavaPHPSwiftRuby
🏗️🏗️🏗️🏗️🏗️

Enabling OAuth security in your SDK currently requires additional configuration outside of your OpenAPI spec.

Step 1: Define OAuth Security in Your OpenAPI Spec

Our current OAuth support does not use the OpenAPI description, but native support is on the way, so don't skip this step!


/oauth2/token:
get:
operationId: auth
security:
- []
responses:
200:
description: OK
content:
application/json:
schema:
type: object
properties:
access_token: string
required:
- access_token
/example:
get:
operationId: example
responses:
200:
description: OK
components:
securitySchemes:
auth:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://speakeasy.bar/oauth2/token/
scopes: {}
security:
- auth: []

Step 2: Add Your Callback Function to Your SDKs

To implement OAuth authentication, you need to write a callback function to handle your OAuth token exchange. To do so, add a file to your SDKs src folder called oauth.ts (or oauth.py for Python, oauth.go for Go, and so on):


import axios from "axios";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function withAuthorization(clientID: string, clientSecret: string) {
return async (): Promise<{ oauth2: string }> => {
const tokenEndpoint = "https://speakeasy.bar/oauth2/token/";
const data = {
grant_type: "client_credentials",
client_id: clientID,
client_secret: clientSecret,
};
try {
const response = await axios.post(tokenEndpoint, data);
return { oauth2: response.data.access_token };
} catch (error) {
throw new Error("Failed to obtain OAuth token");
}
};
}

Step 3: Pass Callback Function in SDK Instantiation

Edit your Readme to instruct users to pass in the callback function when instantiating the SDK. We recommend adding a custom OAuth section that shows users how to instantiate their SDK via the callback function:


const sdk = new SDK({
security: withAuthorization("client_id", "client_secret"),
});
await s.listDrinks();

Scoping Authentication

Global

Global security allows your users to configure the SDK once and reuse the security configuration for all subsequent calls.

To use global security, define your security configuration in the security block at the root of the SDK.


paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks.
description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
tags:
- drinks
components:
securitySchemes:
api_key:
type: apiKey
name: api_key
in: header
security: # Here
- api_key: []

In the resulting SDK, the user will be able to define the security configuration in the SDK's instantiation. It will then be automatically applied to all subsequent method calls without needing to be passed in as an argument:


const s = new SDK({ security: { apiKey: "..MY_KEY.." } });
await s.drinks.listDrinks();

Per-Operation

Info Icon

NOTE

Security Hoisting: In cases where global security is not defined, we will automatically hoist the most commonly occurring operation-level security to be considered global. This will simplify the usage of your SDK.

Operation-specific security configuration allows for overriding one endpoint's authentication configuration.

This is most often used for operations that do not require authentication, or when an operation is part of an authentication flow (for example, invoked to retrieve a shorter-lived access token).

To use operation-specific security, define security within an operation's scope.


paths:
/drinks:
get:
operationId: listDrinks
summary: Get a list of drinks.
description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
security:
- apiKey: []
tags:
- drinks
components:
securitySchemes:
api_key:
type: apiKey
name: api_key
in: header

In the SDK, the user will be able to pass in a specific security configuration as an argument to the method call:


const sdk = new SDK();
const operationSecurity: ListDrinksSecurity = {
apiKey: "",
};
sdk.drinks.listDrinks(operationSecurity).then((res: ListDrinksResponse) => {
if (res.statusCode == 200) {
// handle response
}
});

Flattened Global Security

The flattened global security feature only works if you have a single global security scheme. We provide an option for flattening down the security parameters to pass. This is a small change, but it can be helpful for APIs with a straightforward security configuration. To enable flattened global security, set the flattenGlobalSecurity field to true in your SDK repo gen.yaml:

gen.yaml

configVersion: 1.0.0
generation:
comments:
disableComments: false
omitDescriptionIfSummaryPresent: false
baseServerURL: ""
sdkClassName: speakeasy_bar
singleTagPerOp: false
tagNamespacingDisabled: false
python:
version: 0.0.1
author: speakeasy
clientServerStatusCodesAsErrors: true
description: Python Client SDK Generated by Speakeasy
flattenGlobalSecurity: true
maxMethodParams: 04
packageName: speakeasy-bar

Here's a demonstration of what code in such a situation might look like without and then with flattening:


// Without global security flattening enabled
const s = new SDK({ security: { apiKey: "..MY_KEY.." } });
await s.drinks.listDrinks();
// With global security flattening enabled
const s = new SDK({ apiKey: "..MY_KEY.." });
await s.drinks.listDrinsk();