OAuth 2.0 - Authorization code grant flow

The Authorization Code Flow is the most secure and preferred method to authenticate users via OpenID Connect. The authorization grant is defined in detail in RFC6749 sec-4.1. This grant requires the user to explicitly authenticate themselves and authorize the application initiating the grant.

From a hotel user’s view, it looks like this:

In this flow, protected resources that a client app requests belong to an end user (resource owner). Browsers that could expose protected resources to third-parties do not receive access tokens. Instead, they receive an authorization code that on its own does not provide direct access to protected resources.

You just need to follow a two-step process in order to get a new access token.

  • In the first part of the process (steps 1 - 4) you will send the user to the identity server to give consent to the app. Afterwards, the identity server will redirect the user back to your app using the configured redirect uri. This is where you will get your authorization code.

  • In the second part of the process (steps 5 and 6) you will make a request to the identity server with your authorization code. To which it will respond with your access and refresh tokens.

  • Here’s how the app uses the token to request resources (steps 7 and 8) from the resource server.

    We will go more into detail for each step a bit later in the topic.


Create a client app and get client credentials

After creating an apaleo developer account, the next step to create your app is to register it at My store apps in apaleo.

The registration process involves providing basic details of your app like redirect URIs and the scopes that you require for the endpoints that you want to access.

If you need to make some changes to your client, you can edit it at any point in the future. The registration process is not considered as a part of the authorization flow.

To learn how to create your client, go to Register the OAuth connect client application.

Before you start the OAuth flow, you need to prepare a few things. Here’s what you need to do.

The purpose of this step is to obtain consent from the user to invoke the API to do certain things (specified in ‘scope’) on behalf of the user.

To begin the authorization code flow, your app should first send the user to the consent screen: openid profile

This URL performs the following things:

  • It displays a consent screen to the user with the requested scopes.

  • Once the user authorizes the request, they are redirected to your specified redirect_uri.

    After the user accepts or denies your request, the apaleo identity API redirects the user back to your redirect_uri.

Note: Calling the authorize URL opens the consent screen. When you are asked to log in, use the apaleo credentials, not your client ID and client secret.

Key Description
response_type Indicates the kind of credential that apaleo will return (code vs. token). For this flow, the value must be code.
scope The scopes for which you want to request authorization. These must be separated by a space. For example, to create reservations and get the list of properties use scope=reservations.create </br>Note: If you using OpenID Connect library, then the request must include the openid scope in the scope parameter.
client_id The apaleo generated Client ID for your connect app.
redirect_uri The URL to which apaleo will redirect the browser after the user has granted authorization. The authorization code will be included here, in the code URL parameter. It must match one of the Redirect URIs you specified when registering your client app.
state A randomly generated value provided by your application, which is unique for each authorization request. During the OAuth call-back phase, your application must check that this value matches the one you provided during authorization. This mechanism is essential for the security of your application.

If the user approves the access request, the response contains an authorization code and the state parameter (if included in the request). The response query string is as follows:
Query Parameter Value
code An authorization code that can be exchanged for an access token. Note that codes are single use only, so cannot be reused.
state The value of the state parameter supplied in the request.
session_state The session_state value contains a salted cryptographic hash of Client ID, origin URL, and OpenID Provider’s browser state.

If the user does not approve the request, the response contains an error message. The response query string is as follows:
Query Parameter Value
error The reason it failed, for example: “errorId”.

Step 2. Exchange the authorization code for an access token

Now that you have an authorization code, you must exchange it for an access token that can be used to call apaleo API. Using the authorization code (code) from the previous step, you will need to POST to the token URL.

Content-Type: application/x-www-form-urlencoded

Example cURL request

You can test the creation of token by running the following cURL command.

Note: On Windows, use Windows Subsystem for Linux (WSL) to run the cURL command.

curl -X POST \ \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'client_id=SDXE-AC-MYAPP&client_secret=ZiEWFgFeSP......5yhTgsZgx&grant_type=authorization_code&code=NqS......kGey6Jc&redirect_uri='
Key Description
client_id The apaleo generated Client ID for your connect app.
client_secret The apaleo generated Client Secret for your connect app.
code The authorization code received from the initial authorize call.
redirect_uri This parameter is used for validation only (there is no actual redirection). The value of this parameter must exactly match the value of redirect_uri supplied when requesting the authorization code.

On success, the response contains the access_token, refresh_token, id_token, expires_in, and token_type values, for example:

  "id_token": "eyJhbG.............aGV_EyOANg",
  "access_token": "eyJhbGciOi.....Upe6r6hHNLiNQ",
  "expires_in": 3600,
  "token_type": "Bearer",
  "refresh_token": "_A4CpoIDT.......qYEpxEW8g",
  "scope": "openid profile offline_access"
Key Description
access_token An access token that can be provided in subsequent calls, for example to apaleo API services.
id_token It is sent to the client application as part of an OpenID Connect flow. It is used by the client to authenticate the user.
expires_in The time period (in seconds) for which the access token is valid. After this time period, the token will no longer be valid, and a new one must be retrieved.
token_type How the access token may be used: always Bearer.
refresh_token This token is included if the offline_access scope was requested and granted. This is a long-lived token that can be used to automatically generate a new access_token when the current one expires. This should be kept confidential.
scope A space-separated list of scopes that have been granted for this access_token.

Step 3. Make REST API calls

Once the access_token is obtained, it can be used to make calls to the API by passing it as a Bearer Token in the Authorization header of the HTTP request.

This sample call, which shows details of a property, includes a bearer token in the Authorization request header. This type of token lets you complete an action on behalf of a resource owner.

Content-Type: application/json
Authorization: Bearer my-authentication-token

Example cURL request

You can test your token by running the following cURL command.

Note: On Windows, use Windows Subsystem for Linux (WSL) to run the cURL command.

curl -i -H 'Authorization: Bearer eyJ...Vsg' -X GET

The response shows the property details:

  "id": "MUC",
  "code": "MUC",
  "isTemplate": false,
  "name": {
    "en": "Hotel Munich"
  "description": {
    "en": "This new cozy hotel is located in the heart of Schwabing and is walking distance from the historical city center."
  "companyName": "Hotel München GmbH",
  "commercialRegisterEntry": "Amtsgericht München, HRB 145673183",
  "taxId": "DE311053702",
  "location": {
    "addressLine1": "Leopoldstraße 8-10",
    "postalCode": "80802",
    "city": "Munich",
    "countryCode": "DE"
  "bankAccount": {
    "iban": "DE44 5001 0517 5407 3249 31",
    "bic": "SSKMDEMMXXX",
    "bank": "Stadtsparkasse München"
  "paymentTerms": {
    "de": "Zahlbar bei Check In",
    "en": "Payment on check-in"
  "timeZone": "Europe/Berlin",
  "currencyCode": "EUR",
  "created": "2020-04-08T21:53:26+02:00"