Customize Authentication
Authentication Overview
Speakeasy created SDKs have authentication configured automatically based on the securitySchemes
defined in your OpenAPI specification.
For APIs that are authenticated by long-lived tokens (API Key), these should work out of the box. For APIs that are authenticated by short-lived tokens (oAuth), extra configuration is required to minimize any effort by your users.
securitySchemes
Support
In your OpenAPI specification, define the securitySchemes
object in accordance with your APIs authentiation mechanism.
Authentication Mechanism | Language 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. However, we support the key being passed as a header, cookie, query param, or as a 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 with support for additional languages coming soon.
Typescript | Python | Go | C# | Java | PHP | Swift | Ruby |
---|---|---|---|---|---|---|---|
✅ | ✅ | ✅ | 🏗️ | 🏗️ | 🏗️ | 🏗️ | 🏗️ |
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 will 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, etc):
function withAuthorization(clientID: string, clientSecret: string): (args: CallbackArgs) => Promise<[string, Error]> {
return async (args: CallbackArgs): Promise<[string, Error]> => {
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 response.data.access_token;
} catch (error) {
throw new Error('Failed to obtain OAuth token');
}
};
}
Step 3: Pass Callback Function In SDK Instantiation
You'll need to edit your Readme
to instruct users to pass in the callback function when instantiating the SDK. Our recommendation is to add a custom Oauth section which shows users how to instantiate their SDK via the callback function:
const s = new SDK({ securitySource: { callback: withAuthorization("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET") } });
await s.listDrinks();
Scoping Authentication
Global
Global security allows your users to configure the SDK once, and re-use the security configuration for all subsequent aclls
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
NOTE
Security Hoisting: In the case where global security is not defined, we will automatically hoist the most commonly occurring operation level security to be considered global. This will simplify 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 for when the operation is used as part of an authentication flow (e.g. invoked to retrieve an 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
}
});