Javascript 无法从OAuth Google API获取已安装应用程序的访问令牌

Javascript 无法从OAuth Google API获取已安装应用程序的访问令牌,javascript,google-api,oauth-2.0,google-oauth,extendscript,Javascript,Google Api,Oauth 2.0,Google Oauth,Extendscript,我正在创建OAuth身份验证流,以便我安装的应用程序的用户可以访问他们的私有Google电子表格文档。我使用Adobe ExtendScript进行编码,因此无法使用Google提供的Javascript客户端库。我已经读了很多次了,但是在OAuth流的一个方面需要帮助。我可以通过从已安装的应用程序启动浏览器,让用户提交他们的凭据,然后将授权代码复制并粘贴回应用程序中来获取授权代码。但是,当我发布到端点以交换访问令牌的授权代码时,它不起作用。谷歌的回复正文显示: Moved Temporaril

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

Moved Temporarily
The document has moved <A HREF="https://accounts.google.com/o/oauth2/token">here</A>.
这篇文章写得很好,但是有人知道为什么谷歌的回复中会出现这个“临时移动”的通知吗?任何建议都将不胜感激

编辑:只是澄清一下,以下是我的脚本在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编码,而其他组件则不需要?这是我正在使用的卷曲:

#!/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请求的函数:

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\nUnable 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脚本。它需要三个参数,所有字符串:

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端点,您将得到一个类似于JSON的字符串。因此,您必须使用类似于JSON.parse()的东西对其进行解析。

请参见上面的编辑,以获取此问题的答案。本质上,它归结为ExtendScript中不支持SSL的套接字对象。上面的解决方案显示了一种解决方法,使用ExtendScript system.callSystem()方法在OSX上获取cURL,在Windows上获取VBScript。

还尝试使用encodeURIComponent()包装请求对象中使用的所有值。同样的结果。我不知道extendscript,但是如果您不小心通过http而不是https发送了查询,您可能会看到类似的情况。是的,我在您的URL中看到https,但在某些语言中,您必须为http库提供一个额外的参数,使其执行https。@Tim感谢您的建议。好吧,ExtendScript基于Javascript,我使用的特定库使用Socket对象建立网络通信。Socket对象上是否有一个属性/方法可以确保通过https安全地进行通信?@TimBray您对http与https的猜测是正确的。根据Adobe()上的这篇文章,ExtendScript中的本机套接字对象不支持SSL。我需要设计一种不同的方法来从ExtendScript访问SSL。谢谢
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