javascript - 无法从 OAuth Google API 获取已安装应用程序的访问 token

标签 javascript google-api oauth-2.0 google-oauth extendscript

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

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

然而,我对在 href 标记中找到的完全相同的 URL 进行了 POST 调用。所以,我不确定为什么当我发布到同一个 URL 时,谷歌会告诉我终点已经暂时移动了。这是我用来生成 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);

}

帖子写得很好,但是有人知道为什么这个“临时移动”通知会出现在谷歌的回复中吗?非常感谢任何建议!

编辑:澄清一下,这是我的脚本在原始状态下发出的请求:

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 服务器获得成功的响应。所以,显然我的套接字与谷歌端点交互的方式有问题,但我不确定是什么。是否有可能某些组件需要进行 URI 编码,而其他组件则不需要?这是我正在使用的 cURL:

#!/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,这里是发出网络请求的函数:

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 

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

最佳答案

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

关于javascript - 无法从 OAuth Google API 获取已安装应用程序的访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18619515/

相关文章:

javascript - 在响应式 HTML 中向 PHP 表单添加验证

google-maps - 在Google开发者控制台的 "Accept requests from these HTTP referrers"字段中设置HTTP引用的正确方法

google-analytics - OAuth 2 授权码 - 它的有效期是多久?

authentication - 基于 OAuth 和基于 Token 的身份验证有什么区别?

facebook - Uncaught Error ...FB.Auth.setAuthResponse 仅与 OAuth2 兼容

Javascript 正则表达式替换为不同的值

javascript - 无法按字母顺序自动对按钮进行排序

javascript - 无法在 IE 中选择文本区域中的文本

google-api - Google.Apis.AdExchangeSeller.v2.0

go - ebay API 客户端凭据授权