使用Axios请求Drupal OAuth认证返回invalid_grant错误排查
解决Axios请求Drupal OAuth2认证返回invalid_grant的问题
问题场景
我尝试用Axios从JavaScript应用向Drupal发起OAuth2密码模式认证,用Postman和终端的curl命令都能成功获取访问令牌,但Axios请求始终失败,返回invalid_grant错误。
我的Axios代码
const uri = 'https://test.com/oauth/token' const data = new FormData(); data.append("client_id", "xxxxxx"); data.append("client_secret", "secret"); data.append("grant_type", "password"); data.append("username", "user"); data.append("password", "secret"); data.append("scope", ""); axios({ method: 'POST', url: uri, headers: {}, data: data }) .then(res => { console.log("res", message); // 注:原代码里的message应为res.data,这里是小笔误 }) .catch(err => { console.log("error in request", err); });
错误信息
控制台返回的错误响应:
{ "data": { "error": "invalid_grant", "error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.", "hint": "Check the configuration to see if the grant is enabled.", "message": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client." } }
Drupal端日志也记录了League\OAuth2\Server\Exception\OAuthServerException异常,内容和上述错误描述一致。
问题原因与解决方案
这个问题的核心是请求格式不匹配:Postman和curl默认发送的是application/x-www-form-urlencoded格式的表单数据,但Axios在处理FormData对象时,会自动设置请求头为multipart/form-data,而Drupal的OAuth2服务器并不支持这种格式来处理密码授权请求。
给你两种可行的解决方法:
方法1:改用URLSearchParams封装数据
这是最简单的方案,URLSearchParams会让Axios自动设置正确的Content-Type头,完全匹配Drupal的要求:
const uri = 'https://test.com/oauth/token'; const data = new URLSearchParams(); data.append("client_id", "xxxxxx"); data.append("client_secret", "secret"); data.append("grant_type", "password"); data.append("username", "user"); data.append("password", "secret"); data.append("scope", ""); axios.post(uri, data) .then(res => { console.log("res", res.data); }) .catch(err => { console.log("error in request", err); });
方法2:手动转换FormData并设置请求头
如果你必须使用FormData,可以手动把它转换成URL编码格式,并指定正确的请求头:
const uri = 'https://test.com/oauth/token'; const data = new FormData(); data.append("client_id", "xxxxxx"); data.append("client_secret", "secret"); data.append("grant_type", "password"); data.append("username", "user"); data.append("password", "secret"); data.append("scope", ""); // 将FormData转换为URL编码的字符串 const encodedData = new URLSearchParams(data).toString(); axios({ method: 'POST', url: uri, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: encodedData }) .then(res => { console.log("res", res.data); }) .catch(err => { console.log("error in request", err); });
额外检查项
除了请求格式,建议你再确认以下几点:
- 确保
client_id、client_secret、用户名和密码完全正确,没有多余空格或大小写错误 - 检查Drupal的OAuth2模块是否已启用密码授权类型(Password Grant)
- 确认用户账号状态正常,未被锁定且密码有效
内容的提问来源于stack exchange,提问作者Macaret
相关产品推荐
相关产品推荐

