尝试使用Google OAuth进行身份验证并收到错误"缺少必需参数:grant_type"

时间:2016-11-11 10:09:12

标签: node.js oauth google-oauth google-authentication google-oauth2

我正在尝试创建一个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

2 个答案:

答案 0 :(得分:0)

如果您不想指定scope,请不要附加"&scope="。服务器可能会将您的请求解释为要求范围:

&grant_type=authorization_code

这意味着请求实际上不包含grant_type

答案 1 :(得分:0)

非常感谢João Angelo这个答案(在下面的评论中发布)

确保请求包含此标头: 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;
}