Single Sign-On (JSON)

figure-1

JSON Web Token (JWT) SSO

Your school can be configured to use JWT SSO. Here are the steps of the JWT single sign-on authentication process:

  • Your script builds a JWT request with a secret key shared between you and Thought Industries. The JWT request contains the relevant user data.
  • You redirect the customer to the Thought Industries endpoint at https://mycompany.thoughtindustries.com/access/jwt (or https://www.myvanityURL.com/access/jwt) with the JWT payload.
  • Thought Industries parses the user detail from the JWT payload and then grants the user access.

To perform SSO for a user, you need to send several attributes to Thought Industries as a base64-encoded JSON hash/dictionary.

Base Attributes Required/Recommended for all JWT Payloads

iatintegerThe time the token was generated, this is used to help ensure that a given token gets used shortly after it’s generated. The value must be the number of seconds since UNIX epoch. We will automatically reject the token if the iat is not within 500 seconds of TI server time.
emailstringEmail address of the user being signed in.
externalCustomerIdstringAny unique identifier for the user. We will use this as the internal identifier of a user if provided. If a user already exists with this identifier, their information will be updated. We recommend always providing an externalCustomerId whenever possible, as this allows for email address changes without creating duplicate a user record.
firstNamestringFirst name of the user being signed in.
lastNamestringLast name of the user being signed in.

Access can be assigned in various ways depending on the TI functionality being used.

Assigning Access a la Carte

If you are assigning access to individual pieces of content, you can use the following attributes. By default, we will add onto any existing access. For example, if you specify “course-a” in one payload, and “course-b” in another, the user will have access to both “course-a” and “course-b”. You can use the replaceCourseAccess attribute to override this behavior. In order to find slugs, click ‘View’ from the content management list, then the slug is the part of the URL after “/learn/course/“, but before the next slash. For example, if the URL of your course is /learn/course/this-is-a-test/first-section/first-lesson, then the slug is “this-is-a-test”. This same logic applies to all content items, simply replacing “course” with the content item.to override this behavior.

courseSlugsstring or array of stringsThe unique slug identifier(s) of the course(s) the user has access to. To pass more than one, use an array. This applies to webinars, courses, articles, and videos. We recommend using bundleSlugs  instead of courseSlugs because you can easily add courses to a subscription and that addition will reflect on all previous SSO users and all new SSO users without any SSO integration changes.
bundleSlugsstring or array of strings The unique slug identifier(s) of the subscription(s) the user should be given access to. To pass more than one, use an array. You will need to create the subscriptions within the TI interface, making sure to add courses to the subscription. The word “bundle” is an internal identifier for subscriptions and does not apply to collections. Use courseSlugs directly for a collection of courses.
learningPathSlugsstring or array of strings The unique slug identifier(s) of the learning path(s) the user should be given access to. To pass more than one, use an array.
replaceCourseAccessboolean, default falseSetting this to true will revoke access to any courses not specified in `courseSlugs`. For example, if you send `courseSlugs` over as [‘a’, ‘b’, ‘c’], we will grant access to those three courses.  Afterwards, if you send `courseSlugs` over as [‘a’,’b’]  for the same learner, we will revoke access to course ‘c.’ You should not use this option if you are using TI-managed subscriptions. We will also revoke all access if `courseSlugs` is omitted or an empty array.
replaceLearningPathAccessboolean, default falseSetting this to true will revoke access to any Learning Paths not specified in `learningPathSlugs`. For example, if you send `learningPathSlugs` over as [‘a’, ‘b’, ‘c’], we will grant access to those three Learning Paths.  Afterwards, if you send `learningPathSlugs` over as [‘a’,’b’]  for the same learner, we will revoke access to Learning Path ‘c.’ You should not use this option if you are using TI-managed subscriptions. We will also revoke all access if `learningPathSlugs` is omitted or an empty array.
tieredSubscriptionboolean, default falseYou should set this to ‘true’ if you have a tiered subscription system where a user is upgrading or downgrading between subscriptions. This assumes a user should only have access to one subscription at a time. You should specify which single subscription the user has access to with `bundleSlugs` and we will replace any existing subscription on the user with the subscription specified. We will also revoke access if no subscription is specified, which can be used for cancelations.

If you are using Panorama, you will want to use the following attributes to assign access to the client & license(s). By default, we will add onto any existing access. For example, if you specify “license-a” in one payload, and “license-b” in another, the user will have access to both “license-a” and “license-b”. You can use the replaceLicenseAccess attribute to override this behavior.

Assigning Access to Panorama Through License IDs

You can specify license IDs directly, and we will determine the client automatically. Student / Manager is part of the next generation of Panorama. Manager licenses are ignored for learners– these only apply to client managers. To find a license ID, if you are using sublicense functionality, you will see a license ID when you click “Edit” on any sublicense. If you are not using sublicense functionality, you will see a license ID on the “Master License” tab. The list of licenses passed can only belong to one client.

studentLicenseIdsUUID or array of UUIDsThe UUID(s) of the license(s) the user should have access to as a student. To pass more than one, use an array. The previous licenseIds attribute has been deprecated in favor of this attribute.
managerLicenseIdsUUID or array of UUIDsThe UUID(s) of the license(s) the user should have access to as a manager. To pass more than one, use an array. This attribute only applies if the user is a client manager.

Assigning Access to Panorama Through Client & License SKUs

With the next generation of Panorama, you are now able to assign an arbitrary string “sku” to both Clients & Licenses. The license sku must be unique across a single client, but can be re-used across multiple clients. This allows you to setup a consistent license identification system across clients, and eliminates the need to pull license UUIDs out of TI.

clientIdUUIDThe UUID of the client the user should belong to. To find the UUID of a client, simply navigate to it from the management interface and copy the UUID out of the URL. This can be used as an alternative to clientSlug & clientSku.
clientSlugstringThe slug of the client the user should belong to. To find the slug of a client, simply navigate to it from the management interface, click “view public site”, and copy the path out of the URL. This can be used as an alternative to clientId & clientSku.
clientSkustringThe sku of the client the user should belong to. This can be configured in the client settings. This can be used as an alternative to clientId & clientSlug.
studentLicenseSkusstring or array of stringsThe sku(s) of the license(s) the user should have access to as a student. The SKU can be configured when editing a license. To pass more than one, use an array. This attribute must be specified alongside either clientId, clientSlug, or clientSku.
managerLicenseSkusstring or array of stringsThe sku(s) of the license(s) the user should have access to as a manager. The SKU can be configured when editing a license. To pass more than one, use an array. This attribute only applies if the user is a client manager. This attribute must be specified alongside either clientId, clientSlug, or clientSku.
replaceLicenseAccessboolean, default falseSetting this to true will revoke access to any licenses not specified in either studentLicenseSkus or managerLicenseSkus. For example, if you send studentLicenseSkus over as [‘a’, ‘b’, ‘c’], we will grant access to those three licenses.  Afterwards, if you send `studentLicenseSkus` over as [‘a’,’b’]  for the same learner, we will revoke access to license ‘c.’ We revoke all access if studentLicenseSkus is an empty array and there is no clientId / clientSlug / clientSku specified.

Other Attributes

The following attributes can be used to store additional information about the user.

returnTostringURI of page to redirect the user after they have been created. Defaults to the student dashboard.
ref1string, 32 character limitAny arbitrary information to be stored on the user. Can be used for any arbitrary information, e.g. student ID, company name, etc.
ref2string, 32 character limitSee ref1
ref3string, 32 character limitSee ref1
ref4string, 32 character limitSee ref1
ref5string, 32 character limitSee ref1
ref6string, 32 character limitSee ref1
ref7string, 32 character limitSee ref1
ref8string, 32 character limitSee ref1
ref9string, 32 character limitSee ref1
ref10string, 32 character limitSee ref1
sfContactIdstringSalesforce Contact ID of the user. Must be specified alongside sfAccountId. This field is not currently validated, so please ensure you are sending over correct information.
sfAccountIdstringSalesforce Account ID of the user. Must be specified alongside sfContactId. This field is not currently validated, so please ensure you are sending over correct information.
rolestring, default “student”The role of the user, e.g. “admin”, “student”, “client-manager” etc. Can be a built-in TI role or a custom role. Similar to slugs, the role specified here should be a version of the role name with spaces replaced by dashes and all lowercase.

Specify HS256 as the JWT algorithm in the header of your JWT payload:

{ 
  "typ":"JWT",
  "alg":"HS256" 
}

HS256 stands for HMAC SHA 256, a 256-bit encryption algorithm designed by the U.S. National Security Agency.

You can find your shared secret key by logging into your school’s manager interface and then navigating to “Settings” and then “Security”, from there you will find the key under “API Key.” Be sure to keep this key a secret.

Once you have generated the JWT payload, redirect the user along with the payload to the following Thought Industries endpoint: https://mycompany.thoughtindustries.com/access/jwt?jwt=PAYLOAD The payload should be a base64-encoded JSON object and appended to the URL as a query string. If you use an off-the-shelf JWT library, the payload should automatically be generated in the correct format. The JWT payload must be sent to your Thought Industries subdomain using the https protocol.

Example in Ruby using the jwt gem:

payload = JWT.encode({
   :externalCustomerId => "12345",
   :email => "bob@example.com",
   :firstName => "Bob",
   :lastName => "Jones",
   :iat => Time.now.to_i,
   :returnTo => "/learn/",
   :ref1 => "studentid",
   :ref2 => "company name",
   :ref3 => "origin",
   :bundleSlugs => ["subscription-1", "subscription-next"]
}, "Our shared secret")

response.headers["Location"] = "https://example.thoughtindustries.com/access/jwt?jwt=#{payload}"

More information on JWT, including libraries in variety of languages, can be found at https://jwt.io/