The Intuit Node.js OAuth 2.0 Client makes it easy to authenticate and authorize using OAuth 2.0 and OpenID Connect when you integrate your Node.js web app with the QuickBooks Online API.
This guide assumes that you have an existing web app that you want to integrate with QuickBooks Online.
The recommended way to install the Intuit Node.js OAuth Client is with NPM. Node Package Manager is the package manager for JavaScript.
1 | npm install intuit-oauth --save |
To add the Intuit Node.js OAuth 2.0 Client as a dependency into your project, require the client as shown below:
1 2 3 4 5 6 7 8 9 | var OAuthClient = require('intuit-oauth'); var oauthClient = new OAuthClient({ clientId: 'Enter your clientId', // enter the apps `clientId` clientSecret: 'Enter your clientSecret', // enter the apps `clientSecret` environment: 'sandbox' || 'production', // enter either `sandbox` or `production` redirectUri: 'Enter your callback URL' // enter the redirectUri logging: true // by default the value is `false` }); |
The OAuthClient() method accepts the following parameters:
We have a sample app to showcase the usage of Intuit Node.js OAuth 2.0 Client to authenticate using OAuth 2.0. To use the sample app, you need the following prerequisites:
Note : Client Credentials can be found on the Keys section of the app when you create an app on Developer Portal. To know more on where to kind the Keys refer to Getting Started
1 2 3 | git clone https://github.com/intuit/oauth-jsclient.git cd sample npm install |
1 | cp .env.example .env
|
Edit the .env file to add your:
If you want your endpoint to be exposed over the internet, the easiest way while still developing your code locally is to use ngrok. You do not have to install ngrok. The sample app installs it for you.
1 | npm start
|
NGROK_ENABLED=false in .env)You will see a URL as shown below:
💳 See the sample app in your browser: http://localhost:8000
💳 Copy this into Redirect URI in the browser: http://localhost:8000/callback
💻 Make Sure this redirect URI is also copied to your app in: https://developer.intuit.com
Your will see a URL as shown below:
💻 See the sample app in your browser: https://9b4ee833.ngrok.io
💳 Copy and paste this redirect URI in the browser: https://9b4ee833.ngrok.io/callback
💻 Make Sure this redirect URI is also copied to your app in: https://developer.intuit.com
We welcome any reports of problems, comments, or suggestions. Please report these on the Issue Tracker in Github.
The SDK offers the following helper methods:
1. Is Access-Token Valid
You can check if the access token associated with the oauthClient is valid or not using the helper method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | if(oauthClient.isAccessTokenValid()) { console.log("The access_token is valid"); } if(!oauthClient.isAccessTokenValid()){ 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); }); } .. container:: new-list-content |
Note: If the access_token is not valid, you can call the client’s refresh() method to refresh the tokens for you as shown below.
2. Refresh Access-Token
Access tokens are valid for 3600 seconds (one hour), after which time you need to get a fresh one using the latest refresh token returned to you from the previous request.
When you request a fresh access token, always use the refresh token returned in the most recent token_endpoint response. Your previous refresh tokens expire 24 hours after you receive a new one:
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); }); |
3. Revoke Access-Token
When you no longer need the access token, you could use the below helper method to revoke the tokens. You can also optionally pass the access token or refresh token to this helper method:
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); }); |
4. Getter / Setter for Token
You can call the below methods to set and get the tokens using the oauthClient instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | oauthClient.getToken().setToken({ "token_type": "bearer", "expires_in": 3600, "refresh_token":"<refresh_token>", "x_refresh_token_expires_in":15552000, "access_token":"<access_token>" }); // To get the tokens oauthClient.getToken().getToken(); `OR` oauthClient.token.getToken(); |
The client provides an authResponse, which is a wrapped response that includes the following:
1 2 3 4 5 | 1. response // response from `HTTP Client` used by library 2. token // instance of `Token` Object 3. body // res.body in `text` 4. json // res.body in `JSON` 5. intuit_tid // `intuit-tid` from response headers |
A sample AuthResponse object would look similar to:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | { "token":{ "realmId":"<realmId>", "token_type":"bearer", "access_token":"<access_token>", "refresh_token":"<refresh_token>", "expires_in":3600, "x_refresh_token_expires_in":8726400, "id_token":"<id_token>", "latency":60000 }, "response":{ "url":"https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer", "headers":{ "content-type":"application/json;charset=UTF-8", "content-length":"61", "connection":"close", "server":"nginx", "strict-transport-security":"max-age=15552000", "intuit_tid":"1234-1234-1234-123", "cache-control":"no-cache, no-store", "pragma":"no-cache" }, "body":"{\"id_token\":\"<id_token>\",\"expires_in\":3600,\"token_type\":\"bearer\",\"x_refresh_token_expires_in\":8726400,\"refresh_token\":\"<refresh_token>\",\"access_token\":\"<access_token>\"}", "status":200, "statusText":"OK" }, "body":"{\"id_token\":\"<id_token>\",\"expires_in\":3600,\"token_type\":\"bearer\",\"x_refresh_token_expires_in\":8726400,\"refresh_token\":\"<refresh_token>\",\"access_token\":\"<access_token>\"}", "json":{ "access_token": "<access_token>", "refresh_token": "<refresh_token>", "token_type": "bearer", "expires_in": "3600", "x_refresh_token_expires_in": "8726400", "id_token": "<id_token>" }, "intuit_tid":"4245c696-3710-1548-d1e0-d85918e22ebe" } |
You can use the following helper methods to make full use of the Auth Response Object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | oauthClient.createToken(parseRedirect) .then(function(authResponse) { console.log('The Token in JSON is '+ JSON.stringify(authResponse.getJson())); var status = authResponse.status(); var body = authResponse.text(); var jsonResponse = authResponse.getJson(); var intuit_tid = authResponse.get_intuit_tid(); }); // remove this to next rst oauthClient.createToken(parseRedirect) .catch(function(error) { console.log(error); }); /** * This is how the Error Object Looks : { "originalMessage":"Response has an Error", "error":"invalid_grant", "error_description":"Token invalid", "intuit_tid":"4245c696-3710-1548-d1e0-d85918e22ebe" } */ |
By default the logging is disabled i.e set to false. However, to enable logging, pass the parameter logging : true when you create the oauthClient instance :
1 2 3 4 5 6 7 | var oauthClient = new OAuthClient({ clientId: '<Enter your clientId>', clientSecret: '<Enter your clientSecret>', environment: 'sandbox', redirectUri: '<http://localhost:8000/callback>', logging: true }); |
The logs would be captured under the directory /logs/oAuthClient-log.log
Whenever there is an error, the library throws an exception. You can use the below helper methods to retrieve more information:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | oauthClient.createToken(parseRedirect) .catch(function(error) { console.log(error); }); /** * This is how the Error Object Looks : { "originalMessage":"Response has an Error", "error":"invalid_grant", "error_description":"Token invalid", "intuit_tid":"4245c696-3710-1548-d1e0-d85918e22ebe" } */ |
Whenever there is an error, the library throws an exception and you can use the below helper methods to retrieve more information :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | oauthClient.createToken(parseRedirect)
.catch(function(error) {
console.error("The error message is :"+e.originalMessage);
console.error("The error description is :"+e.error_description);
});
/**
* This is how the Error Object Looks :
{
"originalMessage":"Response has an Error",
"error":"invalid_grant",
"error_description":"Token invalid",
"intuit_tid":"1234-1234-1234-123"
}
*/
|
Sometimes the error returned by QuickBooks Online may not be clear, and you would like Intuit Support to help identify the cause. If so, use the following code to record the Intuit-tid from the response, and send us this value along with the Request and Response log you recorded, so we can help
you diagnose the issue:
1 2 3 4 | oauthClient.createToken(parseRedirect)
.catch(function(error) {
console.error("The intuit-tid is :" + e.intuit_tid);
});
|