OpenID Connect

OpenID Connect allows Apps to retrieve information about the end-user via the OAuth Authorization Code flow.

The OpenID Connect flow is characterized by having id_token in the response_type and by having a scope attribute to show which claims are being requested.

On this page:

OAuth flowsLink

Besides the existing code response_type, OpenID Connect brings id_token as an option to the OAuth flow.

response_typeDescriptioncodeSame as described hereid_tokenBehaves as an implicit flow but only receiving the id_token, without access_tokencode id_tokenKnown as hybrid flow, it behaves like the authorization code flow, also returning the id_token with the authorization code
GET https://{subdomain}.thinkific.com/oauth2/authorize?
    response_type=code%20id_token
    &client_id=IUH123qxo
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20profile%20email
    &state=axasd123UJWdkj
    &code_challenge=JkPMaqxEitO39uCxh_c2nfsUlRDQSTa7rLKx4gkoS3Y
    &code_challenge_method=S256

ScopeLink

Scopes allow apps to request claims from users. The scopes supported are:

claimsdescriptionopenidMandatory for openid flows. Add sub to the claims. sub is the user gid. And user_id_api_v1 for backwards compatibility with Public API v1profileUser's profile data: name, given_name, family_name, updated_at and pictureemailUser's emailsiteSite's data: subdomain, name, currency, domain and support_email

openid is mandatory to work when response_type includes id_token. Any combination with the other scopes is supported.

For example, openid profile, openid email site, and so on.

GET https://{subdomain}.thinkific.com/oauth2/authorize?
    response_type=code%20id_token
    &client_id=IUH123qxo
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20profile%20email
    &state=axasd123UJWdkj
    &code_challenge=JkPMaqxEitO39uCxh_c2nfsUlRDQSTa7rLKx4gkoS3Y
    &code_challenge_method=S256

Response ModeLink

Response mode is how the authorization response is formatted:

claimsdescriptionqueryThe default when response_mode is blank. The response parameters are returned via query string, at the redirect URLform_postThe response parameters are embedded in an HTML form as hidden, which is auto-submitted on load, resulting into a POST request with application/x-www-form-urlencoded content type

Note: query it is the current default, but it won't be supported at some point in the future. This is why we recommend using form_post

For example, when using form_post as response_mode:

GET https://{subdomain}.thinkific.com/oauth2/authorize?
    response_mode=form_post
    &response_type=id_token
    &client_id=IUH123qxo
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20profile%20email
    &state=axasd123UJWdkj
    &code_challenge=JkPMaqxEitO39uCxh_c2nfsUlRDQSTa7rLKx4gkoS3Y
    &code_challenge_method=S256

It renders the following form:

<html>
   <body onload="javascript:document.forms[0].submit()">
    <form method="post" action="https://example-app.com/cb">
      <input type="hidden" name="state"
       value="axasd123UJWdkj"/>
      <input type="hidden" name="id_token"
       value="eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJzdWIiOiJqb2huIiw
         iYXVkIjoiZmZzMiIsImp0aSI6ImhwQUI3RDBNbEo0c2YzVFR2cllxUkIiLC
         Jpc3MiOiJodHRwczpcL1wvbG9jYWxob3N0OjkwMzEiLCJpYXQiOjEzNjM5M
         DMxMTMsImV4cCI6MTM2MzkwMzcxMywibm9uY2UiOiIyVDFBZ2FlUlRHVE1B
         SnllRE1OOUlKYmdpVUciLCJhY3IiOiJ1cm46b2FzaXM6bmFtZXM6dGM6U0F
         NTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZCIsImF1dGhfdGltZSI6MTM2Mz
         kwMDg5NH0.c9emvFayy-YJnO0kxUNQqeAoYu7sjlyulRSNrru1ySZs2qwqq
         wwq-Qk7LFd3iGYeUWrfjZkmyXeKKs_OtZ2tI2QQqJpcfrpAuiNuEHII-_fk
         IufbGNT_rfHUcY3tGGKxcvZO9uvgKgX9Vs1v04UaCOUfxRjSVlumE6fWGcq
         XVEKhtPadj1elk3r4zkoNt9vjUQt9NGdm1OvaZ2ONprCErBbXf1eJb4NW_h
         nrQ5IKXuNsQ1g9ccT5DMtZSwgDFwsHMDWMPFGax5Lw6ogjwJ4AQDrhzNCFc
         0uVAwBBb772-86HpAkGWAKOK-wTC6ErRTcESRdNRe0iKb47XRXaoz5acA"/>
    </form>
   </body>
  </html>

And then, after the submit, results into a POST request to the given redirect_uri:

POST /cb HTTP/1.1
  Host: example-app.com
  Content-Type: application/x-www-form-urlencoded
  id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJzdWIiOiJqb2huIiwiYX
         VkIjoiZmZzMiIsImp0aSI6ImhwQUI3RDBNbEo0c2YzVFR2cllxUkIiLCJpc
         3MiOiJodHRwczpcL1wvbG9jYWxob3N0OjkwMzEiLCJpYXQiOjEzNjM5MDMx
         MTMsImV4cCI6MTM2MzkwMzcxMywibm9uY2UiOiIyVDFBZ2FlUlRHVE1BSnl
         lRE1OOUlKYmdpVUciLCJhY3IiOiJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTD
         oyLjA6YWM6Y2xhc3NlczpQYXNzd29yZCIsImF1dGhfdGltZSI6MTM2MzkwM
         Dg5NH0.c9emvFayy-YJnO0kxUNQqeAoYu7sjlyulRSNrru1ySZs2qwqqwwq
         -Qk7LFd3iGYeUWrfjZkmyXeKKs_OtZ2tI2QQqJpcfrpAuiNuEHII-_fkIuf
         bGNT_rfHUcY3tGGKxcvZO9uvgKgX9Vs1v04UaCOUfxRjSVlumE6fWGcqXVE
         KhtPadj1elk3r4zkoNt9vjUQt9NGdm1OvaZ2ONprCErBbXf1eJb4NW_hnrQ
         5IKXuNsQ1g9ccT5DMtZSwgDFwsHMDWMPFGax5Lw6ogjwJ4AQDrhzNCFc0uV
         AwBBb772-86HpAkGWAKOK-wTC6ErRTcESRdNRe0iKb47XRXaoz5acA&
  state=axasd123UJWdkj

ID TokenLink

ID Token are JWT (JSON Web Tokens), consisting of a header, payload and signature portion, used to verify the authenticity of the token.

It contains the claims requested during the Authorization Code + OpenID Connect flow.

ValidationLink

When receiving the ID_TOKEN, it needs to be validated using a JWK (JSON Web Key) to can be retrieved from:

GET https://{subdomain}.thinkific.com/.well-known/jwks.json

JWKS example response:

{
  "keys": [
    {
      "kty": "RSA",
      "n": "37jh10J64WrNKRDk6_-paqBwFg0ewvBzIX1pPFlxJ6AOf7e-jDIQ1GgJ7i-pB8FG8rj4gdy-JNqRRUj_jQV_eAUGCphX2_Ut4y0MznPMKfoFP__-Cr05oR2xsV3C_bc9lkkV74rAuDSA0DPhZ04nJieDpoURh_jZy7LLiks4WMbv5nJTpiW6As8zaNVDKFf7PDeXlbI2x-LPuI2S2EHePWyC4_PbXmeJmPiywnKjfRSGKyPVAamsZmJ6Mh79SAACD7SBvykWDRfYqSCw7UCwoKPWhB_9harsIWbxer4_PJSCgbdfbBRgfgCzCPS4xS5hB2iRDc5s-cqlgHDVj6fDZQ",
      "e":"AQAB",
      "kid":"54299cd7b7ca111a02b8a5cfbcb653ad2a1afe1ef8a97536621ca3e4c410c668"
    }
  ]
}

We recommend the use of a library to validate the token.

NonceLink

nonce is a string used to mitigate replay attacks by allowing the client to associate its session with the ID Token. When informed in the authorization request the server is going to pass the nonce unmodified as a claim inside the ID Token so the client can verify if the value is the same. The nonce parameter is required when response_mode=form_post

GET https://{subdomain}.thinkific.com/oauth2/authorize?
    response_type=code%20id_token
    &client_id=IUH123qxo
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid%20profile%20email
    &state=axasd123UJWdkj
    &nonce=n-0S6_WzA2Mj
    &code_challenge=JkPMaqxEitO39uCxh_c2nfsUlRDQSTa7rLKx4gkoS3Y
    &code_challenge_method=S256

UserInfoLink


IMPORTANT: During a successful response, the sub value currently contains the Thinkific User's ID. However, this User ID will change in the future. To keep consistency and get user's data via API call, you will have to use user_id_api_v1 attribute.


The Userinfo endpoint returns the data about the logged user.

UserInfo is protected and needs to be accessed by using the access_token received during the Authorization Code + OpenID Connect flow.

Header { Authorization: acc123tok456 }
GET https://{subdomain}.thinkific.com/oidc/userinfo

ResponsesLink

The information returned for this endpoint will correspond to the scope requested during the Authorization Code + OpenID Connect flow.

SuccessLink

{
  "email": "jane@thinkific.com",
  "family_name": "Doe",
  "given_name": "Jane",
  "name": "Jane Doe",
  "picture": "https://assets.thinkific.com/profile.png",
  "roles": ["site_admin"],
  "site": {
      "currency": "usd",
      "domain": "school.thinkific.com",
      "name": "Jane's School",
      "subdomain": "jane",
      "support_email": "jane@thinkific.com"
  },
  "sub": "01EY1SAQY490WCG2H7SZ1365HN",
  "user_id_api_v1": "123456780",
  "updated_at": 1601504367
}

401 UnauthorizedLink

{
  "error": "unauthorized"
}

403 ForbiddenLink

{
  "error": "forbidden"
}

OpenID Connect server discoveryLink

We provide an endpoint to expose the OpenID Connect server configuration. Through this endpoint you can view the endpoints supported, OAuth2 grants, response_modes, response_types

GET https://{subdomain}.thinkific.com/.well-known/openid-configuration
{
  "issuer": "https://school.thinkific.com",
  "authorization_endpoint": "https://school.thinkific.com/oauth2/authorize",
  "token_endpoint": "https://school.thinkific.com/oauth2/token",
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic"
  ],
  "userinfo_endpoint": "https://school.thinkific.com/oidc/userinfo",
  "jwks_uri": "https://school.thinkific.com/.well-known/jwks.json",
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token"
  ],
  "scopes_supported": [
    "openid",
    "profile",
    "email",
    "site"
  ],
  "response_modes_supported": [
    "query",
    "form_post"
  ],
  "response_types_supported": [
    "code",
    "code id_token",
    "id_token"
  ],
  "subject_types_supported": [
    "public"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "claim_types_supported": [
    "normal",
    "aggregated"
  ],
  "claims_supported": [
    "aud",
    "sub",
    "iss",
    "auth_time",
    "name",
    "given_name",
    "family_name",
    "updated_at",
    "picture",
    "email",
    "email_verified",
    "site"
  ]
}