Implement single sign-on with OpenID Connect

This document explains how to implement Intuit single sign-on using Intuit's OAuth 2.0 authentication implementation, which conforms to the OpenID Connect specification and is OpenID Certified.  To explore this workflow interactively, experiment with the OAuth 2.0 playground

If you plan to publish your app on the QuickBooks app store, visit this section for additional implementation details once you have OpenID Connect in place.

These sections take you through the workflow in detail:

Note

As of July 17, 2017, new or existing developers with no previous apps must implement OAuth 2.0. Click here for OAuth 1.0a documentation, available as a reference for existing applications. 

OpenIdConnectFlow.png

Note
  • Only the Master Administrator or a Company Administrator can authorize access to a QuickBooks company.

Prerequisites

  • Create an Intuit Developer account and app: You must have an Intuit Developer account and have created an app within that account. The app serves as a container for the OAuth workflow.
  • Get client keys: Obtain OAuth 2.0 client keys from your app's dashboard on developer.intuit.com.  To locate the app's dashboard, sign in to developer.intuit.com and click My Apps. Find and open the app you want. From here, click the Keys tab. There are two versions of this key:
    • Development keys—use only in the sandbox environment.
    • Production keys—use only in the production environment. 
  • Define redirect URIs: On the app setting page, create one or more redirect URIs. These URIs handle responses from the OAuth 2.0 server and are called after the user authorizes the connection. URIs in this list are the only ones to which the authorization response can be sent from the OAuth 2.0 server.   You must define at least one URI specifically for your application's auth endpoint before you can use OAuth 2.0. For the sandbox environment, this list can include http://localhost. As a best practice, design your app's auth endpoints in a way that doesn't expose authorization codes to other resources on the page.

Sample code

Initiating the authentication request

Making the request

Initiate the OpenID Connect authentication process by redirecting the user to Intuit's OAuth 2.0 server. Retrieve the base URI from the discovery document using the key, authorization_endpoint. The discussion here assumes the base URI is:

 GET https://appcenter.intuit.com/connect/oauth2

This endpoint is accessible over https; plain http connections are refused. Ensure query parameter values are always URL encoded. The set of query  parameters supported by the Intuit OAuth server include:

ParameterValuesDescription
client_idThe client ID you obtain from the developer dashboard.

Required.Identifies which app is making the request. Obtain this value from the Keys tab on the app profile via My Apps on the developer site. There are two versions of this key:

  • Development key—use only in the sandbox environment.
  • Production key—use only in the production environment. 
scopeSpace-delimited set of permissions that the application requests.

Required. Identifies the user information that your application is requesting. The values passed in this parameter inform the consent screen that is shown to the user.  

OpenID Connect authentication scopes:

  • openid—OpenID Connect processing
  • profile—user's given and family names
  • email—user's email address
  • phone—user's phone number
  • address—user's physical address

It is generally a best practice to request scopes incrementally, at the time access is required, rather than up front; see Incremental authorization. The phone and address values are taken from the user's QuickBooks profile.

Additionally, when implementing Intuit single sign-on from the app store, specify one or both of these scopes to authorize your app's access to your user's QuickBooks company :

  • com.intuit.quickbooks.accounting—QuickBooks Accounting API

  • com.intuit.quickbooks.payment—QuickBooks Payments API

redirect_uriOne of the 
redirect URI
values listed for this app in the developer dashboard.
Required. Determines where the response is sent. The value of this parameter must exactly match one of the values listed for this app in the app settings. This includes the https scheme, the same case, and the trailing '/'. For the sandbox environment, this list can include http://localhost (do not use HTTPS in this case). IP addresses are allowed for redirect URIs.
response_typecodeRequired. Determines whether the Intuit OAuth 2.0 endpoint returns an authorization code. Always set this to code.
stateAny stringRequired. Provides any state that might be useful to your application upon receipt of the response. The Intuit Authorization Server roundtrips this parameter, so your application receives the same value it sent. To mitigate against cross-site request forgery (CSRF), it is strongly recommended to include an anti-forgery token in the state, and confirm it in the response. See About anti-forgery state tokens.

Here is an example of a complete OpenID Connect authentication URI specifying openid and email scopes, with line breaks and spaces for readability:

GET https://appcenter.intuit.com/connect/oauth2?
 client_id=Q3ylJatCvnkYqVKLmkH1zWlNzNWB5CkYB36b5mws7HkKUEv9aI&
 response_type=code&
 scope=openid%20email&
 redirect_uri=https://www.mydemoapp.com/oauth-redirect&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps://www.mydemoapp.com/oauth-redirect&

Users are required to give consent if your app requests account access that they have not previously approved or if your app requests any new information about them. Here is a sample consent dialog the user is presented when all the OpenID scopes—openid, profile, email, phone, address—are specified:

Handling the response

The response is sent to the redirect_uri that you specified in the request. All responses are returned in the query string, as shown below:

https://www.mydemoapp.com/oauth-redirect?state=security_token%3D138r5719ru3e1%26url
%3Dhttps://www.mydemoapp.com/oauth-redirect&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7
  • Note the authorization code returned in the code query parameter. You use it later in the flow.
  • Confirm that the state received from Intuit matches the state token you sent in the authentication request. This round-trip verification helps to ensure that the user, not a malicious script, is making the request.

Error responses

Certain error conditions trigger the single query parameter, error=, to be sent to the redirect URI.

Error responseDescription
access_deniedThe user did not authorize the request.
invalid_scopeAn invalid scope string was sent in the request.
 

Exchange code for access token and ID token

Making the request

After the app receives the authorization code, it exchanges the authorization code for an access token. Retrieve the base URI from the discovery document using the key, token_endpoint. The discussion here assumes the base URI is:

POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer 

This endpoint is accessible over https; plain http connections are refused.

FieldDescription
codeRequired. The authorization code returned from the initial request.
redirect_uriRequired. One of the redirect URIs listed for this project in the developer dashboard.
grant_typeRequired. As defined in the OAuth 2.0 specification, this field must contain a value of authorization_code.

The actual request might look like the following:

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
Generating the authorization header

Calculate the authorization header value as follows:

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

where client_id and client_secret are located on the Keys the tab on the app profile via My Apps on the developer site. There are two versions of these keys:

  • Development keys—use only in the sandbox environment.
  • Production keys—use only in the production environment. 

Handling the response

A successful response to this request contains the following fields:

FieldDescription
access_tokenThe token that must be used to access the QuickBooks API.
refresh_tokenThe token used when refreshing the access token

x_refresh_token_
expires_in

The remaining lifetime, in seconds, for the connection, after which time the user must re-grant access. See refresh_token policy for details.
expires_inThe remaining lifetime of the access token in seconds. The value always returned is 3600 seconds (one hour). Use the refresh token to get a fresh one. See Using a refresh token for further information.   
token_typeIdentifies the type of token returned. At this time, this field will always have the value Bearer.
id_tokenReturned for openid and associated user scopes for user authentication.

 

A successful response is returned as a JSON array, similar to the following (this response includes an id_token, as seen for openid and associated scopes):

{ 
"token_type": "bearer", 
"expires_in": 3600, 
"refresh_token":"L311478109728uVoOkDSUCl4s8FDRvjHR6kUKz0RHe3WtZQuBq",
"x_refresh_token_expires_in":15552000,
"access_token":"eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiZGlyIn0..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",
"id_token":"eyJraWQiOiJyNHA1U2JMMnFhRmVoRnpoajhnSSIsImFsZyI6IlJTMjU2In0.eyJzd
WIiOiJiMDUzZDk5NC0wN2Q1LTQ2OGQtYjdlZS0yMmUzNDlkMmU3MzkiLCJhdWQiOlsiTDM5ZWxTdWJGeGpQT1
NwZFpvWVdSS2lDQ0U2VElOanY2N1JvYUU4ekJxYkl4eGI0bEsiXSwicmVhbG1pZCI6IjExMDgwMzM0Nz
EiLCJhdXRoX3RpbWUiOjE0NjI1NTQ0NzUsImlzcyI6Imh0dHBzOlwvXC9vYXV0aC1lMmUucGxhdGZvcm
0uaW50dWl0LmNvbVwvb2F1dGgyXC92MVwvb3BcL3YxIiwiZXhwIjoxNDYyNTYxMzI4LCJpYXQiOjE0NjI1
NTc3Mjh9.BIJ9x_WPEOZsLJfQE3mGji_Q15j_rdlTyFYELiJM-W92fWSLC-TLEwCp5IrRhDWMvyvrLSMZCEd
QALYQpbVy8uKI22JgGWYvkwNEDweOjbYzyt33F4xtn3GGcW9nAwRtA3M19qquWyi7G0kcCZUDN8RfUXz2qKM
J6KPOfLVe2UQ"
}
Note

Other fields may be included in the response, and your application should not treat this as an error. The set shown above is the minimum set.

Adding the Sign in with Intuit button 

To enable your user to sign into your app with their Intuit user ID (email) and password, provide the Sign in with Intuit button in your app. Upon clicking this button, the browser is redirected to the Intuit App Center sign-in window, which prompts the user to log in with their Intuit user ID (email) and password. If you're implementing modified single sign-on, adding this button is optional.

Validating the ID token

An ID Token is a JWT (JSON web token); that is, a cryptographically signed Base64-encoded JSON object. Normally, it is critical that you validate an ID token before you use it, but since you are communicating directly with Intuit over an intermediary-free HTTPS channel and using your client secret to authenticate yourself to Intuit, you can be confident that the token you receive really comes from Intuit and is valid. As a best practice, validating the ID Token is recommended.

Since most API libraries combine the validation with the work of decoding the base64 and parsing the JSON, you probably end up validating the token anyway as you access the fields in the ID token. Here are the validation steps to perform.

Validation steps

Verify the following from the ID token obtained in the last step.

  • The value of iss in the payload section is https://oauth.platform.intuit.com/op/v1.
  • The value of aud in the payload section matches your app's client id, located on Keys tab of your app's dashboard on developer.intuit.com. Keep in mind there are two versions, based on your development stage:
    • Development client ID—found on the Development tab, use only in the sandbox environment.
    • Production client ID—found on the Production tab, use only in the production environment.
  • The expiry time, in the exp field, in the payload sections has not passed.
  • The signature is properly signed by the issuer.
    • Scan through the array of keys at oauth.platform.intuit.com/op/v1/jwks for the public key information whose kid value matches that returned in the ID token header.
    • Use the exponent, e field,  and modulo, m field, values to create the public key and to validate the signature.

JSON web token information

A JSON Web Token consists of three parts separated by dots:

  • Header
  • Payload
  • Signature
Header

The header consists of two parts:

  • kid—the key id of the key used to sign the payload
  • alg—the hashing algorithm being used, such as HMAC SHA256 or RSA

Then, this JSON is Base64Url encoded to form the first part of the JWT. Here is an example:

{
    kid: "r4p5SbL2qaFehFzhj8gI",
    alg: "RS256"
}
Payload

The second part of the token is the payload, which contains the claims. Claims are metadata about the user. Intuit ID tokens contain the following fields:

ClaimDescription
audIdentifies the audience that this ID token is intended for. It must be the OAuth 2.0 client ID of your application.
auth_timeThe time the ID token was authorized.
expThe time the ID token expires, represented in Unix time (integer seconds).
iatThe time the ID token was issued, represented in Unix time (integer seconds).
issThe issuer identifier for the issuer of the response. This is always set to https://oauth.platform.intuit.com/op/v1.
subAn identifier for the user, unique among all Intuit accounts and never reused. An Intuit account can have multiple emails at different points in time, but the sub value is never changed. Use sub within your application as the unique-identifier key for the user.

Here’s an example, formatted for readability:

{
  "sub": "1182d6ec-2a1f-4aa3-af3f-bb3b95db45af",
  "aud": [
    "L3Y7SV6rRxVvArdYzlRxjPXo0b6ItrX4qFhopPXQ6aaEWgKyCa"
  ],
  "realmid": "123145880168382",
  "auth_time": 1464330769,
  "iss": "https://oauth.platform.intuit.com/op/v1",
  "exp": 1464335838,
  "iat": 1464332238
}
Signature

The signature is used to verify that the sender of the JWT is who it says it is and used to ensure that the message wasn't changed along the way. To create the signature, sign a concatenation of the encoded header, the encoded payload, and a secret with the specified algorithm.  For example, if you use the HMAC SHA256 algorithm, the signature is created in the following way:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

Obtaining user information

In addition to the information in the ID token, you can get additional user profile information at Intuit's user profile endpoint. Retrieve the base URI from the discovery document using the key, userinfo_endpoint. The discussion here assumes the base URI is:

GET https://accounts.platform.intuit.com/v1/openid_connect/userinfo

The actual request might look like the following:

GET https://accounts.platform.intuit.com/v1/openid_connect/userinfo
Accept: application/json
Authorization: Bearer <access token>

 The response depends on scopes requested during the initial access token request. Here is a sample where scopes specified are openid, email, and profile:

{
  "sub": "1182d6ec-2a1f-4aa3-af3f-bb3b95db45af",
  "email": "john@doe.com",
  "emailVerified": true,
  "givenName": "John",
  "familyName": "Doe"
}

Here is a sample response where all openid  scopes—openid, profile, email, phone, address—are specified.

{
    "sub": "1182d6ec-2a1f-4aa3-af3f-bb3b95db45af",
    "email": "john@doe.com",
    "emailVerified": true,
    "givenName": "John",
    "familyName": "Doe",
    "phoneNumber": "+1 6305555555",
    "phoneNumberVerified": false,
    "address": {
        "streetAddress": "2007 saint julien ct",
        "locality": "mountain view",
        "region": "CA",
        "postalCode": "94043",
        "country": "US"
    }
}

After obtaining user information, query your app's user database.

  • If the user already exists in your database, initiate an application session for that user.
  • If the user does not exist in your user database, redirect the user to your new-user, sign-up flow. You may be able to auto-register the user based on the information you receive from intuit, or at the very least you may be able to pre-populate many of the fields that you require on your registration form.

Refreshing the 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. 

refresh_token policy

The refresh_token policy specifies lifetime and expiry details of the refresh_token. Of note:

  • The lifetime for the refresh_token returned with the initial access_token is set to at least 100 days.
  • Each time a new access_token is requested, the refresh_token is reset to a new lifetime of at least 100 days.
  • If an access_token is not requested during the current refresh_token 100 day lifetime, the refresh_token expires and access to the QuickBooks company terminates. 
  • As long as it hasn't expired, the refresh_token can be reset as often as needed within a one year access window from the time the original access_token was generated.
  • If the user revokes the connection to the QuickBooks company, the refresh_token is revoked and is no longer valid. 

Access to the QuickBooks company terminates when the current refresh_token expires or at the end of the one year access window from the time the original access_token was generated, whichever is earlier. When access terminates, your app must ask the user to reauthorize the connection. 

Best practices
  • Always use the refresh token returned in the last token_endpoint response in your request for a fresh access token. 
  • The time to request a new access_token is when a QuickBooks API call returns a 401 error.

If you use an expired refresh token, you get the following response:

{ 
    "error": "invalid_grant" 
}

Making the request

Retrieve the base URI for the request from the discovery document using the key, token_endpoint. The discussion here assumes the base URI is:

POST https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer 

This endpoint is accessible over https; plain http connections are refused.

FieldDescription
grant_typeRequired. When requesting a refresh token, set this to refresh_token.
refresh_tokenRequired. The refresh token returned in the last access token response.

The actual request might look like the following:

POST /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
Cache-Control: no-cache
Body: grant_type=refresh_token&
refresh_token=Q311488394272qbajGfLBwGmVsbF6VoNpUKaIO5oL49aXLVJUB

Handling the response

A successful response to this request contains the following fields:

FieldDescription
access_tokenThe token that must be used to access the QuickBooks API. The previous token is invalidated.
expires_inThe remaining lifetime of the access token in seconds. The value always returned is 3600 seconds (one hour). Use the refresh token to get a fresh one. See Refreshing the access token for further information.   
refresh_token

A token used to obtain a new access token. All previous refresh tokens are stale and unusable.

token_typeIdentifies the type of token returned. At this time, this field will always have the value Bearer.
x_refresh_token_
expires_in
The remaining lifetime, in seconds, for the connection, after which time the user must re-grant access. See refresh_token policy for details.

A successful response is returned as a JSON array, similar to the following:

{ 
"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",
"id_token":"eyJraWQiOiJyNHA1U2JMMnFhRmVoRnpoajhnSSIsImFsZyI6IlJTMjU2In0.eyJzd
WIiOiJiMDUzZDk5NC0wN2Q1LTQ2OGQtYjdlZS0yMmUzNDlkMmU3MzkiLCJhdWQiOlsiTDM5ZWxTdWJGeGpQT1
NwZFpvWVdSS2lDQ0U2VElOanY2N1JvYUU4ekJxYkl4eGI0bEsiXSwicmVhbG1pZCI6IjExMDgwMzM0Nz
EiLCJhdXRoX3RpbWUiOjE0NjI1NTQ0NzUsImlzcyI6Imh0dHBzOlwvXC9vYXV0aC1lMmUucGxhdGZvcm
0uaW50dWl0LmNvbVwvb2F1dGgyXC92MVwvb3BcL3YxIiwiZXhwIjoxNDYyNTYxMzI4LCJpYXQiOjE0NjI1
NTc3Mjh9.BIJ9x_WPEOZsLJfQE3mGji_Q15j_rdlTyFYELiJM-W92fWSLC-TLEwCp5IrRhDWMvyvrLSMZCEd
QALYQpbVy8uKI22JgGWYvkwNEDweOjbYzyt33F4xtn3GGcW9nAwRtA3M19qquWyi7G0kcCZUDN8RfUXz2qKM
J6KPOfLVe2UQ"
}

Incremental authorization

We recommend requesting scopes as needed. It is generally a best practice to request scopes incrementally, at the time access is required, rather than up front. Each time you change the set of scopes you must initiate the authorization workflow again with the new list of scopes and you must get new access and refresh tokens. 

When adding scopes to your authorization, you must send the full complement of scopes you need at that point in your app. For example, an app that wants to support purchases should not request QuickBooks Payments API access until the user presses the Buy button. That is, in the request for a new authorization code you add com.intuit.quickbooks.payment to your list of existing scopes.

About anti-forgery state tokens

You must protect the security of your users by preventing request forgery attacks. The first step is creating a unique session token that holds state between your app and the user's client. You later match this unique session token with the authentication response returned by the Intuit OAuth Login service to verify that the user is making the request and not a malicious attacker. These tokens are often referred to as cross-site request forgery (CSRF) tokens.

One good choice for a state token is a string of 30 or so characters constructed using a high-quality random-number generator. Another is a hash generated by signing some of your session state variables with a key that is kept secret on your back-end.

Revoking access

Your app can programmatically revoke access given to it by a specific user. Use the revoke endpoint to request permissions granted to the application to be removed. 

Making the request

Retrieve the base URI for the revoke endpoint from the discovery document using the key, token_endpoint. The discussion here assumes the base URI is:

POST https://developer.api/intuit.com/v2/oauth2/tokens/revoke

 The actual request might look like the following:

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}"
}

Generating the authorization header 

Calculate the authorization header value as follows:

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

where client_id and client_secret are located on the Keys the tab on the app profile via My Apps on the developer site. There are two versions of these keys:

  • Development keys—use only in the sandbox environment.
  • Production keys—use only in the production environment.

Handling the response

This request returns and empty response body and one of the following status codes:

CodeDescription
200Successful revoke.
400One or more of BearerToken, RefreshToken, ClientId or,ClientSecret are incorrect.
401Bad authorization header or no authorization header sent.
500Intuit server internal error, not the fault of the developer.

Single sign-on models 

Intuit Developer supports two models of Intuit single sign-on, standard and modified, as described below.

Standard single sign-on 

With this model your application is required to implement OpenID Connect in order to allow the customer signing up for your application from the QuickBooks app store to sign in directly to your application without being prompted to create a new account or password on your site. The customer signs in only once with their Intuit credentials.

In this model it is mandatory to add the Sign in with Intuit button on all of your sign-in pages. 

Because this flow is easy for customers, it results in more paid customers signing up for your app. We recommend this flow unless you have a very good reason to use the Modified option.

Modified single sign-on 

With this model you still implement OpenID Connect, but your application can let a customer create an account on your site for your app’s use. Subsequent sign-ins from the QuickBooks app store honor the OpenID Connect credentials from Intuit and sign the user directly in to your application.

This modified model makes adding the Sign in with Intuit button to your sign-in pages optional.

Use modified Intuit single sign-on if your customers really need to create an identity and password on your site. For example, they need to sign in to your mobile or tablet app.

Which model is right for your app? 

When considering which Intuit single sign-on model to implement, consider how your users interact with your app.  With the Sign in with Intuit button, the user only has to sign in once, instead of having to sign in to both your app and to the QuickBooks app store. The Sign in with Intuit button is optional with the modified single sign-on model. Here are some use cases for including it in your app:

  • You can create user accounts without an independent username and password in your system when the user's account is created through the Get App Now flow.  In particular for mobile apps, this approach is not recommended. 
  • All your users typically have an Intuit account for an accountant-facing application.
  • Your users spend most of their day in QuickBooks Online, so having the Sign in with Intuit button saves them from having to login again.

Discovery document

The OpenID Connect protocol requires the use of multiple endpoints for authenticating users, and for requesting resources including tokens, user information, and public keys.

To simplify the implementation and increase flexibility, OpenID Connect allows the use of a discovery document, a JSON document found at a well known location containing key-value pairs that provide details about the OpenID Connect configuration, including the URIs of the authorization, token, userinfo, and public-keys endpoints. The discovery document for Intuit's OpenID Connect service is located here:

Here is an example of a discovery document; the field names are those specified in OpenID Connect Discovery 1.0 (refer to that document for their meanings). The values here are illustrative, although they are copied from from a recent version of the actual Intuit discover document, they may have changed. Always refer to the actual document for up-to-date information.

{ 
   issuer:"https://oauth.platform.intuit.com/op/v1",
   authorization_endpoint:"https://appcenter.intuit.com/connect/oauth2",
   token_endpoint:"https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer",
   userinfo_endpoint:"https://accounts.intuit.com/v1/openid_connect/userinfo",
   revocation_endpoint:"https://developer.api.intuit.com/v2/oauth2/tokens/revoke",
   jwks_uri:"https://oauth.platform.intuit.com/op/v1/jwks",
   response_types_supported:[ 
      "code"
   ],
   subject_types_supported:[ 
      "public"
   ],
   id_token_signing_alg_values_supported:[ 
      "RS256"
   ],
   scopes_supported:[ 
      "openid",
      "email",
      "profile",
      "address",
      "phone"
   ],
   token_endpoint_auth_methods_supported:[ 
      "client_secret_post",
      "client_secret_basic"
   ],
   claims_supported:[ 
      "aud",
      "exp",
      "iat",
      "iss",
      "realmid",
      "sub"
   ]
}

 Got Questions? Get Answers in our developer forums.