You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TikTok OAuth授权码始终过期问题求助

解决TikTok OAuth授权码过期(invalid_grant)问题

针对你遇到的invalid_grant错误,以下是几个核心排查方向和修复方案:

1. 授权码仅支持单次使用

TikTok的授权码是一次性凭证,哪怕你之前用同一个code请求token失败,这个code也会立即失效。确保每次获取新的code后,只调用一次get_access_token接口,禁止重复使用同一code。

2. 缩短授权码的生命周期间隔

TikTok授权码的有效期通常在5分钟以内,手动复制跳转URL的过程如果耗时过长,code会直接过期。建议:

  • 替换手动复制流程:用本地服务器(如Flask/Django)自动捕获redirect_uri的回调请求,减少人为延迟(示例代码见下文)。
  • 若必须手动测试,务必在获取code后的1-2分钟内完成token请求。

3. 严格匹配redirect_uri

检查TikTok开发者后台配置的redirect_uri与代码中的REDIRECT_URI是否完全一致,包括:

  • 末尾的斜杠(比如后台是https://oxyfoo.com/pierre/tiktok-automation,代码里不能加斜杠)
  • 域名、路径的大小写
  • 是否包含协议(必须是http/https)

任何细微差异都会导致code验证失败,触发过期错误。

4. 修正token请求的参数处理

你的代码中存在重复URL编码的问题,可能导致code被错误篡改:

# 原代码错误:手动urlencode data后传给requests,requests会再次编码
response = requests.post(TOKEN_URL, headers=headers, data=urllib.parse.urlencode(data))

# 修复方案:直接传入字典,requests会自动处理x-www-form-urlencoded格式
# 同时添加code的URL解码,避免原始code中的转义字符导致错误
def get_access_token(authorization_code):
    # 解码URL中的转义字符(如%2B、%2F等)
    decoded_code = urllib.parse.unquote(authorization_code)
    data = {
        'client_key': CLIENT_KEY,
        'client_secret': CLIENT_SECRET,
        'code': decoded_code,
        'grant_type': 'authorization_code',
        'redirect_uri': REDIRECT_URI
    }
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    response = requests.post(TOKEN_URL, headers=headers, data=data)

    if response.status_code == 200:
        return response.json()
    else:
        print(f"Error: {response.status_code}")
        print(f"Response: {response.text}")
        return None

5. 确认环境匹配(沙盒/生产)

检查你使用的API URL是否与应用所处环境一致:

  • 沙盒环境:授权URL为https://sandbox.tiktok.com/v2/auth/authorize/,token URL为https://open-sandbox.tiktokapis.com/v2/oauth/token/
  • 生产环境:授权URL为https://www.tiktok.com/v2/auth/authorize/,token URL为https://open.tiktokapis.com/v2/oauth/token/

如果应用还在沙盒测试阶段,却使用生产环境URL,会直接触发授权错误。

优化手动测试流程(自动捕获code)

用Flask搭建本地服务,避免手动复制URL:

from flask import Flask, request
import requests
import urllib
import secrets

app = Flask(__name__)

CLIENT_KEY = "xxxxx"
CLIENT_SECRET = "yyyyy"
REDIRECT_URI = "http://localhost:5000/callback"  # 需在TikTok后台配置此地址
AUTHORIZE_URL = 'https://www.tiktok.com/v2/auth/authorize/'
TOKEN_URL = 'https://open.tiktokapis.com/v2/oauth/token/'

@app.route('/')
def index():
    csrf_state = secrets.token_hex(16)
    params = {
        'client_key': CLIENT_KEY,
        'scope': 'user.info.basic',
        'response_type': 'code',
        'redirect_uri': REDIRECT_URI,
        'state': csrf_state,
    }
    auth_url = AUTHORIZE_URL + '?' + urllib.parse.urlencode(params)
    return f'<a href="{auth_url}">点击授权TikTok</a>'

@app.route('/callback')
def callback():
    code = request.args.get('code')
    state = request.args.get('state')
    # 可选:验证state防止CSRF攻击(测试阶段可跳过)
    token_info = get_access_token(code)
    return str(token_info)

def get_access_token(authorization_code):
    decoded_code = urllib.parse.unquote(authorization_code)
    data = {
        'client_key': CLIENT_KEY,
        'client_secret': CLIENT_SECRET,
        'code': decoded_code,
        'grant_type': 'authorization_code',
        'redirect_uri': REDIRECT_URI
    }
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    response = requests.post(TOKEN_URL, headers=headers, data=data)
    if response.status_code == 200:
        return response.json()
    else:
        return {"error": response.status_code, "message": response.text}

if __name__ == '__main__':
    app.run(debug=True)

内容的提问来源于stack exchange,提问作者Madar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 02:46:14