Set up OAuth 2.0

Use the OAuth 2.0 protocol to implment your app’s authentication and authorization.

We’ll show you how to set up the authorization flow so users can authorize to your app and give it permission to connect to their QuickBooks Online company.

If users grant permission, our Intuit OAuth 2.0 Server sends an authorization code back to your app. Your app exchanges this code for access tokens. These tokens are tied to your users’ now authorized QuickBooks Online company (identified by the realmID).

Your app needs access tokens to make API calls and interact with QuickBooks Online data.

Step 1: Create your app on the Intuit Developer Portal

Start by signing in to your developer account and creating an app on the Intuit Developer Portal.

When you create your app, select the QuickBooks Online Accounting scope.

This app provides the credentials you’ll need for authorization requests.

Step 2: Practice authorization in the OAuth Playground

Check out the OAuth Playground to preview each step of the authorization flow. We’ve provided sample data, like the redirect URI, so you can focus on the overall flow.

Using the OAuth Playground isn’t required, but we recommend it.

Step 3: Start developing with an SDK

Our SDKs come with a built-in OAuth 2.0 Client Library and handle many parts of the authorization implementation for you. For instance, our SDKs implement handlers that automatically exchange the authorization codes sent from the Intuit OAuth 2.0 Server for access tokens.

Select a link to download an SDK:


.NET

Java

PHP

Node.js

Python

Ruby

1
Install-Package IppDotNetSdkForQuickBooksApiV3

1
2
3
Download the latest version of oauth2-platform-api.jar and include it in your project.
Sample below shows how to add it to a gradle project:
compile (group: 'com.intuit.quickbooks-online', name: 'oauth2-platform-api', version: '6.0.7', classifier: 'jar-with-dependencies')

1
composer require quickbooks/v3-php-sdk

1
npm install intuit-oauth

1
pip install intuit-oauth

1
gem install 'intuit-oauth'

Note: Our SDKs are only for OAuth 2.0 and QuickBooks Online. SDKs aren’t required to develop an awesome app. However, given the importance of OAuth implementation, we strongly encourage you use them.
Step 4: Understand the end-to-end authorization flow

While authorization is a simple step for app users, it involves several tasks on the backend. Here’s an brief overview:

../../../../_images/oauth2-flow-diagram.png

Creating authorization requests

Managing the authorization flow

Getting access and refresh tokens

Making API calls

Step 5: Get your app’s credentials

Sign in to your Intuit Developer account and get your app’s Client ID and Client secret.

If you’re implementing authorization for a live, in-production app, go to the Production section and select Keys & OAuth to get your credentials.

If you’re implementing authorization for testing with a sandbox company, go to the Development section and select Keys & OAuth to get your credentials.

Step 6: Learn about discovery documents

OAuth 2.0 requires multiple URLs for authentication and requests for resources like tokens, user info, and credentials.

Use our discovery documents to simplify the implementation. These JSON documents, found at a well known location, contain field : value pairs and URL endpoints for authorization, token, userinfo, and other data points.

Step 7: Add your app’s redirect URIs

URIs handle responses from the Intuit OAuth 2.0 Server during the authorization flow. Basically, they’re your app’s endpoints.

Add at least one redirect URI for your app.

If you’re developing with an SDK, use the URI value generated by the SDK.

Tip: As a best practice, design your app’s endpoints so they don’t expose authorization codes to other resources on the page. Learn more about URIs and OAuth 2.0.
Step 8: Create an authorization request

Create the authorization request your app will send to the Intuit OAuth 2.0 Server when users connect to your app.


Authorization request parameters

Request parameters should identify your app and include the required scopes.

Field Description Required
client_id Identifies the app making the request. You got the client_id value in Step 5. Yes
scope

Lists the scopes your app uses.

Enter one or more scopes. The list should be space-delimited. The scope value defines the type of data an app can utilize. This information appears on the authorization page users see when they connect to your app.

Tip: We recommend apps request scopes incrementally based on your feature requirements, rather than all scopes up front.

Yes
redirect_uri Determines where the Intuit OAuth 2.0 Server redirects users to if they authorize your app. The redirect value must match the URI you listed in Step 7, including casing, http scheme, and trailing “/.” Yes
response_type

States if the Intuit OAuth 2.0 endpoint returns an authorization code.

Always set the value to “code”. Example: ``code_type``= code

Yes
state

Defines the state between your authorization request and the Intuit OAuth 2.0 Server response.

The state field is used for validation. It checks if the client (i.e. your app) gets the data back that it sent in the original request. Meaning, the state is maintained from send to response.

You can enter any string value for the state. The server should return the exact state : value pair sent in the original request.

Tip: We strongly recommend you include an anti-forgery token for the state and confirm it in the response. This prevents cross-site request forgery. Learn more about CSRF.

Yes
Important: You must create authorization requests in a browser modal. If your app doesn’t have browser support, use the OAuth Playground, Postman, or another web component to set up the authorization flow.

If you’re developing with a QuickBooks SDK

You can create and configure an object that defines the authorization request with the required parameters.

Here are example authorization requests for supported SDKs:

.NET

Java

PHP

Node.js

Python

Ruby

1
2
3
4
5
6
7
8
9
// Instantiate object
public static OAuth2Client oauthClient = new OAuth2Client(“clientid”, “clientsecret”, “redirectUrl”, “environment”); // environment is “sandbox” or “production”

//Prepare scopes
List<OidcScopes> scopes = new List<OidcScopes>();
scopes.Add(OidcScopes.Accounting);

//Get the authorization URL
string authorizeUrl = oauthClient.GetAuthorizationURL(scopes);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
//Prepare the config
OAuth2Config oauth2Config = new OAuth2Config.OAuth2ConfigBuilder("clientId", "clientSecret")
        .callDiscoveryAPI(Environment.SANDBOX).buildConfig();

//Generate the CSRF token
String csrf = oauth2Config.generateCSRFToken();

//Prepare scopes
List<Scope> scopes = new ArrayList<Scope>();
scopes.add(Scope.Accounting); // add as needed

//Get the authorization URL
String url = oauth2Config.prepareUrl(scopes, redirectUri, csrf); //redirectUri - pass the callback url

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$dataService = DataService::Configure(array(
      'auth_mode' => 'oauth2',
      'ClientID' => "Client ID from the app's keys tab",
      'ClientSecret' => "Client Secret from the app's keys tab",
      'RedirectURI' => "The redirect URI provided on the Redirect URIs part under keys tab",
      'scope' => "com.intuit.quickbooks.accounting or com.intuit.quickbooks.payment",
      'baseUrl' => "Development/Production"
));
$OAuth2LoginHelper = $dataService->getOAuth2LoginHelper();
$authorizationCodeUrl = $OAuth2LoginHelper->getAuthorizationCodeURL();

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Instance of client
var oauthClient = new OAuthClient({
    clientId: '<Enter your clientId>',
    clientSecret: '<Enter your clientSecret>',
    environment: 'sandbox',                                // ‘sandbox’ or ‘production’
    redirectUri: '<Enter your redirectUri>'
});

// AuthorizationUri
var authUri = oauthClient.authorizeUri({scope:[OAuthClient.scopes.Accounting,OAuthClient.scopes.OpenId],state:'testState'});  // can be an array of multiple scopes ex : {scope:[OAuthClient.scopes.Accounting,OAuthClient.scopes.OpenId]}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
from intuitlib.client import AuthClient
from intuitlib.enums import Scopes

//Instantiate client
auth_client = AuthClient(
    “client_id”,
    “client_secret”,
    “redirect_uri”,
    “Environment”, # “sandbox” or “production”
)

// Prepare scopes
scopes = [
    Scopes.ACCOUNTING,
]

// Get authorization URL
auth_url = auth_client.get_authorization_url(scopes)

1
2
3
4
5
6
7
8
9
require 'intuit-oauth'

client = IntuitOAuth::Client.new('client_id', 'client_secret', 'redirectUrl', 'environment')
scopes = [
    IntuitOAuth::Scopes::ACCOUNTING
]

authorizationCodeUrl = oauth_client.code.get_auth_uri(scopes)
# => https://appcenter.intuit.com/connect/oauth2?client_id=clientId&redirect_uri=redirectUrl&response_type=code&scope=com.intuit.quickbooks.accounting&state=rMwcoDITc2N6FJsUGGO9

Depending on the SDK, you may need to set up the configuration file with your Client ID, Client secret, and Redirect URI. Simply reuse the values from previous steps.


If you’re creating an HTTPS/REST request manually

Manually create an authorization request in your app’s language. You’ll need to call the Intuit OAuth 2.0 Server endpoint, generate a URL, and define the URL’s parameters.

Get the base URI from the discovery document. You can also follow these links:

Use the values from the authorization_endpoint.

Step 9: Redirect users to the authorization page

Your app needs to redirect users to the authorization page via the Intuit OAuth 2.0 Server. This starts the “user consent” step of the process. We’ll call this the “authorization flow.”

The authorization flow is required when users connect to your app for the first time. It’s also required any time you change your app’s scopes (i.e. incremental authorization). Users need to grant permission again since your app needs to request access additional data.

Use the authorization URL from your authorization request, or use the following examples.

If you’re developing with a QuickBooks SDK

Here are example redirects for supported SDKs:

.NET

Java

PHP

Node.js

Python

Ruby

1
2
// Redirect the authorization URL
return Redirect(authorizeUrl);

1
2
//Use standard url redirect-
resp.sendRedirect(url);

1
2
//redirect users to authorization screen url
header('Location: '. $authorizationCodeUrl);

1
2
// Redirect the authUri
res.redirect(authUri);

1
2
//Using standard redirect
return redirect(auth_url)

1
redirect_to(authorizationCodeUrl)

If you’re creating an HTTPS/REST request manually

Here’s an example authorization request URL. It specifies the QuickBooks Online Accounting scope (i.e com.intuit.quickbooks.accounting) and adds line brakes for readability:

1
2
3
4
5
https://appcenter.intuit.com/connect/oauth2?
    client_id=Q3ylJatCvnkYqVKLmkxxxxxxxxxxxxxxxkYB36b5mws7HkKUEv9aI&response_type=code&
    scope=com.intuit.quickbooks.accounting&
    redirect_uri=https://www.mydemoapp.com/oauth-redirect&
    state=security_token%3D138r5719ru3e1%26url%3Dhttps://www.mydemoapp.com/oauth-redirect

Review manual requests with cURL

You can review the authorization request URI using cURL. Here’s an example:

1
curl -X POST '< Authorization URI from previous step>'
Step 10: Create the UI that redirects users to the authorization page

There are a few ways users can connect to your app:

Since designing this UI may come later in development, we won’t focus on it here. However you decide to set up the UI, it needs to redirect users to the Intuit OAuth 2.0 Server and open the authorization page.

Preview the authorization page

../../../../_images/oauth2-user-consent-diagram.png

This authorization page is where users authorize your app and give it permission to access their data. They’ll see your app’s name and the QuickBooks Online company they’re connecting with.

If they authorize your app, the server will redirect them back to the redirect URI you set.

Step 11: Get the authorization code from server response

At this point, your app is waiting for a response from the Intuit OAuth 2.0 Server.

If users authorize your app, the Intuit OAuth 2.0 Server sends a response to the redirect URI you specified in Step 7. The response contains an authorization code in the code field.

Copy the code value.


See an example server response for authorization codes

1
2
3
4
https://www.mydemoapp.com/oauth-redirect?
    code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
    state=security_token%3D138r5719ru3e1%26url%3Dhttps://www.mydemoapp.com/oauth-redirect&
    realmId=1231434565226279

Parameter Description
code

The authorization code sent by the Intuit OAuth 2.0 Server.

Max length: 512 characters

realmId The unique ID of the connected user’s QuickBooks Online company. It’s also sometimes called the “company ID.- Use the realmId for subsequent API endpoint URLs to get data from QuickBooks Online companies.
state The state value sent from the Intuit OAuth 2.0 Server. It should match the state sent in the original authorization request.

If users don’t authorize your app, the server sends an access_denied error.

If the authorization request has a scope issue, the server sends an invalid_scope error.

Note: If your response endpoint renders an HTML page, other resources on that page can see the authorization code in the URL. Scripts can read the URL directly, and all resources may be sent to the URL in the caller and Referer HTTP header. Carefully consider if you want to send authorization credentials this way. This is especially important for third-party scripts, such as social plugins and analytics. To avoid issues, we recommend the server first handle the request, then redirect to another URL that doesn’t include the response parameters.
Step 12: Exchange the authorization code for access tokens

Your app should send the authorization code (i.e. the value of the code parameter) back to the Intuit OAuth 2.0 server to exchange it for access and refresh tokens.

If you’re developing with a QuickBooks SDK

Use the example code to create an object named tokenResponse. This automatically exchanges the authorization code for access and refresh tokens:

.NET

Java

PHP

Node.js

Python

Ruby

1
2
3
4
5
// Get OAuth2 Bearer token
var tokenResponse = await auth2Client.GetBearerTokenAsync(code);
//retrieve access_token and refresh_token
tokenResponse.AccessToken
tokenResponse.RefreshToken

1
2
3
4
5
6
7
8
9
//Prepare OAuth2PlatformClient
OAuth2PlatformClient client  = new OAuth2PlatformClient(oauth2Config);

//Get the bearer token (OAuth2 tokens)
BearerTokenResponse bearerTokenResponse = client.retrieveBearerTokens(authCode, redirectUri);

//retrieve the token using the variables below
bearerTokenResponse.getAccessToken()
bearerTokenResponse.getRefreshToken()

1
2
3
$accessTokenObj = $OAuth2LoginHelper->exchangeAuthorizationCodeForToken("authorizationCode", "realmId");
$accessTokenValue = $accessTokenObj->getAccessToken();
$refreshTokenValue = $accessTokenObj->getRefreshToken();

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Parse the redirect URL for authCode and exchange them for tokens
var parseRedirect = req.url;

// Exchange the auth code retrieved from the **req.url** on the redirectUri
oauthClient.createToken(parseRedirect)
    .then(function(authResponse) {
        console.log('The Token is  '+ JSON.stringify(authResponse.getJson()));
    })
    .catch(function(e) {
        console.error("The error message is :"+e.originalMessage);
        console.error(e.intuit_tid);
    });

1
2
3
4
5
6
// Get OAuth2 Bearer token
auth_client.get_bearer_token(auth_code, realm_id=realm_id)

//retrieve access_token and refresh_token
auth_client.access_token
auth_client.refresh_token

1
2
oauth2Token = oauth_client.token.get_bearer_token('the authorization code returned from authorizationCodeUrl')
# => #<IntuitOAuth::ClientResponse:0x00007f9152b5c418 @access_token="the access token", @expires_in=3600, @refresh_token="the refresh token", @x_refresh_token_expires_in=8726400>

If you’re creating an HTTPS/REST request manually

Get the base URI from the discovery document. You can also follow these links:

Create a POST request to exchange the authorization code for access and refresh tokens.

Send requests to the token_endpoint (available in the discovery document) using the following parameters:

Important: Only send one request to exchange the authorization code. Multiple requests may invalidate tokens.

Request parameters for token exchange
Field Description Required
code The authorization code your app received from the Intuit OAuth 2.0 response. Yes
redirect_uri The redirect URI listed for your app. You set this in Step 7. Yes
grant_type The type defined by the OAuth 2.0 server specification. It must have the value authorization_code. Yes

Here’s an example token exchange request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer HTTP/1.1
Accept: application/json
Authorization: Basic UTM0dVBvRDIwanp2OUdxNXE1dmlMemppcTlwM1d2
    NzRUdDNReGkwZVNTTDhFRWwxb0g6VEh0WEJlR3dheEtZSlVNaFhzeGxma1l
    XaFg3ZlFlRzFtN2szTFRwbw==
Content-Type: application/x-www-form-urlencoded
Host: oauth.platform.intuit.com
Body: grant_type=authorization_code&
code=L3114709614564VSU8JSEiPkXx1xhV8D9mv4xbv6sZJycibMUI&
redirect_uri=https://www.mydemoapp.com/oauth-redirect

Review manual requests with cURL

You can review the POST request using cURL. The Authorization header should follow this format:

1
"Basic " + base64encode(client_id + ":" + client_secret)

Here’s an example cURL POST:

1
2
3
4
5
6
7
curl -X POST 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer' \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: REPLACE_WITH_AUTHORIZATION_HEADER (details below)' \
-d 'grant_type=authorization_code' \
-d 'code=REPLACE_WITH_AUTHORIZATION_CODE' \
-d 'redirect_uri=REPLACE_WITH_REDIRECT_URI'

See an example server response for exchanged tokens

The server returns a JSON object. The access code is the access_token field value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
"token_type": "bearer",
"expires_in": 3600,
"refresh_token":"Q311488394272qbajGfLBwGmVsbF6VoNpUKaIO5oL49aXLVJUB",
"x_refresh_token_expires_in":15551893,
"access_token":"eJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiZGGlyIn0..KM1_Fezsm6BUSaqqfTedaA.
dBUCZWiVmjH8CdpXeh_pmaM3kJlJkLEqJlfmavwGQDThcf94fbj9nBZkjEPLvBcQznJnEmltCIvsTGX0ue_w45h7_
yn1zBoOb-1QIYVE0E5TI9z4tMUgQNeUkD1w-X8ECVraeOEecKaqSW32Oae0yfKhDFbwQZnptbPzIDaqiduiM_q
EFcbAzT-7-znVd09lE3BTpdMF9MYqWdI5wPqbP8okMI0l8aa-UVFDH9wtli80zhHb7GgI1eudqRQc0sS9zWWb
I-eRcIhjcIndNUowSFCrVcYG6_kIj3uRUmIV-KjJUeXdSV9kcTAWL9UGYoMnTPQemStBd2thevPUuvKrPdz3ED
ft-RVRLQYUJSJ1oA2Q213Uv4kFQJgNinYuG9co_qAE6A2YzVn6A8jCap6qGR6vWHFoLjM2TutVd6eOeYoL2bb7jl
QALEpYGj4E1h3y2xZITWvnmI0CEL_dYQX6B3QTO36TDaVl9WnTaCCgAcP6bt70rFlPYbCjOxLoI6qFm5pUwGLLp
67JZ36grc58k7NIyKJ8dLJUL_Q9r1WoUvw.ZS298t_u7dSlkfajxLfO9Q"
}
Field Description
access_token The token used to access our API. Max length: 4096 characters.
refresh_token The token used for refreshing the access token. Max length: 512 characters.
expires_in The remaining lifetime of the access token. The value begins at 3600. This is in seconds (one hour).
x_refresh_token_expires_in The remaining lifetime of the current refresh token. This is in seconds. When this expires, users must reauthorize your app.
token_type The type of token returned. This always has the value bearer.
Tip: The response may have other parameters. Don’t treat them as errors. This only lists the minimum set.
Step 13: Decide if you want to implement OpenID Connect

Your app is now set up with OAuth 2.0.

At this point, you can also implement Intuit Single Sign-on and OpenID Connect to further enhance authorization features.

Step 14: Use access tokens to make API calls

Access tokens let your app send requests to our APIs.

Pass the access_token value in the Authorization header of requests each time your app calls an API. The value should always be: Authorization: bearer {AccessToken}

Access tokens are valid for 60 minutes (3,600 seconds). When they expire, use refresh tokens to refresh them. Learn more about access and refresh tokens.

Refresh access tokens

Use refresh tokens to “refresh” expired access tokens. You can refresh access tokens without prompting users for permission.


If you’re developing with a QuickBooks SDK

Here are examples of refreshing access tokens. Since you’re using a supported SDK, server requests and responses get parsed internally.

.NET

Java

PHP

Node.js

Python

Ruby

1
2
3
4
5
// Instantiate object
public static OAuth2Client oauthClient = new OAuth2Client(“clientid”, “clientsecret”, “redirectUrl”, “environment”); // environment is “sandbox” or “production”

//Refresh token endpoint
var tokenResp = await oauthClient.RefreshTokenAsync(“refreshToken”);

1
2
3
4
5
6
7
8
//Prepare the config
OAuth2Config oauth2Config = new OAuth2Config.OAuth2ConfigBuilder("OAuth2AppClientId", "OAuth2AppClientSecret").callDiscoveryAPI(Environment.SANDBOX).buildConfig();

//Prepare OAuth2PlatformClient
OAuth2PlatformClient client  = new OAuth2PlatformClient(oauth2Config);

//Call refresh endpoint
BearerTokenResponse bearerTokenResponse = client.refreshToken("refreshToken"); //set refresh token

1
2
3
4
5
$oauth2LoginHelper = new OAuth2LoginHelper($ClientID,$ClientSecret);
$accessTokenObj = $oauth2LoginHelper->
                    refreshAccessTokenWithRefreshToken($theRefreshTokenValue);
$accessTokenValue = $accessTokenObj->getAccessToken();
$refreshTokenValue = $accessTokenObj->getRefreshToken();

1
2
3
4
5
6
7
8
   oauthClient.refresh()
        .then(function(authResponse) {
            console.log('Tokens refreshed : ' + JSON.stringify(authResponse.json()));
        })
        .catch(function(e) {
            console.error("The error message is :"+e.originalMessage);
            console.error(e.intuit_tid);
        });

1
2
3
4
5
6
7
8
9
# Instantiate client
auth_client = AuthClient(
    “client_id”,
    “client_secret”,
    “redirect_uri”,
    “Environment”, # “sandbox” or “production”
)
# Refresh token endpoint
auth_client.refresh(refresh_token=”refresh_token”)

1
newToken = oauth_client.token.refresh_tokens('Your_refresh_token')

If you’re creating an HTTPS/REST request manually

Create a POST request and use the latest refresh_token value from the most recent API server response.

Send requests to the token_endpoint (available in the discovery document) using the following parameters:


Request parameters for refresh tokens
Field Description Required
grant_type

This is defined in the OAuth 2.0 server specification.

It must have the value refresh_token.

Required
refresh_token The refresh_token value you exchanged the authorization code for. Required

Here’s an example request:

1
2
3
4
5
6
7
8
POST /oauth2/v1/tokens/bearer HTTP/1.1
Accept: application/json
Authorization: Basic UTM0dVBvRDIwanp2OUdxNXE1dmlMemppcTlwM1d2
    NzRUdDNReGkwZVNTTDhFRWwxb0g6VEh0WEJlR3dheEtZSlVNaFhzeGxma1l
    XaFg3ZlFlRzFtN2szTFRwbw==
Content-Type: application/x-www-form-urlencoded
Body: grant_type=refresh_token&
refresh_token=Q311488394272qbajGfLBwGmVsbF6VoNpUKaIO5oL49aXLVJUB

Review manual requests with cURL

You can review the POST request using cURL. The Authorization header should follow this format:

1
"Basic " + base64encode(client_id + ":" + client_secret)

Here’s an example cURL POST:

1
2
3
4
5
6
curl -X POST 'https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer' \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: REPLACE_WITH_AUTHORIZATION_HEADER (details below)'  \
-d 'grant_type=refresh_token' \
-d 'refresh_token=REPLACE_WITH_REFRESH_TOKEN'

See an example server response for refresh tokens

The server returns a JSON object with a refreshed access token in the access_token field.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
"token_type": "bearer",
"expires_in": 3600,
"refresh_token":"Q311488394272qbajGfLBwGmVsbF6VoNpUKaIO5oL49aXLVJUB",
"x_refresh_token_expires_in":15551893,
"access_token":"eJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiZGGlyIn0..KM1_Fezsm6BUSaqqfTedaA.
dBUCZWiVmjH8CdpXeh_pmaM3kJlJkLEqJlfmavwGQDThcf94fbj9nBZkjEPLvBcQznJnEmltCIvsTGX0ue_w45h7_
yn1zBoOb-1QIYVE0E5TI9z4tMUgQNeUkD1w-X8ECVraeOEecKaqSW32Oae0yfKhDFbwQZnptbPzIDaqiduiM_q
EFcbAzT-7-znVd09lE3BTpdMF9MYqWdI5wPqbP8okMI0l8aa-UVFDH9wtli80zhHb7GgI1eudqRQc0sS9zWWb
I-eRcIhjcIndNUowSFCrVcYG6_kIj3uRUmIV-KjJUeXdSV9kcTAWL9UGYoMnTPQemStBd2thevPUuvKrPdz3ED
ft-RVRLQYUJSJ1oA2Q213Uv4kFQJgNinYuG9co_qAE6A2YzVn6A8jCap6qGR6vWHFoLjM2TutVd6eOeYoL2bb7jl
QALEpYGj4E1h3y2xZITWvnmI0CEL_dYQX6B3QTO36TDaVl9WnTaCCgAcP6bt70rFlPYbCjOxLoI6qFm5pUwGLLp
67JZ36grc58k7NIyKJ8dLJUL_Q9r1WoUvw.ZS298t_u7dSlkfajxLfO9Q"
}
Tip: Since apps use access and refresh tokens frequently, store them in a secure location that’s accessible between different invocations of your app. If access or refresh tokens aren’t working, here are a few areas to troubleshoot.
Revoke access tokens

If users disconnect from your app, it needs to automatically revoke access and refresh tokens. For example, this process can start when users select a Disconnect link or button somewhere in your app.


If you’re developing with a QuickBooks SDK

Here are request examples for supported SDKs.

Send the request to the revoke endpoint. This both revokes the access token and removes permissions.

.NET

Java

PHP

Node.js

Python

Ruby

1
2
3
4
5
// Instantiate object
public static OAuth2Client oauthClient = new OAuth2Client(“clientid”, “clientsecret”, “redirectUrl”, “environment”); // environment is “sandbox” or “production”

//Revoke token endpoint
var tokenResp = await oauthClient.RevokeTokenAsync(“refreshToken");

1
2
3
4
5
6
7
8
//Prepare the config
OAuth2Config oauth2Config = new OAuth2Config.OAuth2ConfigBuilder("OAuth2AppClientId", "OAuth2AppClientSecret").callDiscoveryAPI(Environment.SANDBOX).buildConfig();

//Prepare OAuth2PlatformClient
OAuth2PlatformClient client  = new OAuth2PlatformClient(oauth2Config);

//Call revoke endpoint
PlatformResponse response  = client.revokeToken("refreshToken"); //set refresh token

1
2
$oauth2LoginHelper = new OAuth2LoginHelper($clientID,$clientSecret);
$revokeResult = $oauth2LoginHelper->revokeToken($yourToken);

1
2
3
4
5
6
7
8
oauthClient.revoke(params)
        .then(function(authResponse) {
            console.log('Tokens revoked : ' + JSON.stringify(authResponse.json()));
        })
        .catch(function(e) {
            console.error("The error message is :"+e.originalMessage);
            console.error(e.intuit_tid);
        });

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Instantiate client
auth_client = AuthClient(
    “client_id”,
    “client_secret”,
    “redirect_uri”,
    “Environment”, # “sandbox” or “production”
)

# Refresh token endpoint
auth_client.revoke(token=”refresh_token”)

1
trueOrFalse = oauth_client.token.revoke_tokens('the_token_you_want_to_revoke')

If you’re creating an HTTPS/REST request manually

Create a POST request and include the refresh_token value for the token parameter.

Send the request to the revocation_endpoint (available in the discovery document). Here’s an example request:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
POST https://developer.api.intuit.com/v2/oauth2/tokens/revoke HTTP/1.1
Accept: application/json
Authorization: Basic UTM0dVBvRDIwanp2OUdxNXE1dmlMemppcTlwM1d2
    NzRUdDNReGkwZVNTTDhFRWwxb0g6VEh0WEJlR3dheEtZSlVNaFhzeGxma1l
    XaFg3ZlFlRzFtN2szTFRwbw==
Content-Type: application/json

{
    "token": "{bearerToken or refreshToken}"
}
Review manual requests with cURL

You can review the POST request using cURL. The Authorization header should follow this format:

1
"Basic " + base64encode(client_id + ":" + client_secret)

Here’s an example cURL POST:

1
2
3
4
5
curl -X POST 'https://developer.api.intuit.com/v2/oauth2/tokens/revoke' \
-H 'Accept: application/json' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: REPLACE_WITH_AUTHORIZATION_HEADER (details below)' \
-d 'token:REPLACE_WITH_REFRESH_TOKEN/REPLACE_WITH_ACCESS_TOKEN'
Server responses for revoked tokens

If the app successfully revoked access, the server sends a response code: status_code 200.

If it didn’t, or there was an error, you’ll see status_code 400. Review the error message and follow it’s instructions.

Get new refresh tokens

Refresh tokens have a rolling expiry of 100 days.

As long as refresh tokens are valid, you can use them to obtain new access tokens. Always store the latest refresh_token value from the most recent API server response. Use it to make requests and obtain new access tokens.

If 100 days pass, or your refresh token expires, users need to go through the authorization flow again and reauthorize your app.

Tip: You can also get new refresh tokens programmatically using the Refresh Token API before the 100 days expire.