无法从 OAuth Google API 获取已安装应用程序的访问令牌 [英] Cannot get access token from OAuth Google API for installed applications

查看:23
本文介绍了无法从 OAuth Google API 获取已安装应用程序的访问令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建 OAuth 身份验证流程,以便我安装的应用程序的用户可以访问他们的私人 Google 电子表格文档.我正在使用 Adob​​e ExtendScript 进行编码,因此无法使用 Google 提供的 Javascript 客户端库.我已经多次阅读 Google 的 OAuth 2.0 文档安装应用程序,但需要帮助OAuth 流程的一个方面.我可以通过从已安装的应用程序启动浏览器并让用户提交其凭据,然后将授权代码复制并粘贴回应用程序来获取授权代码.但是,当我 POST 到端点以交换访问令牌的授权代码时,它不起作用.来自 google 的响应正文显示了这一点:

I'm creating an OAuth authentication flow so users of my installed application can access their private Google spreadsheet documents. I'm coding with Adobe ExtendScript, so I cannot use the Javascript client libraries Google provides. I've read Google's OAuth 2.0 documentation for installed applications quite a few times, but need help with one aspect of the OAuth flow. I am able to get an authorization code by launching a browser from the installed app, and having the user submit their credentials, and then copy and pasting the authorization code back into the app. However, when I POST to the endpoint for exchanging the authorization code for an access token, it doesn't work. The body of the response from google shows this:

Moved Temporarily
The document has moved <A HREF="https://accounts.google.com/o/oauth2/token">here</A>.

然而,我对在 href 标签中找到的完全相同的 URL 进行了 POST 调用.所以,我不知道为什么当我发布到同一个 URL 时,谷歌会告诉我终点已经暂时移动了.这是我用来生成 POST 的代码.

And yet, I made the POST call to that exact same URL found in the href tag. So, I'm not sure why google would tell me that the end point has moved temporarily when I POSTed to that same URL. Here is the code I'm using to generate the POST.

function getAccessToken(authcode)
{
    var http = require('http'),
        OAuthAccessEndPoint = 'https://accounts.google.com/o/oauth2/token',
        OAuthAccessParams = {};

    OAuthAccessParams['code']             = authcode;
    OAuthAccessParams['client_id']        = '{my_client_id}';
    OAuthAccessParams['client_secret']    = '{my_client_secret}';
    OAuthAccessParams['redirect_uri']     = 'urn:ietf:wg:oauth:2.0:oob';
    OAuthAccessParams['grant_type']       = 'authorization_code';

    var response = http.post(OAuthAccessEndPoint, OAuthAccessParams);

}

这篇文章写得很好,但有人知道为什么这个暂时移动"通知会出现在谷歌的回复中吗?非常感谢任何建议!

The post is made fine, but does anybody know why this 'Moved Temporarily' notice would come up in google's response? Any suggestions are much appreciated!

澄清一下,这是我的脚本在原始文件中提出的请求:

Just to clarify, here is the request my script is making in the raw:

POST /o/oauth2/token HTTP/1.1
User-Agent: Adobe ExtendScript
Accept: */*
Connection: close
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 226

code={authcode}&client_id={my_client_id}&client_secret={my_client_secret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code&

如果我在 cURL 中使用授权代码以及其他参数,我确实会从 Google 的 OAuth 服务器获得成功响应.因此,显然我的套接字与 Google 端点交互的方式出现了问题,但我不确定是什么.是否有可能某些组件需要进行 URI 编码,而其他组件则不需要?这是我正在使用的 cURL:

If I use the authorization code in cURL, along with the other params, I do get a successful response from Google's OAuth servers. So, obviously something is up with the way my sockets are interacting with Google's endpoints, but I'm not sure what. Is it possible that some components need to be URI encoded, while others do not? Here is the cURL I am using:

#!/bin/bash
AUTHCODE="$1"

POSTCONTENT="code=$AUTHCODE&client_id={my_client_id}&client_secret={my_client_secret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code&"

echo $POSTCONTENT

curl -v --data $POSTCONTENT https://accounts.google.com/o/oauth2/token

编辑 2:因此,由于在 Extendscript 中套接字不支持 SSL,我编写了一个使用操作系统级别调用来调用请求的函数.如果在 OSX 上,我们可以假设我们可以访问 cURL,但在 Windows 上,我们必须编写一个 VBScript,通过命令行中的 cscript 主机执行.对于 ExtendScript,这里是发出 Web 请求的函数:

EDIT 2: So, since Sockets do not support SSL in Extendscript, I wrote a function that uses OS level calls to invoke the request. If on OSX, we can assume that we have access to cURL, but on Windows, we have to write a VBScript that gets executed via the cscript host in the command line. For ExtendScript, here is the function that makes the web request:

function webRequest(method, endpoint, query){

    var response = null,
        wincurl  = WORKING_DIR.fsName + '\lib\curl.vbs',
        curlCmd = '';

    try {

        if ( os() == "Win" ) {
            curlCmd = 'cscript "' + wincurl + '" /Method:' + method + ' /URL:' + endpoint + ' /Query:' + query + ' //nologo';
        } else {
            if (method === "POST") {
                curlCmd = 'curl -s -d "' + query + '" ' + endpoint;
            } else if (method === "GET") {
                curlCmd = 'curl -s -G -d "' + query + '" ' + endpoint;
            }
        }

        response = system.callSystem(curlCmd);

    } catch (err) {

        alert("Error
Unable to make a `"+ method +"` request to the network endpoint.  Please try again.");

    }

    return response;

}

function os(){
    var os = system.osName;
    if (!os.length) { os = $.os; }
    app_os =  ( os.indexOf("Win") != -1 )  ?  "Win" : "Mac";
    return app_os;
}

这里是从 ExtendScript 库调用的 VBScript 脚本.它需要三个参数,都是字符串:

And here is the VBScript script that is called from the ExtendScript library. It takes three params, all strings:

set namedArgs = WScript.Arguments.Named

sMethod = namedArgs.Item("Method")
sUrl = namedArgs.Item("URL")
sRequest = namedArgs.Item("Query")

HTTPPost sMethod, sUrl, sRequest

Function HTTPPost(sMethod, sUrl, sRequest)

    set oHTTP = CreateObject("Microsoft.XMLHTTP")  

    If sMethod = "POST" Then
        oHTTP.open "POST", sUrl,false
    ElseIf sMethod = "GET" Then
        oHTTP.open "GET", sUrl,false
    End If

    oHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
    oHTTP.setRequestHeader "Content-Length", Len(sRequest)
    oHTTP.send sRequest

    HTTPPost = oHTTP.responseText

    WScript.Echo HTTPPost

End Function 

您可以在 ExtendScript 中为任何 API 端点使用它,但响应将始终是一个字符串.因此,对于 Google 的 OAuth Endpoints,您将获得一个看起来像 JSON 的字符串.所以,你必须用 JSON.parse() 之类的东西来解析它.

You can use this in ExtendScript for any API endpoint, but the response will always be a string. So, in the case of Google's OAuth Endpoints, you'll get a string that looks like JSON. So, y ou'll have to parse it with something like JSON.parse().

推荐答案

有关此问题的答案,请参阅上面的编辑.本质上,它归结为不支持 SSL 的 ExtendScript 中的 Socket 对象.上面的解决方案显示了使用 ExtendScript system.callSystem() 方法获取 OSX 上的 cURL 和 Windows 上的 VBScript 的解决方法.

See edits above for the answer to this. Essentially it boiled down to Socket objects in ExtendScript not supporting SSL. The solution above shows a workaround by using ExtendScript system.callSystem() method to get at cURL on OSX and a VBScript on Windows.

这篇关于无法从 OAuth Google API 获取已安装应用程序的访问令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆