OAuth Authorization

    Plan Availability
    Legacy Plans
    Platform

Thinkific uses the OAuth 2.0 authorization framework to issue access tokens on behalf of Thinkific Sites.

A detailed explanation of the OAuth options and steps is provided below. For a quick overview of the endpoints refer to our OAuth API Reference.

In this article:

Overview

When building Apps, you must authorize users using the Authorization Code Flow shown below. This flow can be extended with PKCE (Proof Key for Code Exchange) for scenarios where Client Secret cannot be safely stored.

authorization code flow

Note: This flow only supports authorization to access Thinkific API's on behalf of a Thinkific Site. To identify the current user and access their profile data, the flow should be extended with OpenID Connect.

App Credentials

In order to use this your App, you will need the app credentials (Client ID and Client Secret). You can collect these by registering an app with Thinkific.

See Building Apps in Thinkific to learn more.

Users

During Authorization, User Roles help to determine whether the user is permitted to install and access an App's functionality.

Installing Apps

Only users that have the role of Site Owners, Site Admins, or Partners will be able to install an App.

User flow

Your app must follow the correct installation flow, so that end users have a consistent app installation experience. This flow is detailed here: What should a user see when they install my app?

After Installation on a Thinkfic Site

Once an App has been installed on a Thinkific Site, users of all roles (including students) will be granted an access token when going through the OAuth Flow.

The issued access token is scoped to the user's appropriate role. For example, if the user is a student, their access token will return an unauthorized error when making requests to any of the Admin APIs, however they will be able to make successful calls to the Teaching API which returns data scoped to their role.

Before authorizing a user to access your app

When building an app, you should confirm the user's level of access before granting access to your App's Admin tools.

To do so, once you receive an access token from an OAuth flow, you should make a call to the Admin API using the Access Token granted to that user (to something like /api/public/v1/users). If the user is an admin they will receive a successful response, if they are a student they will receive an unauthorized response and should not be granted access.

You can gain more contextual information about a user by using OpenID Connect.

Authorization Code Flow

The authorization code flow returns a refresh token that can require the user to grant access once.

Step 1: Ask for permissions from the Thinkific Site Owner

In order to gain the necessary permissions for a Thinkific site, you'll need to redirect the Site Owner to the authorization flow by constructing the following URL:

https://{subdomain}.thinkific.com/oauth2/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_mode=query&response_type=code&state={state}

where:

Value Description
subdomain: The Subdomain for the Thinkific Site where the app will be installed.
client_id Your App's client ID. (Retrieved in Step 1).
redirect_uri One of the authorized redirect URIs you've configured in your App. (Completion of this authorization will redirect back to this uri)
state A unique and non-guessable value which will be sent back to the authorization code request. (Optional, but highly recommended to mitigate CSRF attacks)
response_type When using Authorization code flow, this value should always be code.
response_mode When using Authorization code flow, the default value, if blank is "query" but "form_post" can also be used

Note: Only the Site Owner can complete this authorization, Course & Site Admins are not able to grant access to apps.

Step 2: Confirm authorization code

Once the Site Owner grants access by installing the app, Thinkific will redirect the user back to the informed redirect_uri using the following format:

{redirect_uri}?code={authorization_code}&subdomain={subdomain}&state={state}

where:

Value Description
authorization_code A randomly generated code that expires in 60 seconds
subdomain The Subdomain for the Thinkific Site where the app is being installed.
state The value (if any) provided in the previous request using the state value.

The app should receive Thinkific's request and then make the final request to retrieve the access token using the authorization code.

Step 3: Retrieving access token

Upon receiving the authorization code, the app should perform one last request to retrieve the access token, a POST request using basic authentication.

Endpoint:

POST https://{subdomain}.thinkific.com/oauth2/token

Basic Authentication:

Basic Authentication can be generated by encoding a username and a password in base64.

If using a tool that handles encoding for you (like Postman), input the username and password with the following values.

Key Value Description
Username client Your app's client ID
Password client_secret Your apps's client secret

When encoding authentication in base64 manually, use the folowing format:

base64(client_id:client_secret)

The resulting example should be something like:

Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=

Request parameters:

In the body of the request, two values are expected:

Value Description
grant_type Value should be authorization_code
code The authorization code provided in the previous step

Example:

{
  "grant_type": "authorization_code",
  "code": "5a3c34512703ee80eb006dd255c0345a"
}

Headers:

The request must a User-Agent: request header, or the request will fail with a 403 forbidden error. 

Response parameters:

Upon receipt of a successful request, Thinkific will respond with a HTTP status 200 with the following attributes:

Value Description
access_token An access token to make secure requests. This token expires after 24 hours.
refresh_token A refresh token to request a new access token. Refresh tokens do not expire but can only be used once.
token_type Value should be "bearer"
gid Global id to uniquely identify a Thinkific Site
expires_in Number of seconds until the access_token will become invalid.

Example:

{
  "access_token": "5a16505d-5ee5-4853-8cb9-41b63a13a291",
  "token_type": "bearer",
  "refresh_token": "3cb103dd-f05f-43a9-aa51-c33b8f1f2546",
  "expires_in": 86399,
  "gid": "703ca109-741c-40d2-9cf0-3ac51c63086b"
}

Errors

Invalid Credentials

If the client_id or client_secret are invalid, Thinkific will respond with an HTTP 401 Status:

{
"error": "invalid credentials"
}
Invalid Code

If the authorization code is incorrect or no longer valid, Thinkific will respond with an HTTP 401 status:

{
"error": "invalid code"
}
Forbidden Code

If the request lacks a User-Agent: request header, Thinkific will respond with an HTTP 403 status:

{
"error": "Forbidden"
}

Step 4: Making secure requests

Now that you have a valid access token, you can begin making authorized requests to Thinkific's APIs using Bearer Token Authorization.

Example Request:

curl -H 'Authorization: Bearer 386ea500-fc01-45e9-8914-f53e3b7c0ed5' \
-H 'Content-Type: application/json' \
https://api.thinkific.com/api/public/v1/users

Step 5: Refreshing token

Access tokens expire after 24 hours, and will need to be refreshed in order to continue accessing the Thinkific API.

Apps can use the refresh_token that is provided when it received the current access token to request a new valid access token with the following API call:

Endpoint:

POST https://{subdomain}.thinkific.com/oauth2/token

Once again, this endpoint uses the Basic Authorization method, so be sure to follow this structure.

Request parameters:

While the first time the request parameters included a "code" value, during the refresh call we will insted now pass a grant_type of refresh_token.

Value Description
grant_type Value should be "refresh_token"
refresh_token Refresh token to request a new access token

example:

{
"grant_type": "refresh_token",
"refresh_token": "0d8dcc00-a6e7-450c-baef-6f27bb07e36c"
}

Response parameters:

Upon successful refresh of the access_token, Thinkific will respond with a HTTP status 200 with the following attributes:

Value Description
access_token A new access token to make secure requests.
refresh_token A refresh token to request a new access token. Refresh tokens do not expire but can only be used once.
token_type Value should be "bearer"
gid Global id to uniquely identify a Thinkific Site
expires_in Number of seconds until the access_token will become invalid

example:

{
  "access_token": "4a6cb9f1-3b1a-449f-bf57-5ec5db7272b8",
  "token_type": "bearer",
  "refresh_token": "e1963268-7687-4c69-a7c9-96957dca4550",
  "expires_in": 86399,
  "gid": "703ca109-741c-40d2-9cf0-3ac51c63086b"
}

Errors

Invalid Credentials

If the client_id or client_secret are invalid, Thinkific will respond with a HTTP 401 Status:

{
"error": "invalid credentials"
}
Invalid Refresh Token

If the refresh token is incorrect or no longer valid, Thinkific will respond with a HTTP 401 status:

{
"error": "invalid refresh token"
}

Note: Every time an access_token is generated, a new refresh token is also generated and the previous token is invalided.

Authorization Code Flow with PKCE

Proof Key for Code Exchange or just PKCE, is an extension to the Authorization Code flow that helps to prevent certain attacks and to be able to securely perform the OAuth exchange from an App. It is a best practice for Apps that cannot store the Client Secret, since it's replaced by a one time code challenge.

Looking for a quickstart? Follow this link for a detailed starter using Vue.JS

Step 1: Generate code verifier, code challenge method and code challenge

The code verifier and code challenge should be generated by the App for the OAuth requests.

Value Description
code_verifier A dynamically created cryptographically random key and it should be unique for every authorization request.
code_challenge_method Is used to generate the code challenge, "S256" is the standard at Thinkific.
code_challenge Is a hashed version of the code verifier, using the code challenge method algorithm and base64url-encoded.

Step 2: Ask for permissions from the Thinkific Site Owner with code challenge and code challenge method

In order to gain the necessary permissions for a Thinkific site, you'll need to redirect the Site Owner to the authorization flow by constructing the following URL.

Code Verifier and Code Challenge

Prior to requesting access, you must generate the code verifier. It's recommended the code verifier to be a string with the size of 43-128 characters.

From the code verifier, you must hash using SHA 256 and encode to a Base 64 URL safe string.

Requesting Access

https://{subdomain}.thinkific.com/oauth2/authorize?client_id={client_id}&redirect_uri={redirect_uri}&response_mode=query&response_type=code&state={state}&code_challenge={code_challenge}&code_challenge_method={code_challenge_method}

where:

Value Description
subdomain: The Subdomain for the Thinkific Site where the app will be installed.
client_id Your App's client ID. (Retrieved in Step 1).
redirect_uri One of the authorized redirect URIs you've configured in your App. (Completion of this authorization will redirect back to this uri)
state A unique and non-guessable value which will be sent back to the authorization code request. (Optional, but highly recommended to mitigate CSRF attacks)
response_type When using Authorization code flow, this value should always be code
response_mode When using Authorization code flow, the default value, if blank is "query" but "form_post" can also be used
code_challenge A challenge derived from the code verifier, using SHA 256 and encoded to a Base 64 URL safe string.
code_challenge_method This is the algorithm used to generate the code_challenge. This value should always be "S256"

Note: Only the Site Owner can complete this authorization, Course & Site Admins are not able to grant access to apps.

Step 3: Confirm authorization code

Once the Site Owner grants access by installing the app, Thinkific will redirect the user back to the informed redirect_uri using the following format:

{redirect_uri}?code={authorization_code}&subdomain={subdomain}&state={state}

where:

Value Description
authorization_code A randomly generated code that expires in 60 seconds
subdomain The Subdomain for the Thinkific Site where the app is being installed.
state The value (if any) provided in the previous request using the state value.

The app should be prepared to receive Thinkific's request and then make the final request to retrieve the access token as described in the next step.

Step 4: Retrieving access token

Upon receiving the authorization code, the app should perform the token request to retrieve the access token.

Endpoint:

POST https://{subdomain}.thinkific.com/oauth2/token

Basic Authentication:

The token request should be authenticated by using the Basic Authentication method, using the Client ID and Client Secret encoded in base64.

Please note that Client Secret is optional for the Authorization Code with PKCE, but it's required if you want to receive the refresh token.

If using a tool that handles encoding for you (like Postman), input the username and password with the following values.

Key Value Description
Username client Your app's client ID
Password client_secret Your apps's client secret
base64(client_id:client_secret)

The resulting example should be something like:

Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ=

Request parameters:

In the body of the request, two values are expected:

Value Description
grant_type This value should be "authorization_code"
code The authorization code provided in the previous step
code_verifier The random key generated at the beginning of the flow

Example:

{
  "grant_type": "authorization_code",
  "code": "5a3c34512703ee80eb006dd255c0345a",
  "code_verifier": "l2sdelBTs0cQiUJH-kjVxaxCv994o7gvqATmrGlru78"
}

Response parameters:

Upon receipt of a successful request(code verifier validated with the code challenge), Thinkific will respond with a HTTP status 200 with the following attributes:

Value Description
access_token An access token to make secure requests. This token expires after 24 hours
token_type Value should be "bearer"
gid The Subdomain for the Thinkific Site where the app is being installed.
expires_in Number of seconds until the access_token will become invalid.
refresh_token A refresh token to request a new access token. Refresh tokens do not expire but can only be used once. Only returned if Client Secret is provided

Example:

{
  "access_token": "5a16505d-5ee5-4853-8cb9-41b63a13a291",
  "token_type": "bearer",
  "refresh_token": "3cb103dd-f05f-43a9-aa51-c33b8f1f2546",
  "expires_in": 86399,
  "gid": "703ca109-741c-40d2-9cf0-3ac51c63086b"
}

Errors

Invalid Credentials

If the client_id or client_secret are invalid, Thinkific will respond with a HTTP 401 Status:

{
"error": "invalid credentials"
}
Invalid Grant

If the code challenge method is not S256 or if the code verifier and code challenge validation fails, Thinkific will respond with a HTTP 401 status:

{
"error": "invalid grant"
}
Invalid Code

If the authorization code is incorrect or no longer valid, Thinkific will respond with a HTTP 401 status:

{
"error": "invalid code"
}

Step 5: Making secure requests

Now that you have a valid access token, you can begin making authorized requests to Thinkific's APIs using Bearer Token Authorization.

Example Request:

curl -H 'Authorization: Bearer 386ea500-fc01-45e9-8914-f53e3b7c0ed5' \
-H 'Content-Type: application/json' \
https://api.thinkific.com/api/public/v1/users

You can find more information about the OAuth process in our free app development course!

Was this article helpful?
2 out of 5 found this helpful