Bixby Developer Center

Guides

Authorizing Access With OAuth

About Using OAuth With Bixby

You can use OAuth 2.0, with full support of the standard authorization code grant flow with Proof Key for Code Exchange (PKCE) for better security, so that users can authorize access to a third-party service.

Note

With our support for PKCE, the only code_challenge methods supported are S256 and SHA256.

In general, when OAuth is used, the key players are the following:

  • The user owns some resource (for example, their list of contacts) that could be made available to functions.

  • The provider of some service to access this protected resource (for example, Google's contacts service).

  • You, the developer, who implements the function to access the service, which might not be the provider.

  • The capsule, which uses Bixby's OAuth 2.0 client to ask for users' authorization, in order to access their resources at the service provider.

As the developer, you need to register your capsule as a standard OAuth 2.0 client that supports the standard Authorization Code Grant type. The client secrets are kept on Bixby's servers. Store the parameters, such as the client ID and the client secret you obtained from the provider, as developer keys with Bixby.

Different providers can be registered with Bixby. A user authorizes a capsule to access a particular scope of capabilities with the provider. To access OAuth APIs, you must have the developer keys registered with the provider, and store them with Bixby. Once the user authorizes access, the capsule receives an access key that allows access to user content from the provider.

In general, Bixby manages all these keys. You can learn more about how to implement OAuth below.

Note

Bixby does not currently support the OAuth 1.0 protocol. Your capsule must authenticate with OAuth 2.0 providers.

How to Implement OAuth

There are multiple things you must do to incorporate OAuth into your capsule.

  1. After creating your action models, implement your actions with OAuth.
  2. Set up the authorization in your authorization.bxb file.
  3. [Optional] Configure your properties with any additional information you might need.

Implement Your Actions With OAuth

You would implement your actions with OAuth by using API calls, as you would any other web service within Bixby. For more information and for an example function, you can read about it in the Calling Web Services -- OAuth topic.

Caution

You must use HTTPS for OAuth calls. Unencrypted HTTP endpoints are insecure and are not supported!

Bixby's maximum supported length for OAuth access tokens is 2048 characters.

You can use the various JavaScript OAuth APIs to make OAuth calls between the user and the provider, if your JavaScript function has a valid authorization section.

OAuth Authorization

Bixby has built-in support for endpoints that require OAuth 2.0 authorization. Use the authorization key and its subkeys to set the parameters for your capsule's external OAuth provider. You need to consult your OAuth provider's documentation to find its endpoint URIs and the parameters that it supports.

You configure OAuth under the authorization key in an authorization.bxb file in your capsule's root directory:

authorization {
user {
oauth2-authorization-code (providerId) {
authorize-endpoint (...)
client-id (...)
client-secret-key (...)
scope (...) // optional
token-endpoint (...)
}
}
global {
oauth2-client-credentials (providerId) {
client-id (...)
client-secret-key (...)
scope (...) // optional
token-endpoint (...)
}
}
}

The client-id is a public identifier for your application, registered with or assigned by your OAuth provider. The OAuth client secret is not stored in your capsule for security reasons. Instead, client-secret-key is used to look up the secret, which you enter on the Configuration & Secrets screen in the Bixby Developer Center.

You can specify authorization for only a user, only global, or both. To then use an authorization method defined in authorization.bxb with an endpoint, the endpoint must be annotated with authorization { user } or authorization { global }. If the endpoint is not annotated with authorization { something }, no authorization is used for that endpoint:

action-endpoint (MyAction) {
remote-endpoint (...) {
method (POST)
}
authorization {
user
}
}
Note

If you need to use a custom grant-type for a user, use the oauth2-custom key to define the authorization.

For an explanation of the authorization subkeys, see the authorization reference. Not all authorization definitions need to include all keys.

Here's another example, using the Spotify Web API:

authorization {
user {
oauth2-authorization-code (Spotify)
authorize-endpoint (https://accounts.spotify.com/authorize)
client-id (spotify-id)
client-secret-key (spotify-secret)
scope (playlist-read-private playlist-read-collaborative ...)
token-endpoint (https://accounts.spotify.com/api/token)
}
}

As part of the OAuth flow, you are required to register a redirect URI (redirect_uri) with the service provider. Normally, this is set in the service provider's dashboard. Refer to your provider's documentation for more information.

Register Bixby's redirect URI to the following:

https://<your-capsule-id>.oauth.aibixby.com/auth/external/cb

Replace <your-capsule-id> with your encoded capsule ID, with the - dash character in place of the . period character. For example, if your capsule ID is example.dice, your redirect URI would be https://example-dice.oauth.aibixby.com/auth/external/cb.

Multiple Global OAuth Specifications

You can also have multiple global OAuth specifications per capsule. If you do have multiple global specifications, you must add a providerID at the endpoint for disambiguation:

action-endpoint (...) {
...
authorization {
global(<provider id>)
}
}

Token Endpoints

You can also define local token endpoints in a JavaScript file within your capsule. These endpoints could perform work, such as parameter reformatting, before calling an external OAuth token endpoint.

This authorization block specifies a local endpoint file, AuthEndpoints.js, and an exported function to call within that file named tokenEndpoint:

authorization {
user {
oauth2-authorization-code (myService) {
client-id (123-456-789)
client-secret-key (secret)
authorize-endpoint (https://api.myService.com/login/v3/oauth)
token-endpoint (AuthEndpoints.js::tokenEndpoint)
}
}
}

The AuthEndpoints.js file might look like this:

export function tokenEndpoint(input) {
const {
$grantType,
$clientId,
$clientSecret,
$scope,
$authCode,
$redirectUri,
$refreshToken,
$codeVerifier,
} = input
const options = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
Authorization: 'Basic {' + base64.encode($clientId + ':' + $clientSecret) + '}',
},
format: 'json',
}
const params = {
grant_type: 'authorization_code',
code: $authCode,
redirect_uri: $redirectUri,
}
const response = http.postUrl('https://api.myService.com/login/v3/oauth/access', params, options)
return {
access_token: response.access_token,
expires_in: response.expires_in,
refresh_token: response.refresh_token,
}
}

If the token endpoint does return a refresh_token, then once the access_token is expired, the new access_token is requested from the token endpoint with grant type: refresh_token. So if a local token endpoint is used, it also needs to handle any refresh_token tokens, if they are returned by the access_token grant. You can read more about token and token management, as well as general information on OAuth 2.0 on at https://oauth.net/2/.

The codeVerifier is used for the PKCE, as specified in RFC 7636. Bixby will pass the code challenge S256(codeVerifier) to your defined authorize-endpoint; your local endpoint should pass the code verifier on to its external token endpoint.

For another example, consider an action (TestAction) that requires OAuth authorization:

action (TestAction) {
type (Calculation)
collect {
input (input) {
type (TestConcept)
min (Required) max (One)
}
}
output (TestConcept)
}

You need to specify in your endpoints.bxb file that this TestAction requires OAuth authorization:

action-endpoint (TestAction) {
remote-endpoint ("{main.url}/TestPath") {
method (POST)
}
authorization {
user
}
}

The $vivContext parameter includes the OAuth access token as accessToken. $vivContext is included automatically in the request body for HTTP POST requests made to remote endpoints. To include it in local endpoints, include it in the accepted-inputs key.

OAuth access tokens will automatically be included with HTTP GET requests as long as your capsule is using runtime version 3 or later or the use-authorization-header-for-remote-endpoint-oauth runtime flag is set.

In this example, $vivContext is used to return the OAuth access token when a user logs off a service:

import authLib from 'lib/auth.js';

export function logout(input) {
const { $vivContext } = input;
return $vivContext.accessToken;
}

if (config.get('oauth.enable') == 'enable') {
export function authLib.getAuthorization as authorization;
}

See Authorization Errors for information on handling OAuth authorization errors in JavaScript actions.

Note

Bixby does not currently support the OAuth 1.0 protocol. Your capsule must authenticate with OAuth 2.0 providers.