使用django-oauth-toolkit获取access_token时遇invalid_client错误求助
按照django-oauth-toolkit官方教程在Django项目中集成OAuth2,已成功获取client_id、secret、code_verifier和code,但执行以下curl请求获取access_token时:
curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://127.0.0.1:8000/o/token/" -d "client_id=${ID}" -d "client_secret=${SECRET}" -d "code=${CODE}" -d "code_verifier=${CODE_VERIFIER}" -d "redirect_uri=http://127.0.0.1:8000/noexist/callback" -d "grant_type=authorization_code"终端始终返回
{"error": "invalid_client"},反复核对凭证仍无法解决。
检查客户端认证类型匹配性
去Django后台的Applications页面查看你创建的客户端Client Type:- 如果是
Public类型,请求里不能带client_secret,直接去掉curl中的-d "client_secret=${SECRET}"参数 - 如果是
Confidential类型,确认client_secret完全正确,注意大小写、特殊字符(比如空格、引号是否需要转义)
- 如果是
确认环境变量是否正确替换
终端里的${ID}、${SECRET}等变量如果未提前赋值,curl会直接传递变量名而非实际凭证。先执行:echo $ID $SECRET $CODE $CODE_VERIFIER确认输出是正确的凭证值,若未赋值,直接将实际值替换到curl命令中(特殊字符可使用单引号包裹)
严格匹配redirect_uri
获取code时使用的redirect_uri,必须和请求token时的完全一致,包括协议、域名、端口、路径。比如授权时用http://localhost:8000/noexist/callback,请求时用127.0.0.1会导致不匹配。去Django后台客户端页面的Redirect uris字段核对,确保请求中的redirect_uri与其中一条完全相同。验证code的有效性
authorization code默认有效期短且仅能使用一次,若之前已用该code请求过token,或code已过期,会触发异常。重新走授权流程获取新code后再尝试。检查请求格式合规性
确保请求的Content-Type是application/x-www-form-urlencoded,参数必须是url编码的键值对,不能用JSON格式传递。可借助Postman模拟请求,对比curl的参数格式是否正确。查看Django日志获取细节
在settings.py中添加日志配置:LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': {'class': 'logging.StreamHandler'}, }, 'loggers': { 'django_oauth_toolkit': { 'handlers': ['console'], 'level': 'DEBUG', }, }, }重启服务后执行curl请求,终端会输出服务器端的详细错误原因,比如client_secret不匹配、客户端不存在等。
内容的提问来源于stack exchange,提问作者Adryan Taborda

