OpenID Connect allows Apps to retrieve information about the end-user via the OAuth Authorization Code flow.
The OIDC flow is characterized by having id_token
in the response_type
and by having a scope
attribute to show which claims are being requested.
In this article
OAuth flows
Besides the existing code
response_type, OpenID Connect brings id_token
as an option to the OAuth flow.
response_type | Description |
code | Same as described here |
id_token | Behaves as an implicit flow but only receiving the id_token, without access_token |
code id_token |
Known 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
Scope
Scopes allow apps to request claims from users. The scopes supported are:
Claims | Description |
openid | Mandatory for openid flows. Add sub to the claims. sub is the user gid. And user_id_api_v1 for backwards compatibility with Public API v1 |
profile | User's profile data: name, given_name, family_name, updated_at, and picture |
User's email | |
site | Site'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 Mode
Response mode is how the authorization response is formatted:
Claims | Description |
query | The default when response_mode is blank. The response parameters are returned via query string, at the redirect URL |
form_post | The 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 usingform_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 Token
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.
Validation
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.
Nonce
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
UserInfo
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
Responses
The information returned for this endpoint will correspond to the scope requested during the Authorization Code + OpenID Connect flow.
Success
{
"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 Unauthorized
{
"error": "unauthorized"
}
403 Forbidden
{
"error": "forbidden"
}
OpenID Connect server discovery
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://courses.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",
"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"
]
}