Authenticate with OAuth

Last updated on March 30, 2022

Authenticating an app with OAuth

Public and custom apps must authenticate using the OAuth 2.0 specification in order to get access to vendor data through the Bókun App API. This guide describes the OAuth process that is initiated when a vendor installs an app. Getting your app credentials First, you need to create an app to get the credentials you will use during the OAuth process:

  1. From your Partner Dashboard, click Apps > Create app.
  1. Provide an app name, app URL, and whitelist redirection URLs.
  1. Click Save. You are redirected to your app’s overview page, where you can view the API key and API secret that you will need for OAuth.

Terminology

Before we proceed with describing the authorisation process, let’s define a few key concepts used in this guide:

  • Client: Any app that wants access to a vendor’s data. A user must grant permission before the client can access any data.
  • Client credentials: The app credentials that you got above. We will refer to the API key as client_id and the API secret as client_secret.
  • API: Bókun’s GraphQL based App API, which the client can use to read and modify vendor data.
  • User: A Bókun vendor. The user gives permission to a client to access vendor data through the API.

The OAuth flow

Bókun uses OAuth 2.0 authorization code grant flow to issue access tokens on behalf of users. The process is as follows:

  1. The user clicks on a link to the app URL (as defined in the app setup in the Partner dashboard), in the Bókun app store.
  1. Bókun redirects the user to the app's URL, sending over parameters.
  1. The app redirects the user back to the Bókun app store installation confirmation page, sending over parameters including redirect_uri.
  1. The user reviews the requested permissions and terms of use, and confirms installation.
  1. Bókun redirects the user to the app’s redirect_uri (which must be a whitelisted redirect URL as specified in the app settings), sending over parameters including an access code.
  1. The app sends a request to Bókun to get the access token. The request must include the client_idclient_secret, and code.
  1. Bókun returns the access token, and the app stores it permanently for future use. The OAuth process is now complete.
  1. The client can now use the access token to make requests to the API to get to the user’s data.

So, the steps your app needs to implement for this process to work is following:

  1. Process initial request from Bokun to your app URL
      • Validate the incoming request, and redirect back to Bókun indicating what permissions your app needs and a URL to which to redirect the user once validation on Bokun side is done (the redirect URL).
  1. Process second request from Bokun: Access code
      • Validate the incoming request, get the incoming access code.
  1. Get the access token
      • Send a request to Bókun servers exchanging the access code for an access token. Store the access token safely and permanently.
  1. Make authenticated requests to the API
      • Sending the access token in a request header with every request you make

For details on what you need to implement at each step, see the following sections.

Handling incoming requests (the app URL)

When you get a request for the app URL, it indicates that one of the following happened:

  1. The user clicked the “Install” button for your app in the Bókun app store (new install).
  1. The user clicked the “Open” button for your app in the Bókun app store (already installed).

This request will only include the domaintimestamp, and hmac parameters. It will not include state or code parameters. You can use this to distinguish where you are in the OAuth process (if you get valid state and code parameters then you can move directly to Exchange access code for the access token).

The main thing to do here is to redirect them back to Bókun with information about what permissions you want to ask for.

Incoming Request

Bókun will send a GET request to the app installation URL, as specified in the app settings in the Partner Dashboard. If we assume that the app installation URL is https://example.org/some/installation/url, then the full URL called will look like this with query parameters described below.

https://example.org/some/installation/url?domain={domain}&timestamp={timestamp}&hmac={hmac}
  • {domain}: The unique domain for the vendor that is installing the app
  • {timestamp}: The full timestamp when the request was sent, as number of seconds from the epoch, in UTC timezone.
  • {hmac}: for verification, see Verification of the hmac parameter.

Outgoing Response

Redirect the user to the Bókun authorisation URL, using the query parameters described below.

https://{domain}.bokun.io/appstore/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}&state={nonce}
  • {domain}: The unique vendor domain.
  • {api_key}: The app’s API key.
  • {scopes}: A comma-separated list of scopes, or permissions that the app is asking for. See API access scopes
  • {redirect_uri}: The URL to which the user is redirected after authorising the client. The complete URL specified here must be added to your app as a whitelisted redirection URL, as defined in the app settings in the Partner Dashboard.
  • {nonce}: A random value provided by your app that is unique for each authorisation request. During the OAuth callback, your app must check that this value matches the one you provided during authorization. This mechanism is important for the security of your app.

Verification of the hmac parameter

Every request or redirect from Bókun to the client server includes an hmac parameter that can be used to verify the authenticity of the request from Bókun. For each request, you must remove the hmac entry from the query string and process it through an HMAC-SHA256 hash function.

By way of example, consider the following query string:

"code=12345&hmac=123abc456def&domain=mytours&state=98765&timestamp=1337178173"

To remove the hmac, you can transform the query string to a map, remove the hmac key-value pair, and then lexicographically (in alphabetic order) concatenate your map back to a query string. This leaves the remaining parameters from the example query string:

"code=12345&domain=mytours&state=98765&timestamp=1337178173"

Next, you process the string through an HMAC-SHA256 hash function using the app API secret key (client_secret). The message is authentic if the generated hexdigest is equal to the value of the hmac parameter.

Handling access code requests (the redirect URL)

When you get a request for the URL you specified as redirect_uri in the earlier step, it means that Bokun has confirmed that the user has given your app the requested permissions.

Incoming Request

Bókun will send a GET request to the URL you specified in redirect_uri. If we assume that the URL is https://example.org/some/redirect/uri, then the full URL called will look like this with the query parameters described below.

https://example.org/some/redirect/uri?domain={domain}&state={nonce}&timestamp={timestamp}&hmac={hmac}&code={authorization_code}
  • {domain}: The unique domain for the vendor that is installing the app.
  • {nonce}: The same one that your app provided to Bókun in the previous step.
  • {timestamp}: The full timestamp when the request was sent, as number of seconds from the epoch, in UTC timezone.
  • {authorization_code}: The code you will use to get the access token in the final step.

Before you continue, make sure your app performs the following security checks.

  1. Make sure the nonce matches.
  1. Make sure the hmac is valid (see Verification of the hmac parameter).

If any of the checks fails, your app must reject the request with an error, and must not continue.

Exchange access code for the access token

If all security checks pass, then you can exchange the access code for a permanent access token by sending a POST request to the vendor’s access_token endpoint:

POST https://{domain}.bokun.io/appstore/oauth/access_token

In your request, {domain} is the vendor’s unique domain and the following parameters must be posted in the request body:

  • {client_id}: The API key for the app, as defined in the Partner Dashboard.
  • {client_secret}: The API secret key for the app, as defined in the Partner Dashboard.
  • {code}: The authorisation code provided in the redirect.

The server then responds with your access token, along with the confirmed access scopes:

{
  "access_token": "abcdef123456789fedcba",
  "scope": "PRODUCTS_MANAGE,BOOKINGS_CREATE",
  "vendor_id": "abc123"
}

A description of the fields is as follows:

  • access_token : The permanent access token that you can use for all future API requests. Your app needs to store this in a secure location, for example in a relational database.
  • scope: The permissions or access scopes granted to you by the user.
  • vendor_id: The unique identifier of the vendor that installed the app. It is a good idea to store this with the access token, since the domain may change but the vendor_id will never change.

The API access token can be used to access the vendor’s data as long as the client is installed. Clients should store the token somewhere to make authenticated requests for a vendor’s data.

Making authenticated requests to the API

After the client has obtained an API access token, it can make authenticated requests to the API. These requests should contain the following header:

  X-Bokun-App-Access-Token: {access_token}

where {access_token} is replaced with the permanent access token you received at the end of the OAuth process.

URL for the requests is:

https://{domain}.bokun.io/api/graphql

Updating the OAuth access scopes

What happens if you need further permissions / access scopes after the user has installed your app (for example, you might want to request additional scopes if your integration requires access to other API endpoints)?

No problem. Simply redirect your user to the Bókun authorisation URL, including the new list of scopes your app needs:

https://{domain}.bokun.io/appstore/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={redirect_uri}&state={nonce}

If the user grants the requested access, we will redirect back with a new access code which you can exchange for a new access token.

 
Did this answer your question?
😞
😐
🤩