Google OAuth有限输入设备应用报错:unsupported_grant_type
问题排查与修复
你的错误根源在于请求token接口时的参数传递方式与设置的Content-Type不匹配:
你明确设置了Content-Type: application/x-www-form-urlencoded,但却用json参数传递数据——requests会自动将json参数的内容序列化为JSON格式,甚至会覆盖你手动设置的Content-Type,导致后端无法正确解析grant_type参数,最终返回"unsupported_grant_type"错误。
另外,grant_type无需手动做URL编码,直接使用原始字符串即可。
修复后的代码如下:
import json import requests import time def main(): with open("client_secret.json") as f: creds = json.load(f) # 简化读取逻辑,无需先read再loads # 获取设备码 device_code_res = requests.post( "https://oauth2.googleapis.com/device/code", json={ "client_id": creds['installed']['client_id'], "scope": "https://www.googleapis.com/auth/youtube" } ) if not device_code_res.ok: print("获取设备码失败:", device_code_res.text) return reply = device_code_res.json() # 提示用户完成验证(这一步不能省略,否则直接请求token会返回授权未完成) print(f"请访问 {reply['verification_url']},输入代码 {reply['user_code']} 完成验证") # 轮询请求token,等待用户完成验证 interval = reply.get('interval', 5) while True: token_res = requests.post( "https://oauth2.googleapis.com/token", headers={"Content-Type": "application/x-www-form-urlencoded"}, data={ # 改用data参数传递表单格式数据 "client_id": creds['installed']['client_id'], "device_code": reply['device_code'], "grant_type": "urn:ietf:params:oauth:grant-type:device_code" } ) token_data = token_res.json() if token_res.ok: print("获取token成功:", token_data) break # 处理常见的等待状态 if token_data.get("error") == "authorization_pending": time.sleep(interval) interval = min(interval * 2, 60) # 避免轮询过于频繁 else: print("获取token失败:", token_data) break if __name__ == "__main__": main()
额外补充:
- 设备授权流程必须等待用户完成验证后才能获取到有效token,原代码直接在获取设备码后立即请求token,大概率会返回"authorization_pending"错误,因此添加了轮询逻辑,并根据返回的
interval控制轮询间隔。 - 简化了客户端凭证的读取方式,
json.load(f)可以直接读取文件中的JSON内容。
内容的提问来源于stack exchange,提问作者CrabbyPete
相关产品推荐
相关产品推荐

