【问题标题】:HTTP Post oAuth 2 "Check the `grant_type` parameter"HTTP Post oAuth 2“检查 `grant_type` 参数”
【发布时间】:2021-11-21 08:41:59
【问题描述】:

我正在使用以下代码在我的 dart 应用中为 Wikimedia 实施 OAuth 2 授权流程:

String jsonString = jsonEncode(<String, String>{
  'grant_type' : 'authorization_code',
  'redirect_uri' : Uri.encodeFull(redirectUri),
  'code' : authCode,
  'client_id' : CLIENT_ID,
  'client_secret' : clientSecret,
});
String paramName = 'param';
String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
List<int> bodyBytes = utf8.encode(formBody);

Future<http.Response> response = http.post( 
  Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
  headers: <String, String>{
    "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
    "Content-Length" : bodyBytes.length.toString()
  },
  body: bodyBytes,
);

对此的回应是:

{ "error": "invalid_request", "error_description": "请求是 缺少必需的参数,包括无效的参数值, 多次包含一个参数,或者格式错误。",
"hint": "检查 `grant_type` 参数", "message": "请求 缺少必需的参数,包含无效的参数值, 包含不止一次的参数,或者格式错误。” }

这可能与内容类型仍然是 JSON 的事实有关,即使我在标头中将其定义为 application/x-www-form-urlencoded 或因为内容长度为 -1。

Header Information from Flutter DevTools

General Information from Flutter DevTools

【问题讨论】:

    标签: flutter http dart oauth-2.0 mediawiki-api


    【解决方案1】:

    要匹配Content-Type 标头,您需要将参数编码为application/x-www-form-urlencoded

    为此,您可以将代码更改为:

    String body = Uri(queryParameters: <String, String> {
      'grant_type' : 'authorization_code',
      'redirect_uri' : Uri.encodeFull(redirectUri),
      'code' : authCode,
      'client_id' : CLIENT_ID,
      'client_secret' : clientSecret,
    }).query;
    

    调用几乎相同:

    Future<http.Response> response = http.post( 
      Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
      headers: <String, String>{
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
        'Content-Length' : body.length.toString()
      },  
      body: body,
    );
    

    附录

    这可以更简洁一些,将两个部分组合到一个调用中:

    Future<http.Response> response = http.post(
      Uri.parse('https://meta.wikimedia.org/w/rest.php/oauth2/access_token'),
      headers: <String, String>{
        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
      },  
      body: <String, String>{
        'grant_type': 'authorization_code',
        'redirect_uri': Uri.encodeFull(redirectUri),
        'code': authCode,
        'client_id': CLIENT_ID,
        'client_secret': clientSecret,
      }
    );
    

    请注意,特定的 Content-Length 标头不是必需的,因为这是在发送时计算的。

    【讨论】:

    • 这仍然遇到完全相同的问题,唯一的区别是正文不是 utf-8 编码的。
    • 有趣。我没有合适的客户端 ID 等,但是运行您的代码会给我提供的错误,而运行我的代码会给出不同的错误:{"error":"invalid_client","error_description":"Client authentication failed","message":"Client authentication failed"} 这是我或多或少预期的。
    • 我在您的编辑中删除了 Content Lenght 参数(并删除了重定向 uri,因为它不是必需的),现在它可以工作了。谢谢!
    猜你喜欢
    • 2016-10-02
    • 2014-10-14
    • 2017-12-16
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 2020-12-04
    • 1970-01-01
    • 2012-01-02
    相关资源
    最近更新 更多