Перейти к содержимому
Socialift
Руководство

TikTok Login Kit: OAuth-поток и жизненный цикл токенов

TikTok Login Kit — это OAuth 2.0. Приложение отправляет пользователя на https://www.tiktok.com/v2/auth/authorize/ с client_key, scopes и state, получает code на зарегистрированный redirect URI и на сервере обменивает его через /v2/oauth/token/. Access token живёт 24 часа, refresh token — 365 дней, поэтому обновление нужно планировать ежедневно.

Обновлено:

Как работает OAuth в TikTok?

TikTok использует authorization code flow. Пользователь подтверждает запрошенные scopes на странице авторизации TikTok, TikTok перенаправляет его обратно с code, а ваш сервер обменивает код вместе с client key и client secret на access token, refresh token и open_id пользователя. Дальше API-запросы отправляют access token в заголовке Authorization: Bearer.

Login Kit есть для Web, Desktop, iOS и Android. Веб-поток опирается на сервер, который хранит client secret и проверяет state; в desktop- и mobile-потоках добавляется PKCE — при обмене кода отправляется code_verifier.

Что может токен, определяют scopes. user.info.basic добавляется автоматически; остальные, например video.list или video.publish, нужно подключить к приложению в портале разработчика и показать на проверке приложения.

Ключевые термины: client key, client secret, open_id и токены

client_key
Открытый идентификатор приложения. Передаётся в ссылке авторизации и в запросах токена.
client_secret
Секретный ключ приложения. Используется только в серверных запросах к /v2/oauth/token/ и /v2/oauth/revoke/; не попадает в браузер или мобильную сборку.
code
Код авторизации, который приходит на redirect URI после согласия пользователя. Обменивайте его на токены сразу.
access_token
Bearer-токен для API-запросов, действует 24 часа с момента выдачи.
refresh_token
Нужен для получения нового access token; действует 365 дней с первой выдачи. В ответе на обновление может прийти другой refresh token.
open_id
Уникальный идентификатор пользователя TikTok, приходит вместе с токеном. Используйте его как ключ подключённого аккаунта.
state
Случайное значение, которое создаётся перед редиректом и сверяется в callback, — защита от CSRF.

Как настроить OAuth TikTok для веб-приложения

  1. Зарегистрируйте redirect URI

    В настройках Login Kit добавьте до 10 redirect URI. Каждый должен быть абсолютным, начинаться с https, быть короче 512 символов, статическим (без query-параметров) и без фрагмента #.

  2. Создайте и сохраните state

    Для каждой попытки входа генерируйте случайную строку и храните её в сессии пользователя или короткоживущем cookie. Официальный веб-пример TikTok тоже использует короткоживущий cookie.

  3. Перенаправьте на страницу авторизации

    Откройте https://www.tiktok.com/v2/auth/authorize/ с client_key, response_type=code, scope через запятую, redirect_uri и state. Чтобы окно согласия показывалось всегда, добавьте disable_auto_auth=1.

  4. Проверьте callback

    TikTok возвращает code, scopes и state, а при ошибке — error и error_description. Отклоняйте запрос, если state не совпал, и сверяйте выданные scopes с запрошенными.

  5. Обменяйте код на сервере

    Отправьте POST на https://open.tiktokapis.com/v2/oauth/token/ в формате application/x-www-form-urlencoded с client_key, client_secret, code, grant_type=authorization_code и тем же redirect_uri. Desktop- и mobile-приложения передают ещё code_verifier.

  6. Надёжно сохраните токены

    Храните access_token, refresh_token, оба срока и open_id в зашифрованном виде. Веб-гайд TikTok прямо возлагает на сервер ответственность за безопасность client secret и refresh token.

Login Kit на Python

Обработчики не привязаны к фреймворку: session — хранилище сессии вашего веб-фреймворка.

tiktok_login.py
import secrets
from socialift import TikTok

REDIRECT_URI = "https://app.example.com/oauth/tiktok/callback"
SCOPES = ["user.info.basic", "video.list", "video.publish"]

async def begin_login(session: dict) -> str:
    session["tiktok_state"] = secrets.token_urlsafe(32)
    async with TikTok.from_env() as tt:
        return tt.login_url(
            redirect_uri=REDIRECT_URI,
            state=session["tiktok_state"],
            scopes=SCOPES,
        )

async def finish_login(session: dict, code: str, state: str) -> dict:
    expected = session.pop("tiktok_state", "")
    if not expected or not secrets.compare_digest(state, expected):
        raise ValueError("OAuth state mismatch")
    async with TikTok.from_env() as tt:
        bundle = await tt.exchange_code(code, redirect_uri=REDIRECT_URI)
    return {
        "open_id": bundle.raw.get("open_id"),
        "access_token": bundle.access_token,
        "refresh_token": bundle.refresh_token,
        "expires_at": bundle.expires_at,
        "scopes": bundle.scopes,
    }

exchange_code отправляет тело в формате form-urlencoded, как требует TikTok, и выбрасывает ApiError, если access token не пришёл.

Сохраняйте результат в зашифрованном виде. SDK ничего не хранит между вызовами, поэтому один клиент может обслуживать много авторов.

PKCE: веб, desktop и mobile

PKCE: веб, desktop и mobile — Таблица возможностей по платформам
ПлатформаPKCEПравила redirect URI
WebВ гайде Login Kit for Web не упоминается; защита строится на серверном secret и stateАбсолютный https, статический, без фрагмента, до 10 штук, короче 512 символов
DesktopОбязателен: code_challenge и code_challenge_method=S256 в ссылке, code_verifier при обменеhttp или https, допускаются localhost и 127.0.0.1, порт обязателен (можно wildcard), без параметров и фрагмента
iOS / Androidcode_verifier обязателен при обмене кодаПо данным платформы, указанным для приложения (package name, bundle ID)

Desktop-гайд TikTok вычисляет code_challenge как SHA-256 от verifier в hex-кодировке, а не в base64url, как в RFC 7636.

PKCE для desktop-приложений

Verifier должен быть длиной 43–128 символов и состоять только из A–Z, a–z, 0–9 и символов -, ., _, ~.

tiktok_desktop_pkce.py
import hashlib
import secrets
from socialift import TikTok

REDIRECT_URI = "http://127.0.0.1:3455/callback/"

def make_pkce() -> tuple[str, str]:
    verifier = secrets.token_urlsafe(48)                       # 64 символа
    challenge = hashlib.sha256(verifier.encode()).hexdigest()  # hex, как в документации TikTok
    return verifier, challenge

async def desktop_login(state: str) -> tuple[str, str]:
    verifier, challenge = make_pkce()
    async with TikTok.from_env() as tt:
        url = tt.login_url(
            redirect_uri=REDIRECT_URI,
            state=state,
            code_challenge=challenge,
            code_challenge_method="S256",
        )
    return url, verifier

async def desktop_callback(code: str, verifier: str):
    async with TikTok.from_env() as tt:
        return await tt.exchange_code(code, redirect_uri=REDIRECT_URI, code_verifier=verifier)

Обмен кода выполняйте на своём backend: запрос токена всё равно содержит client secret.

Сроки жизни токенов и что с ними делать

Сроки жизни токенов и что с ними делать — Таблица возможностей по платформам
СитуацияСрокЧто делать
access_token24 часа с момента выдачиОбновляйте до истечения; точное значение — в expires_in ответа
refresh_token365 дней с первой выдачиЕсли в ответе на обновление пришёл другой refresh token, замените сохранённый
Истёк refresh tokenнетПроведите пользователя через Login Kit заново
Пользователь отключил приложениеК приходу authorization.removed access token уже недействителенПометьте аккаунт отключённым и прекратите запросы
Вызван /v2/oauth/revoke/Доступ вашего приложения отозванУдалите сохранённые токены

естьнет

Ежедневное обновление и отзыв при отключении

tiktok_tokens.py
from datetime import datetime, timedelta, timezone
from socialift import ApiError, TikTok

async def ensure_fresh(account: dict) -> dict:
    left = account["expires_at"] - datetime.now(timezone.utc)
    if left > timedelta(hours=2):
        return account
    async with TikTok.from_env() as tt:
        try:
            bundle = await tt.refresh_token(account["refresh_token"])
        except ApiError:
            account["status"] = "reconnect_required"
            return account
    account.update(
        access_token=bundle.access_token,
        refresh_token=bundle.refresh_token or account["refresh_token"],
        expires_at=bundle.expires_at,
    )
    return account

async def disconnect(account: dict) -> None:
    async with TikTok.from_env() as tt:
        await tt.revoke(account["access_token"])

Запускайте обновление через cron или очередь с интервалом меньше 24 часов. Каждый раз сохраняйте refresh token из ответа — TikTok требует использовать новое значение, если оно изменилось.

Scopes и согласие на практике

Параметр scope — список через запятую, и каждый scope должен быть заранее назначен приложению на сайте TikTok for Developers. В callback TikTok возвращает выданные scopes в параметре scopes — сохраните его и проверяйте перед вызовом endpoint'а, которому нужен конкретный scope.

Если вы позже добавили scopes, проведите существующих пользователей через авторизацию снова. При disable_auto_auth=0 TikTok пропускает страницу авторизации для активной сессии, при disable_auto_auth=1 показывает её всегда — именно это нужно, когда меняется набор scopes. В SDK: tt.login_url(..., disable_auto_auth=True).

Если пользователь удалит приложение в настройках TikTok, зарегистрированный webhook получит authorization.removed; к этому моменту access token уже недействителен. Socialift SDK проверяет такие доставки через verify_tiktok_request и разбирает через parse_tiktok_event. Точные redirect- и webhook-URL для консоли TikTok показаны на странице «Kalitlar» (ключи) в кабинете Socialift.

Чек-лист безопасности OAuth TikTok

  • Храните client secret и refresh token только на сервере и в зашифрованном виде.
  • Создавайте новый state для каждого входа и отклоняйте callback с несовпадающим значением.
  • Регистрируйте точные статические HTTPS redirect URI; контекст передавайте через state или сессию, а не query-параметрами.
  • В desktop-приложениях используйте PKCE с S256 и передавайте code_verifier при обмене.
  • Обновляйте access token по расписанию чаще, чем раз в 24 часа, и сохраняйте сменившиеся refresh token.
  • Отзывайте токен через /v2/oauth/revoke/, когда пользователь отключается в вашем продукте.
  • Пишите в лог log_id неудачных запросов для поддержки TikTok.

← Назад в блог

Частые вопросы

Сколько действует access token TikTok?

Access token действует 24 часа с момента выдачи, refresh token — 365 дней с первой выдачи. Поэтому интеграции нужна ежедневная задача обновления; после истечения refresh token пользователь проходит авторизацию заново.

Возвращает ли TikTok новый refresh token при обновлении?

Может вернуть. По документации TikTok refresh_token в ответе может отличаться от отправленного, и тогда нужно использовать новое значение. Обновляйте сохранённый токен после каждого обновления.

Нужен ли PKCE для веб-авторизации TikTok?

В гайде Login Kit for Web PKCE нет: веб-поток опирается на серверный client secret и проверку state. Desktop- и mobile-приложения обязаны передавать code_verifier при обмене кода; для desktop code_challenge — это SHA-256 в hex.

Почему возникает ошибка redirect_uri?

redirect_uri в запросе должен в точности совпадать со значением, зарегистрированным в настройках приложения. Для веба это абсолютный https-адрес, статический (без параметров) и без фрагмента #; при обмене кода передавайте то же значение.

Как отозвать токен TikTok?

Отправьте POST на https://open.tiktokapis.com/v2/oauth/revoke/ с client_key, client_secret и token. В Socialift SDK это await tt.revoke(access_token).

Какой scope выдаётся по умолчанию?

Приложениям с Login Kit автоматически добавляется user.info.basic: он даёт open_id, аватар и отображаемое имя. Остальные scopes подключаются к приложению отдельно.

Источники

  1. TikTok for Developers — Login Kit for Web
  2. TikTok for Developers — Login Kit for Desktop
  3. TikTok for Developers — User access token management
  4. TikTok for Developers — Scopes reference
  5. TikTok for Developers — Webhook events

Связанные страницы