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
相关产品推荐
相关产品推荐

