Docs
Login Kit with QR Code
Overview
This document explains how to integrate with Login Kit to support user authorization with QR codes for your web application. Once authenticated users authorize your app, you can access their basic TikTok profile data including their display name and avatar. Additional data access may require approval for additional Scopes. Learn more on Scopes Overview.
Prerequisites
Obtain a client key and client secret by logging in to Developer Portal and selecting your app.
Security Advisory: Verifying integrity using client_ticket
The client_ticket
mentioned throughout this document enables you to verify the data integrity of the response. While your app may still function even if you don't validate the client_ticket
, doing so introduces security risks. Therefore, it is highly recommended that you 1) always verify that the client_ticket
matches the one generated by you, and 2) reject any response where this validation fails as it may have been compromised by a malicious attacker.
Integration Guide
Your web app must implement the following functionality on the server side:
- Generate QR code: Request QR code URL, generate a
client_ticket
, insert theclient_ticket
inside the QR code URL, render the URL, and then display to user. - Repeatedly check the QR code status and refresh or disable it accordingly.
- Parse the response for the provided authorization
code
once QR code status is changed toconfirmed
. - Request access token and refresh token from Tiktok using the authorization code and client key.
- Notify the user of authorization success or failure.
- Use the access token to fetch authorized user data, and use the refresh token to extend the access token's expiration time.
For more information on access and refresh tokens, see Manage User Access Tokens.
See Appendix A for instructions on using client_ticket
.
APIs
Get QR Code Endpoint
GEThttps://open-api.tiktok.com/v0/oauth/get_qrcode
Description
Request QR code from TikTok.
Request
Request Query
Key | Type | Description | Example | Required |
client_key | string | Client key provided by TikTok | aw7nk86b7czitwc9 | true |
scope | string | Comma-separated scope name. Need to be approved first | user.info.basic,user.info.username | true |
next | string | Callback url. Domain needs to be approved along with scopes on TikTok for Developers | https://calllback.example.com | true |
state | string | Callback url parameters | key%3Dabc | true |
Example request URL
https://open-api.tiktok.com/v0/oauth/get_qrcode?client_key=aw7ne86e7fzitwc9&scope=user.info.basic&next=https://callback.example.com&state=key%3Dvalue
Response
Response Body
Key | Type | Description | Example |
message | string | Response status | success | error |
data | Response.data Struct | Response body data | N/A |
extra | Response.extra Struct | Extra information for the response | N/A |
Response.data Struct
A successful response will include the Response.data
struct. Please then perform the following steps:
- Extract the
scan_qrcode_url
. - Generate a unique
ticket
string using your preferred approach. For example, you could generate an alphanumeric 8 character string such as2ncv7awq
. Persist thisticket
alongside your service. - In the previously extracted
scan_qrcode_url
, replace the parameterclient_ticket
with your ticket. For example,scan_qrcode_url=...&client_ticket=tobefilled&...
should be replaced byscan_qrcode_url=...&client_ticket=your_ticket&...
. - Use the modified
scan_qrcode_url
to generate a QR code. - Display the QR code to your user.
This client_ticket
will be used when calling check_qrcode
endpoints. See Appendix A for detailed instructions on using client_ticket
.
Key | Type | Description | Example |
scan_qrcode_url | string | QR code url, returned when the call is successful | aweme://authorize?authType=100&client_key=abcd1234&client_ticket=tobefilled&... |
token | string | Token used to check QR code status, returned when the call is successful | VJ5JCKGJGRSWNMFWHQH4W5NKY943Q97D |
error_code | int32 | Error code returned when the call is successful | 0 |
When the call fails, the following struct is returned:
Key | Type | Description | Example |
description | string | Error description returned when the call is failed | error |
error_code | int32 | Error code returned when the call is failed | 10001 |
Response.extra Struct
Key | Type | Description | Example |
error_detail | string | Details for the error. When the call is successful, the error_detail is empty string. | parameter is invalid. |
logid | int32 | The log ID for this request. | 20211217192600010245241048055EDE71 |
Example Response
Success
{
"data": {
"error_code": 0,
"scan_qrcode_url": "aweme://authorize?authType=100&client_key=abcd1234&client_ticket=tobefilled&...",
"token": "VJ5JCKGJGRSWNMFWHQH4W5NKY943Q97D..."
},
"extra": {
"error_detail": "",
"logid": "20211217192600010245241048055EDE71"
},
"message": "success"
}
Failure
{
"data":{
"description": "error",
"error_code": 10001
},
"extra": {
"error_detail": "error details",
"logid": "20211217192600010245241048055EDE71"
},
"message":"error"
}
Check QR code Endpoint
GEThttps://open-api.tiktok.com/v0/oauth/check_qrcode
Description
Check QR code status
Note
This API should be accessed by polling from your server side. This API should be invoked immediately after calling the get_qrcode
endpoint.
Request
Request Query
Key | Type | Description | Example | Required |
client_key | string | Client key provided by TikTok | aw7ne86e7fzitwc9 | true |
scope | string | Comma-separated scope name. Need to be approved first | user.info.basic,user.info.username | true |
next | string | Callback url. Domain needs to be approved along with scopes on TikTok for Developers | https://calllback.example.com | true |
token | string | Token obtained along with QR code | VJ5JCKGJGRSWNMFWHQH4W5NKY943Q97D | true |
Example request URL
https://open-api.tiktok.com/v0/oauth/check_qrcode?client_key=aw7ne86e7fzitwc9&scope=user.info.basic&next=https://callback.example.com&token=VJ5JCKGJGRSWNMFWHQH4W5NKY943Q97D
Response
Response Body
Key | Type | Description | Example |
message | string | Response status | success | error |
data | Response.data Struct | Response body data | N/A |
extra | Response.extra Struct | Extra information for the response | N/A |
Response.data Struct
When the call succeeds, it returns the following struct. After getting the response, you should:
- Check that the status is confirmed and the authorization code is appended in the
redirect_url
. - Check that the status is not
expired
. Otherwise, re-invoke theget_qrcode
API. - Validate that the
client_ticket
returned in the response matches your previously generated ticket. If they don't match, ignore the response as its integrity may be compromised.
Key | Type | Description | Example |
client_ticket | string | A string, which is generate in user's service. This is returned when the call is successful. | client_ticket="A23SDWEGsdasd" |
status | string | QR code status | new | expired | scanned | confirmed |
redirect_url | string | Redirect URL appended with authorization code, returned when the status is | https://callback.example.com?code=HOXbXtnAok4qojdOmsHjucm1V1KJrOjYuMnV |
error_code | int32 | Error code returned 0 when the call is successful | 0 |
When the call fails, the following struct is returned:
Key | Type | Description | Example |
description | string | Error description returned when the call is failed | error |
error_code | int32 | Error code returned when the call is failed | 10001 |
Response.extra Struct
Key | Type | Description | Example |
error_detail | string | Details for the error. When the call is successful, the error_detail is empty string. | parameter is invalid. |
logid | int32 | The log ID for this request. | 20211217192600010245241048055EDE71 |
Example Response
Success
// status = new, wait for user to scan this QR, client_ticket will be empty
{
"data":{
"client_ticket": "",
"error_code" 0,
"status": "new"
},
"extra":{
"error_detail": "",
"logid": "202112132120360102452421962502D468"
},
"message": "success"
}
// status = scanned. should disable the QR code under this scenario
{
"data":{
"client_ticket": "your_ticket_string",
"error_code" 0,
"status": "scanned"
},
"extra":{
"error_detail": "",
"logid": "202112132120360102452421962502D468"
},
"message": "success"
}
// status = confirmed authorization and obtain the code
{
"data":{
"client_ticket": "your_ticket_string",
"error_code" 0,
"status": "comfirmed",
"redirect_url": "https://example.com?code=example_code"
},
"extra":{
"error_detail": "",
"logid": "202112132120360102452421962502D468"
},
"message": "success"
}
// status = expired, should request new QR code under this scenario
{
"data":{
"error_code" 0,
"status": "expired"
},
"extra":{
"error_detail": "",
"logid": "202112132120360102452421962502D468"
},
"message": "success"
}
Failure
{
"data":{
"description": "error",
"error_code": 10001
},
"extra": {
"error_detail": "error details",
"logid": "202112131904550102510041850CDE9528"
},
"message":"error"
}