Authorization FAQ

Here’s a deeper dive into the OAuth 2.0 and authorization process to connect apps with the Intuit Financial Ecosystem.

Do I need to authorize my app to integrate it with QuickBooks?

Yes. The first step is to create an app on the Intuit Developer Platform. This generates credentials you’ll use to connect to the Intuit OAuth 2.0 server, get access tokens, and make API calls.

OAuth 2.0 is our authorization standard. Only registered apps can connect to the Intuit OAuth2.0 server, call our API, and end-users’ QuickBooks Online companies.

What credentials do I need to connect to OAuth?

Here’s what you need to get started. Keep in mind, different API entities and features may require additional info:

How do access tokens work?

Access tokens work behind the scenes. They allow the connection between your app, the Intuit OAuth 2.0 server, our API, and an end-user’s device.

Tokening starts when users connect to your app. Your app sends users an authorization request. This request redirects users to sign in to their QuickBooks Online company. We ask if they’re willing to give your app permission to access their data. This flow is called “user consent.”

If a user grants permission, the Intuit OAuth 2.0 Server sends an authorization code to your app. Your app then sends the authorization code back to the server to get an access token. Use the access token to call our API and query objects or perform operations.

If the user doesn’t grant the permission, the server returns an error and your app can’t call our API.

How long do access and refresh tokens last?
Access tokens

Access tokens are valid for 3,600 seconds (or one hour).

When it expires, use the latest refresh_token value from the most recent server response to “refresh” it.

If an API request returns a 401 unauthorized message, it means the access token has expired.

Refresh tokens

Refresh tokens are valid for 100 days. This expiry date is rolling and gets extended each time it’s used to refresh an access token.

Refresh tokens are only for getting new access tokens.

As long as the refresh token itself hasn’t expired, each time you refresh your access token, your app periodically updates the refresh_token value. This is for security. When you get a new refresh token, the previous refresh token value automatically expires.

Important

Tip: We update the value of the refresh_token value every 24 hours hours, or the next time you refresh the access tokens after 24 hours. This is an additional security measure by Intuit to reduce risk of compromise.

We recommend you always store and use the latest access_token and refresh_token value from the most recent server response when you refresh access tokens.

If the refresh token hasn’t been used in the last 100 days, meaning a user hasn’t connected to your app and thus no API calls have been made, the refresh token expires. Your app’s access to the QuickBooks company terminates. Users will need to sign in and authorize your app again.

Why does the refresh_token value change after 24 hours?

Each time you make an API call and refresh your app’s access token, our server also sends your app a new value for the refresh_token.

Keep in mind, we periodically update and change refresh refresh_token values. This is an additional security measure by Intuit to reduce risk of compromise. While the refresh token itself doesn’t expire, the value changes every 24 hours. This makes the previous refresh_token value stale.

We recommend you always store and use the latest access_token and refresh_token value from the most recent server response when you refresh access tokens.

Why is my access token invalid?

Access tokens may stop working for a few reasons:

As a best practice, write your code to anticipate situations where granted access tokens become invalid.

How do I fix “invalid_grant” errors?

You may see an invalid_grant error when exchanging your authorization code for access tokens or refreshing access tokens.

When exchanging the authorization code for access tokens

  1. Review the redirect URI for your app. It should match with the redirect URI used in queries to the Intuit OAuth 2.0 server. Redirect URIs shouldn’t have any query parameters. If query parameters are required, pass them as state variables.
  2. If you have a multi-threaded app, make sure the developer’s application is not using the same parameter name code for other purposes. Code can’t be reused multiple times. If Intuit OAuth 2.0 server sends data with the code parameter to your app, used by a different thread, this can create a conflict.
  3. Check the Client ID and Client secret for your app. Also make sure you use the correct set of keys: development keys should be used for development environments, production keys are for your live code.
  4. Only exchange access tokens one at a time. If two attempts are made to exchange for access tokens, the first attempt will succeed but the second will return invalid_grant.

Our servers may see this as a possible security issue and revoke your refresh tokens for the first successful call. Your next attempt to refresh tokens will return the invalid_grant error. At this point, you’ll need to start the authorization process from the beginning.

When refreshing an access token

  1. Make sure the refresh token hasn’t expired. If you use an old refresh token, you’ll get an invalid_grant error.
  2. Go to the developer group status page to see if there are any API service outages, or if our servers are undergoing maintenance. Service outages may return an invalid_grant error.
  3. Check your app’s code to see if it’s not sending stale or cached values, instead of the latest ones sent via responses from the Intuit OAuth 2.0 Server. If you’re using a QuickBooks Online SDK, make sure the client object is updated with the latest token object.
  4. Make sure the refresh token hasn’t been revoked. Using a revoked refresh token will result in an error. Review the returned error message to make changes.
  5. Requests to refresh tokens require both the current access_token and refresh_token. The result should be a newly generated access token. Only exchange access tokens (meaning one unique value for the access_token parameter) one at a time. If two attempts are made, the first attempt will succeed, but the second will return invalid_grant. Multiple attempts may invalidate your refresh token.

Important

Important: We periodically update refresh_token values. It’s a good idea to always store and use the latest refresh_token value from the most recent server response.
What’s a redirect URI? Do I need one?

Redirect URIs are used for authorization. It’s where the Intuit OAuth 2.0 Server sends users after they agree to authenticate your app during the authorization process.

It’s also where your app sends requests from and our servers return responses after users connect to your app.

Code at the URI location needs to process the initial authorization server request, construct requests for access and refresh tokens, and manage tokens. The Intuit OAuth 2.0 Server can only redirect and send responses to registered URIs.

How do I register a redirect URI?

Apps have two URIs: one for development (sandbox) environments and one for your production app.

Follow these steps to set your app’s URI.

Note

Important: HTTP redirect URIs must be protected with TLS security. The Intuit OAuth 2.0 Server can only redirect to URIs beginning with https. IP addresses aren’t allowed. This prevents access token interception during the authorization process.

During development, you also need to register redirect URIs for any third-party testing platforms (Postman, Insomnia, etc) or other apps when testing with your sandbox company.

What are the current scopes for the QuickBooks API?

Scopes determine the type and level of access your app gets to QuickBooks Online company data. This also decides which API entities your app can use.

When you set up OAuth 2.0, you’ll list your app’s scopes in the authorization request. We recommend requesting scopes incrementally, based on your current data requirements, rather than requesting all scopes up front.

Keep in mind, you must initiate the authorization workflow again with the new list of scopes and get new access and refresh tokens. Users also need to reauthorize your app each time you change your app’s scopes.

How do I create the UI where users connect to my app, and how does it start the authorization process?

Before you start, review the rules for using branded images.

Here are a few examples of basic UI that lets users connect their QuickBooks Online company to your app. Pick the method that’s best for you.

Create a button and use it as an in-app connection point, using the accounting scope

Create a button and use it as an in-app connection point, using the accounting scope

This example covers creating UI so users can connect from within your app. We’ll use the following scopes:

  • com.intuit.quickbooks.accounting

These scopes let your app make calls to our Accounting API.

Design your app to include a “Connect to QuickBooks” button somewhere in the UI.

../../../../_images/C2QB_auth.png

When users select this button, your app starts the authorization process and sends an authorization request.

Create a URL for the chosen scopes. Use your app’s Client ID and Client Secret from your developers account. You’ll also need the redirect URI.

Example Authorize URL for the accounting scope

1
2
3
4
5
6
https://appcenter.intuit.com/connect/oauth2?
      client_id=<Client ID from developer portal>&
      response_type=code&
      redirect_uri=<redirect URI for your app>&
      scope=com.intuit.quickbooks.accounting&
      state=security_token%3D138r5719ru3e1

After your user selects the “Connect to QuickBooks” button, they’re taken to a sign-on page. This is where they authorize the connection and give your app access to their data.

Authorization_page_example

qbo/docs/develop/authentication-and-authorization/C2QB_Flow_Step4.png
qbo/docs/develop/authentication-and-authorization/C2QB_Flow_Step4.png

x


Create a button and use it as an in-app connection point, using the OpenID scope (single sign-on)

Create a button and use it as an in-app connection point, using the OpenID scope (single sign-on)

This example covers creating UI so users can connect from within your app. We’ll use the following scopes:

  • openid
  • At least one of the following: profile, email, phone, address

These scopes let your app get user profile info.

Design your app to include a “Sign in with Intuit” button somewhere in the UI.

../../../../_images/SIWI_openid.png

When users select this button, your app starts the authorization process and sends an authorization request.

Create a URL for the chosen scopes. Use your app’s Client ID and Client Secret from your developers account. You’ll also need the redirect URI.

Example Authorize URL for OpenID Connect

1
2
3
4
5
6
7
https://appcenter.intuit.com/connect/oauth2?
      client_id=<Client ID from developer portal>&
      scope=openid%20email%20address&
      redirect_uri=<redirect URI for your app>&
      response_type=code&
      state=138r5719ru3e1&
      claims=%7B%22id_token%22%3A%7B%22realmId%22%3Anull%7D%7D

In this example, the user should already be signed in to the QuickBooks Online company they want to connect. If not, the realmId won’t be presented back in the redirect URI.

After your user selects the “Sign in with Intuit” button, they’re taken to a sign-on page. This is where they authorize the connection and give your app access to their data.


Use the provided “Get app now” button from the QuickBooks App Store

Use the provided “Get app now” button from the QuickBooks App Store

This example assumes you want to list your app on the QuickBooks App store. Instead of creating a button, you’ll use the UI we provide so users can connect to your app. We’ll use the following scopes:

  • openid, profile, email, phone, address
  • com.intuit.quickbooks.accounting

These scopes let your app make calls to our Accounting API and get user profile info.

In this case, the authorization process starts when users visit the QuickBooks App Store and select the “Get app now” button.

../../../../_images/Get_app_now.png

Create a URL for the chosen scopes. Use your app’s Client ID and Client Secret from your developers account. You’ll also need the redirect URI.

Example Authorize URL for the accounting scope and OpenID Connect

1
2
3
4
5
6
7
https://appcenter.intuit.com/connect/oauth2?
      client_id=<Client ID from developer portal>&
      scope=openid%20email%20address%20com.intuit.quickbooks.accounting&
      redirect_uri=<redirect URI from developer portal>&
      response_type=code&
      state=138r5719ru3e1&
      claims=%7B%22id_token%22%3A%7B%22realmId%22%3Anull%7D%7D

To preview what this flow looks, get your app ID and visit the following URL:

  1. Sign in to your developer account.
  2. Select the Dashboard link on the toolbar.
  3. Find your app on the list.
  4. Copy the App ID.
  5. Visit https://appcenter.intuit.com/app/connect/oauth2/request?appId=djQuMTo6OGQzYmJlYTI3Yg:<App_ID_of_your_app>

This URL takes you to the Production Connect or Development Connect Request URL. This is specified in List on the app store section of your developer account.

Note

Note: To test the “Get app now” button in a sandbox environment, append the query parameter with sandbox_app=true.

Learn more about the “Get app now” button integration.

How can my app protect against cross-site request forgery (CSRF) from authentication requests?

You must protect the security of your users by preventing cross-site request forgery (CSRF) attacks. To mitigate attacks, include a unique session token in your app’s authorization request (often referred to as cross-site request forgery [CSRF] tokens).

A good way is to create a string of 30 or so characters constructed using a high-quality random-number generator. Another is creating a hash and comparing it to a key kept secret on your back end.

Use the ‘state’ parameter in your authorization request to add your unique session token. Your app will match the unique session token with the one returned in the Intuit OAuth 2.0 server response. This verifies the user, not a malicious attacker or bot, started the authorization process.

See our available SDKs and sample integrations
Language Does it have a client library Does it have integration examples
Java Yes
.Net Yes
PHP Yes
Ruby No
Node.js Yes
Python Yes
GoLang No Yes