Authenticating against the LMS GraphQL API

The Administrate IDP (Identity Provider) handles the log in needs of the LMS, Booking, and Approval Portals. The IDP uses the industry standard OAuth 2 Code flow to authenticate.

The full manual process is documented below, however, in most cases, using a library like Auth0 is preferred.

Authentication Steps

Step 1: Retrieve the Portal Configuration

First you'll need to retrieve the required configuration for your Portal.

Make sure you have curl and jq installed and run the following in your command line and then take note of the brand, client_id and domain.

curl https://<portal> | jq '.brand'

curl https://<portal> | jq '.idp'

Step 2: Generate the Code Verifier and Code Challenge

We also need to generate our code verifier and our code challenge. The code verifier is a random, unique string that you need to store (to complete the flow later). To create the code challenge, you need to create a SHA256 hash of the verifier, and base64 URL encode it.

Python sample:

from base64 import urlsafe_b64encode
import hashlib

code_verifier = "unique_and_r@nd0M!_string"
code_challenge = urlsafe_b64encode(                     # Result: "Ia6CrXEp0F-eOk_i1JHCLF_LkHW4zBoRYBADp6b0kjg"
).decode().replace("=", "")

Tip: This article has some recommendations on how to create a code challenge in JS

Step 3: Authorize the End User

You can now create the authorization URL using the information from steps 1 and 2:

https://<domain>/authorize?brand=<brand>&client_id=<client_id>&redirect_uri=<uri to return to once sign in complete>&code_challenge=<code>

Send the end user to this URL to authenticate with their credentials via the Administrate IDP.

Tip: The user may not be prompted to enter their credentials, if they were previously logged in.

Step 4: Exchange the Code for an Access Token

Once the user is authorized, they will be redirected to the redirect_uri with a query parameter containing a code.

Take this code, and post it to the /token route of the IDP as application/json along with the client_id and the code verifier:

Example cURL:

curl --location --request POST '' \
    --header 'Content-Type: application/json' \
    --data-raw '{"code": "RETURNED FROM STEP 3","client_id": "WIthSkbdp7XIQrO6HuEkJ3gjtFlh1MRZ","code_verifier": "unique_and_r@nd0M!_string"}'

This will return a JSON response that will contain several fields, the most important being the access_token that is required to use the LMS and WebLink APIs. You can pull data out of the access_token payload to get information about who has just signed in. Other data includes the id_token (which is used to identify the user in other operations) and the refresh token (which is used to generate a new access token without requiring re-authorization).

Tip: The response is encoded as a JWT. You can decode it using JWT.IO.

To validate the authenticity of the token, you can check our public key on our Identity Provider.

Step 5: Using the Access Token

To test that everything has worked as expected, you can execute a simple query against the LMS GraphQL API using the Access Token:

curl '' \
    -H 'authorization: Bearer ACCCESS_TOKEN_FROM_STEP_4' \
    -H 'content-type: application/json' \
    --data-binary '{"query":"{ hello }"}'

Mutations are run using the POST method.

Step 6: Exchange the Refresh Token for an Access Token

In Step 4, a Refresh Token is returned along with the Access Token. The Refresh Token can be repeatedly used to collect a new Access Token and ID Token by posting it to the /token route as application/json along with the client_id and a grant_type of refresh_token:

Example cURL:

curl --location --request POST '' \
    --header 'Content-Type: application/json' \
    --data-raw '{"grant_type": "refresh_token", "client_id": "FROM_STEP_1", "refresh_token": "RETURNED_FROM_STEP_4" }'

Step 7: Sign Out

To sign the user out of Administrate (so they have to authenticate with their credentials in step 3), you can send the user to the signout route.

Optionally, you can provide an id_token query argument. This will invalidate the refresh token of the user identified by the id_token.

Optionally, you can provide a redirect_uri query argument which is where the user will be redirected once sign out is complete. If a redirect_uri is not supplied, this route returns a 200 response.

https://<domain>/signout?brand=<brand>&client_id=<client_id>&id_token=<id_token>&redirect_uri=<uri to send the user to once sign out is complete>