SSO Examples

ExamplesLink

Ruby ExampleLink

# 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
  THINKIFIC_API_KEY = ENV["THINKIFIC_API_KEY"]
  THINKIFIC_SUBDOMAIN = ENV["THINKIFIC_SUBDOMAIN"]

  def create
    # If the submitted credentials pass, then log user into Thinkific
    if user = User.authenticate(params[:login], params[:password])
      sign_into_thinkific(user)
    else
      render :new, :notice => "Invalid credentials"
    end
  end

  private

  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 = Time.now.to_i
    jti = "#{iat}/#{SecureRandom.hex(18)}"
    payload = JWT.encode({
      :iat   => iat,
      :jti   => jti,
      :first_name  => user.first_name,
      :last_name => user.last_name,
      :email => user.email,
      },
      THINKIFIC_API_KEY
    )
    redirect_to thinkific_sso_url(payload)
  end

  def thinkific_sso_url(payload)
    url = "http://#{THINKIFIC_SUBDOMAIN}.thinkific.com/api/sso/v2/sso/jwt?jwt=#{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?
    url
  end

end

PHP ExampleLink

// Create token header as a JSON string
$header = json_encode(['typ' = 'JWT', 'alg' = 'HS256']);

// Create token payload as a JSON string
$payload = json_encode([
  'email'='test@thinkific.com',
  'first_name'='Test',
  'last_name' = 'User',
  'iat' = time(),
]);

// Encode Header to Base64Url String
$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

// Encode Payload to Base64Url String
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));

// Create Signature Hash
$key = 'API_KEY';
$signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, \$key, true);

// Encode Signature to Base64Url String
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

// Create JWT
$jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;

$baseUrl = "https://yoursite.thinkific.com/api/sso/v2/sso/jwt?jwt=";
$returnTo = urlencode("https://yoursite.thinkific.com");
$errorUrl = urlencode("https://yoursite.thinkific.com");
$url = $baseUrl . $jwt . "&return_to=" . $returnTo . "&error_url=" . $errorUrl;

echo \$url;

C# ExampleLink

// C# .Net Core 2.2

using Newtonsoft.Json;
using System;
using System.Security.Cryptography;

public JsonResult ThinkificLogin()
{
  //get API key from vault
  string PlainTextSecurityKey = \_configuration["ThinkificAPIKey"];

  //create header object then convert to a JSON string and encoding character,s finally converting to base 64.
  string HeaderObj = JsonConvert.SerializeObject(new { typ = "JWT", alg = "HS256" });
  var HeaderBase64 = FixChars(Base64Encode(HeaderObj));

  //create payload object then convert to a JSON string and encoding characters, finally converting to base 64.
  var Payload = new
  {
    first_name = "Name 1",
    last_name = "Name 2",
    email = "email@email.com",
    iat = GetUnixEpoch()
  };
  var PayloadBase64 = FixChars(Base64Encode(JsonConvert.SerializeObject(Payload)));

  //Base 64 header and base 64 Payload need to be concatinated seperated by . for use creating the signature.
  var headerAndPayload = HeaderBase64 + "." + PayloadBase64;

  //HMAC the crap out of the Plain Text key, after converting it to a byte array
  HMACSHA256 hmac = new HMACSHA256(System.Text.Encoding.ASCII.GetBytes(PlainTextSecurityKey));

  //Hash the combined header and payload, converting the result to a base 64 then encoding the resulting characters.
  var SignatureBase64 = FixChars(Convert.ToBase64String(hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(headerAndPayload))));

  //build the final token.
  var JWT = HeaderBase64 + "." + PayloadBase64 + "." + SignatureBase64;

  //breath a sigh of releaf that this portion of your project is completed!
  return new JsonResult(JWT);
}

public string FixChars(string Input)
{
  Input = Input.Replace('+', '-');
  Input = Input.Replace('/', '\_');

  if (Input.Contains('='))
  {
    Input = Input.Replace("=", string.Empty);
  }
  return Input;
}

public string Base64Encode(string plainText)
{
  var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
  return Convert.ToBase64String(plainTextBytes);
}

public long GetUnixEpoch()
{
  TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
  long secondsSinceEpoch = (int)t.TotalSeconds;
  return secondsSinceEpoch;
}

As this code will vary widely across themes and external sites, we can't give specific instructions. If you have any questions, please reach out!