Getting Started with OAuth 2.0 and the Kashoo API

This article contains some helpful tips for third party developers to get started with the Kashoo OAuth 2.0 provider and API.

Written by Amrik Randhawa Updated over a week ago

Getting started

Registration

You must register your client app/service with the Kashoo OAuth 2.0 provider before it can access the Kashoo API. Please supply the following information to api@kashoo.com:

A brief description of the app/service and how it will be integrated with Kashoo. Include a URL to your app/service's web site.

The full name of the app/service that you would like to be displayed to users when they are asked to authorize access. For example, if you choose "My Great App", the user will see a message similar to "The app My Great App is requesting permission to view/modify your Kashoo businesses." Be specific; there should be no ambiguity about which app is asking for authorization.

The URL to which we can redirect users after they have granted/denied your app/service access to Kashoo (aka a redirection endpoint). The production and staging redirect URLs must be protected by SSL/TLS, though the staging endpoint may optionally use a self-signed certificate if necessary. And, for the sake of developer convenience, the development redirect URL may point to "localhost" without using SSL/TLS. If any of the endpoints aren't implemented yet, you can give us placeholder URLs as long as they point to domains you control. Keep in mind that, when your client app actually begins to use the Kashoo OAuth 2.0 provider, the redirect URL must exactly match what you provide to us now. So, if you register "https://foo.bar/" now and then attempt to use "https://foo.bar/baz" later, the authorization attempt will be automatically rejected. For more information on what to expect from an authorization redirection, see Authorization Code - Authorization Response.

Client app credentials

Each client app/service is issued its own unique credentials to authenticate with the Kashoo OAuth 2.0 provider. Credentials consist of a client ID and client secret:

Client ID: A unique identifier for each client application. Assume that this ID can be seen by the whole world; there is no need to try to keep it confidential.

Client secret: A random, secret key that is used to authenticate each client application. A secret consists of a long sequence of ASCII upper and lowercase letters, digits, underscores (_) and hyphens (-) only. It is critical that the client secret be kept confidential to protect users from fraudulent/malicious activity. Any accidental exposure of a client secret should be reported to Kashoo as soon as possible so it can be revoked and a new secret can be issued in its place.

Grant types

The Kashoo OAuth 2.0 provider supports the authorization code and implicit grant types for third party API clients:

Authorization code grant: The most common and most versatile grant type for client apps. Should be used by server-side applications that need temporary or ongoing access to a user's Kashoo businesses.

Implicit grant: This grant type is useful in a very limited set of circumstances. Since it is incapable of issuing refresh tokens, the primary use case is for an app that runs purely in the user agent (e.g. browser) and needs a single-use access token.

Auth endpoints

There are a pair of Kashoo endpoints that are involved in the OAuth 2.0 authentication and authorization process:

Authorization codes

An authorization code is issued when a Kashoo user grants access to their businesses. As suggested by the official spec, each auth code will be valid for no more than 10 minutes and may be exchanged one time only for an access token and refresh token. For security reasons, multiple attempts to exchange the same auth code will invalidate the auth code and all access tokens and refresh tokens already issued for that client grant.

Scopes

The Kashoo OAuth 2.0 provider currently ignores any access token scope explicitly requested by a client app. If the user agrees to grant permission to a third party app, the resulting token will include the "full-access" scope, which implies full read and write access to all of the user's businesses (assuming they have read and write privileges, that is).

Future versions of the Kashoo OAuth 2.0 provider may include capabilities for finer grained control over client app scope. If so, they will be implemented in a backward-compatible manner.

Token expiration

An access token issued for any grant type will last no more than one hour. However, you should make no assumptions about how long a token will last; instead, rely only on the "expires_in" parameter to determine for how many seconds it is valid.

If using a grant type that supports refreshing a token (e.g. authorization code grant), then a successful grant will also include a refresh token in its response. Each refresh token is long lived (though they are not guaranteed to last forever) and may be exchanged one time only for a new access token and refresh token. For security reasons, multiple attempts to exchange the same refresh token will invalidate all access tokens and refresh tokens already issued for that client grant.

Use the token endpoint, as listed in the Auth endpoints section, to refresh an expired access token.

Logout

When a user decides to terminate your client app/service's authorization for their Kashoo businesses, your app/service should explicitly end the client grant. Post the user's current access token, via the "accessToken" JSON property, to the logout endpoint at https://api.kashoo.com/oauth2/api/logout to revoke all access tokens and refresh tokens that have been issued to your client app/service for that user. For example:

Cross-site request forgery protection

To protect your users against cross-site request forgeries (CSRF), the official OAuth 2.0 spec strongly recommends that client apps include a state token parameter whenever sending a user to the authorization endpoint (https://api.kashoo.com/oauth2/authorize). If a state token is provided in such a manner, then after choosing to grant or deny access, the user will be sent to your client app/service's redirect URL with the original state token included in the query string. Your client app/service can then verify that the current user is the same one that initiated the authorization request by examining the state token.

For security reasons the Kashoo OAuth 2.0 provider does not allow custom query string parameters for storing application state in the redirect URL of client app authorization requests. Instead, you can use the state token as an internal identifier for application state that is preserved and restored when the user returns to your client app/service after authorizing a client grant. For example, if you wanted to return the user to the page they were viewing when the client grant request was initiated, you would create a record in your client app's data store with the state token as the key/ID and the page name as a field in the record. It may be tempting to encode the application's state directly into the content of the state token itself, but this is no better than using no CSRF protection at all; in fact, depending on what info was included in the application state, it could be even more harmful to the user, so just don't do it.

The state token itself must be an unpredictable value; ideally a long random string of characters. For example, generate a random and secure UUID or a hash of the user's session ID.

If your client app/service does not use the state token parameter, then it MUST implement some other mechanism to protect against CSRF.

Kashoo API

The Kashoo API is documented at api.kashoo.com. Of particular interest may be the /users/me/businesses endpoint to retrieve a list of the user's businesses and the various endpoints below /businesses/{business_id} to create, read, update and delete resources that belong to a business (e.g. accounts, expenses, invoices, contacts). To determine the privileges available to a user for a particular business, see the "privileges" property of the business element in question.

The Kashoo OAuth 2.0 provider issues bearer tokens, which can be included without any additional credentials via the "Authorization" header in requests to the Kashoo API. For example:

If a token has expired or is otherwise invalid, the Kashoo API will return an HTTP 401 Unauthorized status response. If the client app used an authorization code grant, it can then exchange its refresh token for a new access token and try the API request again. Remember that each refresh token may only be exchanged once.

Authorization errors

This section describes the auth error responses you may encounter when integrating with Kashoo's API. The listings below contain the most common error cases, but they may not be comprehensive. If you encounter an error that is not detailed here, please contact answers@kashoo.com for help.

Regardless of client grant type, when a user chooses to deny access to your app, you can expect their user agent (e.g. web browser) to be redirected to your redirect URL with an "error" parameter value of "access_denied". More info and examples are available in the official OAuth 2.0 spec for authorization code and implicit grants.

Following are the errors you may encounter when attempting to exchange an authorization code for an access token via the "POST /oauth2/token" endpoint. The "Error code" column refers to the value of the "error" field from the JSON response. More info is available in the official OAuth 2.0 spec's Error Response section.

The errors you may encounter when refreshing an access token via the "POST /oauth2/token" endpoint:

These are the auth errors you may encounter when a request to a protected Kashoo API endpoint is rejected. The "Error code" column refers to the value of the "error" field of the response's "WWW-Authenticate" header. More info can be found in the official OAuth 2.0 Bearer Token spec's WWW-Authenticate Response Header Field section.