HTTP Post oAuth 2 "Check the `grant_type` parameter"
HTTP Post oAuth 2 "Check the `grant_type` parameter"
我正在使用以下代码在我的 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": "The request is
missing a required parameter, includes an invalid parameter value,
includes a parameter more than once, or is otherwise malformed.",
"hint": "Check the `grant_type` parameter", "message": "The request
is missing a required parameter, includes an invalid parameter value,
includes a parameter more than once, or is otherwise malformed." }
这可能与 content-type 仍然是 JSON 这一事实有关,尽管我在 header 中将其定义为 application/x-www-form-urlencoded
或者因为 content-length 是-1.
Header Information from Flutter DevTools
General Information from Flutter DevTools
要匹配 Content-Type
header,您需要将参数编码为 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
header 不是必需的,因为这是在发送时计算的。
我正在使用以下代码在我的 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": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed.",
"hint": "Check the `grant_type` parameter", "message": "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed." }
这可能与 content-type 仍然是 JSON 这一事实有关,尽管我在 header 中将其定义为 application/x-www-form-urlencoded
或者因为 content-length 是-1.
Header Information from Flutter DevTools
General Information from Flutter DevTools
要匹配 Content-Type
header,您需要将参数编码为 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
header 不是必需的,因为这是在发送时计算的。