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>.administratelms.com/config | jq '.brand'
curl https://<portal>.administratelms.com/config | 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"
hashlib.sha256(code_verifier.encode()).digest()
).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 'https://identity.getadministrate.com/token' \
--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 'https://lms-api.administratehq.com/graphql' \
-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 'https://identity.getadministrate.com/token' \
--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>