SSO V2 - Automatically Sign in From Your Own Website

This article will explain how to use Thinkific's SSO feature to sign into your Thinkific school from your website.

Note: This is an advanced plan feature that should only be implemented by those with access to software development resources. If you don't know what SSO is, then you probably don't need this feature.

Thinkific's SSO feature uses JWT (JSON Web Tokens) to achieve Single Sign On. Single sign-on is a mechanism that allows you to authenticate users in your systems and subsequently tell Thinkific that the user has been authenticated. The user is then allowed access to your Thinkific school without being prompted to enter separate login credentials.

How Thinkific's SSO Works

  1. An unauthenticated user signs into your system.

  2. Once the user has been authenticated on your system, code written within your system must construct a JWT payload (explained below) and redirect to Thinkific's Single Sign-On URL, passing the payload as a query string parameter. Optionally, you may also pass a properly encoded return_to URL as a query string parameter as well as an error_url.

  3. Thinkific deconstructs the JWT payload and either finds the user or creates the user if the user has not been created. The user is then signed into your Thinkific school.

The JWT Payload

Your application must construct the JWT payload and sign it using your Thinkific API key.  The key can be found under the API section of your Thinkific admin dashboard. The best practice for security is to generate the JWT token on a server and then retrieve it from the client side, rather than exposing the JWT shared secret in the client side JavaScript.

Note: Do not base 64 encode your API key when signing your JWT token. Our application expects the API key as-is when verifying your JWT token.

The JWT payload is typically constructed as a hash. The following attributes are supported:

  1. email - the email of the authenticated user. This is REQUIRED. If external_id is NOT supplied, email will be used as the unique identifier.

  2. first_name - the first name of the authenticated user. This is REQUIRED.

  3. last_name - the last name of the authenticated user. This is REQUIRED.

  4. external_id - an identifier for the authenticated user. This might be the id of the user in your system. This is OPTIONAL, but if supplied will be used as the unique identifier of the user.

  5. bio - a textual bio of the user. This is OPTIONAL

  6. phone_number - the user's phone number. This is OPTIONAL.

  7. company - the user's company. This is OPTIONAL.

  8. city - the user's city. This is OPTIONAL.

  9. country - the user's country. This is OPTIONAL.

  10. website - the user's website. This is OPTIONAL.

  11. timezone - the user's timezone abbreviation (as defined here: This is OPTIONAL.

  12. iat - must be the number of seconds since UNIX epoch. This is essentially the time that the JWT payload was issued. This is REQUIRED.

  13. jti - JSON Web Token ID. This is used to defend against replay attacks and is typically constructed using a combination of the iat and a random value. This is REQUIRED.

There are various libraries for working with JWT. A list can be found here.

One thing to be aware of is that the JWT payload is merely encoded and signed, not encrypted, so don't put any sensitive data in the hash table. JWT works by serializing the JSON that is being transmitted to a string. It then base 64 encodes that string and then makes an HMAC of the base 64 string which depends on the shared secret. This produces a signature that the recipient side can use to validate the user.

The return_to parameter

After a user is authenticated in your system, it should redirect to your Thinkific school's SSO URL. As part of the redirect URL, you can append a return_to query string parameter that is an encoded URL that the user will be returned to after the sign in to your Thinkific school is complete. For example:


The error_url parameter

When attempting to use the SSO, errors can occur. For example, the user's email address may be improperly formatted. In these cases, you may want the user to be redirected to an error page of your choosing. For example:


The Thinkific SSO URL

The Thinkific SSO URL is the URL on your Thinkific school that you redirect to after a user has successfully authenticated in your system. It has the following structure:

http://{your-school}{payload}&return_to={url to return to}&error_url={url to redirect to in the case of an error}

  • The jwt parameter is the JWT payload that you construct and is REQUIRED.

  • The return_to is the url that you want the user to be redirected to after signing in to your Thinkific school. It is OPTIONAL.

  • The error_url is the url that you want the user to be redirected to in the case of an error. This is OPTIONAL.

  • If the return_to url is not supplied, the user will be redirected to their default page within your Thinkific school.

  • If the error_url is not supplied, the user will be redirected to the return_to url that you supplied OR, if no return_url is supplied, to a generic Thinkific error page.

Ruby Example


# Assuming that you've set your API key and Thinkific subdomain in the environment, you
# can use the Thinkific SSO from your controller like this example.
require 'securerandom' unless defined?(SecureRandom)
class SessionController < ApplicationController
  # Configuration
  def create
    if user = User.authenticate(params[:login], params[:password])
      # If the submitted credentials pass, then log user into Thinkific
      render :new, :notice => "Invalid credentials"
  def sign_into_thinkific(user)
    # This is the meat of the business, set up the parameters you wish
    # to forward to THinkific. All parameters are documented in this page.
    iat =
    jti = "#{iat}/#{SecureRandom.hex(18)}"
    payload = JWT.encode({
      :iat   => iat,
      :jti   => jti,
      :first_name  => user.first_name,
      :last_name => user.last_name,
      :email =>,
      :external_id => 'primary key or identifier of the user in your system'
    redirect_to thinkific_sso_url(payload)
  def thinkific_sso_url(payload)
    url = "http://#{THINKIFIC_SUBDOMAIN}{payload}"
    url += "&return_to=#{URI.escape(params["return_to"])}" if params["return_to"].present?
    url += "&error_url=#{URI.escape(params["error_url"])}" if params["error_url"].present?

Error Handling

 If an error occurs, the user will not be signed into your Thinkific school. There are several cases when this might occur:

  1. Your code does not provide the JWT payload

  2. Your JWT payload is not correctly signed

  3. Your JWT payload is expired - this is based on the age of the IAT parameter. Thinkific allows a 2 minute leeway of accuracy to account for things like clock skew.

  4. A validation error occurs when creating a new user in your Thinkific school. (if one of the required parameters is missing, for example).

  5. Some other unforseen exception occurs.

If an error does occur, and you have provided a return_to parameter, Thinkific's SSO will not sign the user in and will redirect to the supplied return_to URL with 2 parameters:

  • kind - the type of error (currently one of 6 possibilities: jwt, validation, expired_token, invalid_iat, invalid_jti and unspecified)

  • message - the error message

If an error does occur, and you have provided an error_url parameter, Thinkfic's SSO will not sign the user in and will redirect to the supplied error_url with the same parameters as above.

  • The error_url is used preferentially to the return_to url if both are provided

If an error occurs and you have not provided a return_to parameter, Thinkific's SSO will not sign the user in and will display the error message on the default page of your Thinkific school.

Did you find it helpful? Yes No

Send feedback
Sorry we couldn't be helpful. Help us improve this article with your feedback.