尝试使用 Google OAuth 进行身份验证并收到错误 "Required parameter is missing: grant_type"
Trying to Authenticate with Google OAuth and get error "Required parameter is missing: grant_type"
我正在尝试创建一个 Node.js 身份验证服务以使用 Google OAuth api.
进行身份验证
我有这个代码:
private exchangeTokens(code: string): Rx.Observable<IAuthTokens>{
code = decodeURIComponent(code);
console.log(`exchanging code for tokens: ${code}`);
const redirectUri = "http://localhost:8080";
let url = YouTubeAuthenticationServer.baseUrl + "token";
var postData= "code=" + encodeURIComponent(code);
postData += "&redirect_uri=" + encodeURIComponent(redirectUri);
postData += "&client_id=" + encodeURIComponent(process.env.CLIENT_ID);
postData += "&client_secret=" + encodeURIComponent(process.env.CLIENT_SECRET);
postData += "&scope=";
postData += "&grant_type=authorization_code";
return this.makePostRequest<IAuthTokens>(url,postData);
}
private makePostRequest<T>(targetUrl:string, data: string): Rx.Observable<T>{
console.log(`getting targetUrl: ${targetUrl}`);
var urlObject = url.parse(targetUrl);
var options: http.RequestOptions = {
hostname: urlObject.hostname,
port: Number(urlObject.port),
path: urlObject.path,
protocol: "https:",
method: "POST"
};
const request = https.request(options);
const returnObservable = Rx.Observable.fromEvent(<any>request, "response")
.take(1)
.flatMap( response => RxNode.fromWritableStream(<any>response))
.do( data => console.log(`data pumped: ${data}`) )
.toArray()
.map(function(allData){
return JSON.parse(allData.join("")) as T;
});
console.log(`write data: ${data}`);
request.write(data);
request.end();
return returnObservable;
}
从中我得到以下日志:
exchanging code for tokens: 4/k6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8#
getting targetUrl: https://accounts.google.com/o/oauth2/token
write data: code=4%2Fk6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8%23&redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=myCorrectId&client_secret=myCorrectSecret&scope=&grant_type=authorization_code
data pumped: {
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
所以我要发送以下内容:
code=4%2Fk6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8%23
redirect_uri=http%3A%2F%2Flocalhost%3A8080
client_id=myCorrrectId
client_secret=myCorrectSecret
scope=
grant_type=authorization_code
所以我不明白为什么说我不发送grant_type
如果您不想指定 scope
,则不要附加 "&scope="
。服务器可能将您的请求解释为请求以下范围:
&grant_type=authorization_code
这意味着请求实际上不包含 grant_type
。
非常感谢 João Angelo 的回答(发表在下面的评论中)
确保请求包含此 header:
Content-Type: application/x-www-form-urlencoded
因为 Google 可能允许其他内容类型并且可能会误解有效负载。
代码现在看起来像这样:
private makePostRequest<T>(targetUrl:string, data: string): Rx.Observable<T>{
console.log(`getting targetUrl: ${targetUrl}`);
var urlObject = url.parse(targetUrl);
var options: http.RequestOptions = {
hostname: urlObject.hostname,
port: Number(urlObject.port),
path: urlObject.path,
protocol: "https:",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
const request = https.request(options);
const returnObservable = Rx.Observable.fromEvent(<any>request, "response")
.take(1)
.flatMap( response => RxNode.fromWritableStream(<any>response))
.do( data => console.log(`data pumped: ${data}`) )
.toArray()
.map(function(allData){
return JSON.parse(allData.join("")) as T;
});
console.log(`write data: ${data}`);
request.write(data);
request.end();
return returnObservable;
}
我正在尝试创建一个 Node.js 身份验证服务以使用 Google OAuth api.
进行身份验证我有这个代码:
private exchangeTokens(code: string): Rx.Observable<IAuthTokens>{
code = decodeURIComponent(code);
console.log(`exchanging code for tokens: ${code}`);
const redirectUri = "http://localhost:8080";
let url = YouTubeAuthenticationServer.baseUrl + "token";
var postData= "code=" + encodeURIComponent(code);
postData += "&redirect_uri=" + encodeURIComponent(redirectUri);
postData += "&client_id=" + encodeURIComponent(process.env.CLIENT_ID);
postData += "&client_secret=" + encodeURIComponent(process.env.CLIENT_SECRET);
postData += "&scope=";
postData += "&grant_type=authorization_code";
return this.makePostRequest<IAuthTokens>(url,postData);
}
private makePostRequest<T>(targetUrl:string, data: string): Rx.Observable<T>{
console.log(`getting targetUrl: ${targetUrl}`);
var urlObject = url.parse(targetUrl);
var options: http.RequestOptions = {
hostname: urlObject.hostname,
port: Number(urlObject.port),
path: urlObject.path,
protocol: "https:",
method: "POST"
};
const request = https.request(options);
const returnObservable = Rx.Observable.fromEvent(<any>request, "response")
.take(1)
.flatMap( response => RxNode.fromWritableStream(<any>response))
.do( data => console.log(`data pumped: ${data}`) )
.toArray()
.map(function(allData){
return JSON.parse(allData.join("")) as T;
});
console.log(`write data: ${data}`);
request.write(data);
request.end();
return returnObservable;
}
从中我得到以下日志:
exchanging code for tokens: 4/k6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8#
getting targetUrl: https://accounts.google.com/o/oauth2/token
write data: code=4%2Fk6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8%23&redirect_uri=http%3A%2F%2Flocalhost%3A8080&client_id=myCorrectId&client_secret=myCorrectSecret&scope=&grant_type=authorization_code
data pumped: {
"error" : "invalid_request",
"error_description" : "Required parameter is missing: grant_type"
}
所以我要发送以下内容:
code=4%2Fk6Pp7jCPDms2meo0qfINqs0c9FZSjJ7PvGp8mdnh3Y8%23
redirect_uri=http%3A%2F%2Flocalhost%3A8080
client_id=myCorrrectId
client_secret=myCorrectSecret
scope=
grant_type=authorization_code
所以我不明白为什么说我不发送grant_type
如果您不想指定 scope
,则不要附加 "&scope="
。服务器可能将您的请求解释为请求以下范围:
&grant_type=authorization_code
这意味着请求实际上不包含 grant_type
。
非常感谢 João Angelo 的回答(发表在下面的评论中)
确保请求包含此 header:
Content-Type: application/x-www-form-urlencoded
因为 Google 可能允许其他内容类型并且可能会误解有效负载。
代码现在看起来像这样:
private makePostRequest<T>(targetUrl:string, data: string): Rx.Observable<T>{
console.log(`getting targetUrl: ${targetUrl}`);
var urlObject = url.parse(targetUrl);
var options: http.RequestOptions = {
hostname: urlObject.hostname,
port: Number(urlObject.port),
path: urlObject.path,
protocol: "https:",
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
const request = https.request(options);
const returnObservable = Rx.Observable.fromEvent(<any>request, "response")
.take(1)
.flatMap( response => RxNode.fromWritableStream(<any>response))
.do( data => console.log(`data pumped: ${data}`) )
.toArray()
.map(function(allData){
return JSON.parse(allData.join("")) as T;
});
console.log(`write data: ${data}`);
request.write(data);
request.end();
return returnObservable;
}