OAuth Client Secret rotation
Overview
The Braintree GraphQL API provides mutations for creating, disabling, and deleting client secrets. This guide walks you through the steps to safely rotate a client secret using these mutations. The system will ensure that each OAuth application never has less than one enabled client secret and never has more than two secrets in total.
Audience
This guide assumes you understand making HTTP requests with headers and know how to run GraphQL mutations and queries over HTTP.
Prerequisites
IP restrictions enabled
To use the OAuth Client Secret Rotation APIs, you must have IP or hostname restrictions enabled, and you must define an allowed host IP. All client secret rotation requests must originate from that host.
An OAuth application
This guide assumes that you have an OAuth application created via the process explained in the Braintree Auth documentation. In the Braintree console, make note of your application's client ID and client secret because they will be needed for creating access tokens to access the API and the secret itself is needed for doing secret rotation.
An access token
To execute most Braintree API requests, an API key pair is required for authentication.
However, the API key pair alone is insufficient for validity of client secret rotation requests.
For these sensitive operations, you need an OAuth Access Token with one and only one scope named MANAGE_OAUTH_CLIENT_SECRETS
.
To get such an Access Token, follow the instructions in the OAuth Access Tokens Integration Guide.
Access Tokens have only a three-minute time-to-live (TTL) and are intended to be used by an automated process that completes in seconds.
Overview: Rotating a client secret
Rotating a secret is a multi-step operation, designed to avoid the possibility that you will delete your enabled key and lock yourself out of the system. Here is an overview of the process:
- Create a new client secret that will replace the old client secret that you wish to rotate. This new secret will be enabled, and you will have two enabled secrets.
- Disable the old client secret. Once you have updated your systems to use the new secret, you should disable the old secret in preparation for deleting it.
- Delete the old client secret. Now that the old secret is disabled, you can safely delete it.
The details of each operation are covered below.
Creating a new secret
To create a new client secret, you first create an access token with MANAGE_OAUTH_CLIENT_SECRETS
scope and then use that token to call the createOAuthClientSecret
mutation.
The Braintree API does not require any input for the client secret creation mutation. The OAuth application and merchant are determined by the access token provided in headers of a request. The mutation below creates a new client secret and returns the secret value.
mutation
mutation ($input: CreateOAuthClientSecretInput!) {.createOAuthClientSecret(input: $input) {secret}}
There must be an input, but no fields.
variables
{"input": {}}
Calls to the Braintree Making API calls documentation must include HTTP headers Braintree-Version
and Authorization
.
Braintree-Version: 2023-12-20
Authorization: Bearer <YOUR_ACCESS_TOKEN>
Expected response containing the brand-new OAuth client secret:
response
{"data": {"createOAuthClientSecret": {"secret":"NEW_CLIENT_SECRET_VALUE"}}}
Take note of the secret and save it somewhere safe. You will not be able to see it again via API calls or the control panel.
Disabling the old secret
Once you have switched your systems over to the new secret, you are ready to disable the old secret.
You do that by calling the disableOAuthClientSecret
mutation and passing in the old secret value to be disabled.
For this operation, you can use the original access token you created from the old secret (if not timed out), or a new one made from the new secret you just created.
Again, headers are required.
Braintree-Version: 2023-12-20
Authorization: Bearer <YOUR_ACCESS_TOKEN>
The disable mutation accepts a secret value input returning the masked secret and a boolean disabled
value.
mutation
mutation ($input: DisableOAuthClientSecretInput!) {disableOAuthClientSecret(input: $input) {oauthClientSecret {maskedSecretdisabled}}}
And the input to go along with that example:
variables
{"input": {"secret": "OLD_CLIENT_SECRET_VALUE"}}
The response from disable-secret will include the masked secret value, and a boolean disabled
value which willl be true
.
response
{"oauthClientSecret": {"maskedSecret": "*****************************ALUE","disabled": true}}
Deleting the old secret
Once you have disabled the old secret, it can be deleted.
To do that, create a new access token from the new secret and call the deleteOAuthClientSecret
mutation passing in the old secret value.
For this mutation, a new access token must be used, one created from the new client secret because the old secret is now disabled.
Before you call delete, create that new token.
Send the new access token in the headers.
Braintree-Version: 2023-12-20
Authorization: Bearer <NEW ACCESS TOKEN>
The delete-mutation accepts the old secret value and returns nothing.
mutation
mutation ($input: DeleteOAuthClientSecretInput!) {deleteOAuthClientSecret(input: $input) {}}
variables
{"input": {"secret": "OLD_CLIENT_SECRET_VALUE"}}
The delete-secret response will be empty, unless you specify a clientMutationId
.
Rotation complete!
Now that the old secret is deleted, you have successfully rotated your OAuth client secret.