Single-step OAuth2 is a simplified variant of the OAuth2 protocol. In the standard OAuth2 flow, the user is redirected to the data source, grants the requested scopes, and is redirected back to our service, which exchanges the resulting authorization code for an access token. Only after these steps can the user start making queries.
Single-step OAuth2 skips the interactive authorization and redirect steps. Instead, the user's credentials – such as a client ID and secret, or an API key and secret – are exchanged for an access token in a single request. This is commonly a client credentials grant.
Note
Use single-step OAuth2 when the data source issues an access token directly in exchange for static credentials, without redirecting the user to an authorization screen. If the data source uses the full redirect-based flow, use OAuth2 authentication instead.
Prerequisites for configuring single-step OAuth2 authentication
To configure single-step OAuth2 authentication, you need to know:
- The token endpoint the data source exposes for exchanging credentials for an access token.
- The credentials the data source expects (for example, a client ID and secret, or an API key and secret) and how they must be sent (for example, as a Base64-encoded
Authorizationheader, or as form parameters). - The JSON path to the access token in the response, and the lifetime of the token.
Unlike standard OAuth2, single-step OAuth2 does not require you to register a callback URL, since there's no redirect back to Supermetrics.
Single-step OAuth2 authentication flow
The single-step flow is defined under the singleStepOAuth2 object and consists of two parts:
authentication: The request that exchanges the user's credentials for an access token.refresh: The request to fetch a new token before the old one expires.- How the refresh works depends on the data source. Some APIs re-send the stored credentials to the token endpoint to obtain a fresh access token, while others return a refresh token from the authentication step that is used to request a new token.
Template single-step OAuth2 configuration
Below you can find a template configuration that you can fill in with your own information for an easier start. The exact headers, body format, and parameters depend on the data source – fill in the placeholders based on what the API's token endpoint requires:
{
"authentication": {
"type": "single_step_oauth2",
"description": "Example description shown to users in the authentication screen.",
"userInputs": [
{
"id": "[input id]",
"label": "[label shown to the user]",
"type": "text"
}
],
"singleStepOAuth2": {
"clientId": "[encrypted client ID, if required]",
"clientSecret": "[encrypted client secret, if required]",
"tokenLifetime": 3600,
"authentication": {
"tokenJsonPath": "$[path to access token in JSON response]",
"request": {
"method": "[HTTP method, e.g. POST]",
"url": "[url to token endpoint]",
"headers": [
{
"name": "[header name]",
"value": "[header value]"
}
],
"body": {
"type": "[body type, e.g. urlencoded_form]",
"formData": [
{
"name": "[parameter name]",
"value": "[parameter value]"
}
]
}
}
},
"refresh": {
"request": {
"method": "[HTTP method, e.g. POST]",
"url": "[url to token endpoint]",
"headers": [
{
"name": "[header name]",
"value": "[header value]"
}
],
"body": {
"type": "[body type, e.g. urlencoded_form]",
"formData": [
{
"name": "[parameter name]",
"value": "[parameter value]"
}
]
}
}
}
}
},
"secrets": {
"items": [
{
"id": "[secret id]",
"classification": "secret",
"source": "userInput",
"value": "[id of the user input field that collects this value]"
}
]
}
}
Configuring single-step OAuth2 authentication
We'll walk through configuring single-step OAuth2 authentication using the Quantcast Platform Reporting API as an example. The authentication details for this API can be found in Quantcast's documentation:
With Quantcast, you log in to the app to obtain your credentials (an Account ID, API key, and secret key), and then use those credentials to obtain an access token and start making requests.
To configure single-step OAuth2 authentication to Quantcast, we need to:
- Add an
authenticationcomponent with typesingle_step_oauth2. - Define the
userInputsto collect credentials from the connector user. - Configure the token request under the
authenticationobject, including the JSON path to the token and the token lifetime. - Configure the token refresh under the
refreshobject.
Base configuration for single-step OAuth2 authentication
Let's start by defining the base configuration for the single-step OAuth2 authentication type:
"authentication": {
"type": "single_step_oauth2",
"description": "Description shown to users during the authentication flow",
"singleStepOAuth2": {
...
}
}
Supplying credentials
With single-step OAuth2, the credentials are almost always provided by the connector user through the userInputs array (as in the Quantcast example below). We recommend registering these values as secrets and referencing them in requests with the {{secrets.*}} placeholder. A secret with source: "userInput" resolves to the user's value in both the authentication and refresh requests, so you don't need to switch between {{inputs.*}} and {{user.properties.*}} for the two flows.
Note
When all the credentials the data source needs are collected through
userInputs(as with Quantcast below), theclientIdandclientSecretproperties of thesingleStepOAuth2object are never referenced and therefore aren't used. They can be left empty – their contents don't affect the flow.
Single-step OAuth2 also works when a data source authenticates with a fixed developer application credential instead of, or alongside, the user's own credentials. In that less common case, store the application's ID and secret in the clientId and clientSecret properties and reference them in the request with the {{oauth2.client_id}} and {{oauth2.client_secret}} placeholders – for example, Basic {{base64(oauth2.client_id,':',oauth2.client_secret)}}. These values must be encrypted first, using the "Secret encryption" section of the Connector builder user interface.
User inputs
Because single-step OAuth2 has no interactive authorization screen, we collect the credentials the user needs to provide through the userInputs array. Each input defines an id (used to reference the value later), a label shown to the user, and a type.
Use the password type for sensitive values such as API keys and secrets, so they're masked in the user interface.
For Quantcast, we collect the Account ID, API key, API secret, and a name for the login:
"userInputs": [
{
"id": "account_id",
"label": "Account ID",
"type": "text"
},
{
"id": "api_key",
"label": "API key",
"type": "password"
},
{
"id": "secret_key",
"label": "API secret",
"type": "password"
},
{
"id": "username",
"label": "Give a name for your login",
"type": "text"
}
]
Because Quantcast issues credentials to the user directly, no separate developer application is required. The clientId and clientSecret fields are therefore left empty and the user's own credentials are used instead:
"singleStepOAuth2": {
"clientId": "",
"clientSecret": "",
...
}
Registering the credentials as secrets
Because the API key and secret are sensitive, we suggest registering them as secrets rather than referencing the user inputs directly. This keeps the values out of plain-text configuration and lets us reference them with the {{secrets.*}} placeholder in both the authentication and refresh requests.
Define the secrets at the connector root under the secrets component. For a value the user enters, set source to userInput and value to the id of the user input field that collects it. Sensitive credentials use the secret classification:
{
"secrets": {
"items": [
{
"id": "api_key",
"classification": "secret",
"source": "userInput",
"value": "api_key"
},
{
"id": "secret_key",
"classification": "secret",
"source": "userInput",
"value": "secret_key"
}
]
}
}
Each secret is now available as {{secrets.api_key}} and {{secrets.secret_key}} in the request URL, headers, parameters, and body.
Authentication request
Next, we configure the authentication object, which defines how the credentials are exchanged for an access token.
The Quantcast API expects a POST request to its token endpoint with the following details:
- The API key and secret key sent as a Base64-encoded
Authorizationheader. - A request body with the parameters:
grant_typewith the string valueclient_credentialsscopewith the required scopes
We reference the credentials through the secrets registered in the previous step using the secrets. prefix (for example, secrets.api_key), and use placeholder operations to Base64-encode them.
The tokenJsonPath property defines where to find the access token in the response, and is configured under the authentication object:
{
"authentication": {
"singleStepOAuth2": {
"authentication": {
"tokenJsonPath": "$.access_token",
"request": {
"type": "sync",
"method": "POST",
"url": "https://auth.quantcast.com/oauth2/default/v1/token",
"headers": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "Authorization",
"value": "Basic {{base64(secrets.api_key,':',secrets.secret_key)}}"
}
],
"body": {
"type": "urlencoded_form",
"formData": [
{
"name": "grant_type",
"value": "client_credentials"
},
{
"name": "scope",
"value": "api_access read_reports"
}
]
}
}
}
}
}
}
Token lifetime
Access tokens are typically set to expire after a short time. Configure the tokenLifetime property under the singleStepOAuth2 object as an integer with the number of seconds the token is valid. For Quantcast, the token is valid for 86400 seconds (24 hours):
"singleStepOAuth2": {
"clientId": "",
"clientSecret": "",
"tokenLifetime": 86400,
"authentication": {
...
}
}
Token refresh
To avoid requiring the user to re-authenticate every time the token expires, we configure an automatic refresh under the refresh object. For Quantcast, the refresh request re-sends the stored credentials to the same token endpoint to obtain a fresh access token, so it's identical to the authentication request.
The configuration for the refresh request looks like this:
{
"authentication": {
"singleStepOAuth2": {
"refresh": {
"request": {
"type": "sync",
"method": "POST",
"url": "https://auth.quantcast.com/oauth2/default/v1/token",
"headers": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "Authorization",
"value": "Basic {{base64(secrets.api_key,':',secrets.secret_key)}}"
}
],
"body": {
"type": "urlencoded_form",
"formData": [
{
"name": "grant_type",
"value": "client_credentials"
},
{
"name": "scope",
"value": "api_access read_reports"
}
]
}
}
}
}
}
}
Full configuration
Now you should have all the necessary configurations for a successful single-step OAuth2 authentication. Here you can see the full configuration for all the steps defined above:
{
"authentication": {
"type": "single_step_oauth2",
"description": "Please insert your Account ID and credentials from the data source and give a name for your login.",
"userInputs": [
{
"id": "account_id",
"label": "Account ID",
"type": "text"
},
{
"id": "api_key",
"label": "API key",
"type": "password"
},
{
"id": "secret_key",
"label": "API secret",
"type": "password"
},
{
"id": "username",
"label": "Give a name for your login",
"type": "text"
}
],
"singleStepOAuth2": {
"clientId": "",
"clientSecret": "",
"tokenLifetime": 86400,
"authentication": {
"tokenJsonPath": "$.access_token",
"request": {
"type": "sync",
"method": "POST",
"url": "https://auth.quantcast.com/oauth2/default/v1/token",
"headers": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "Authorization",
"value": "Basic {{base64(secrets.api_key,':',secrets.secret_key)}}"
}
],
"body": {
"type": "urlencoded_form",
"formData": [
{
"name": "grant_type",
"value": "client_credentials"
},
{
"name": "scope",
"value": "api_access read_reports"
}
]
}
}
},
"refresh": {
"request": {
"type": "sync",
"method": "POST",
"url": "https://auth.quantcast.com/oauth2/default/v1/token",
"headers": [
{
"name": "Accept",
"value": "application/json"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded"
},
{
"name": "Authorization",
"value": "Basic {{base64(secrets.api_key,':',secrets.secret_key)}}"
}
],
"body": {
"type": "urlencoded_form",
"formData": [
{
"name": "grant_type",
"value": "client_credentials"
},
{
"name": "scope",
"value": "api_access read_reports"
}
]
}
}
}
}
},
"secrets": {
"items": [
{
"id": "api_key",
"classification": "secret",
"source": "userInput",
"value": "api_key"
},
{
"id": "secret_key",
"classification": "secret",
"source": "userInput",
"value": "secret_key"
}
]
}
}
Using the single-step OAuth2 token in requests
Now that you have configured a successful single-step OAuth2 flow, you can start using the access token in other requests. For this, we'll be using placeholders, so we ensure all the requests will always use the latest refreshed token.
The token can be used in the request object using the placeholder {{user.access_token}} anywhere in the configuration: in account fetching, reporting, and so on.
The configuration for it will usually look like this:
...
"request": {
"url": "http://...",
"headers": [
{
"name": "Authorization",
"value": "Bearer {{user.access_token}}"
}
],
...
}