【问题标题】:How to get Google refresh_token in Javascript API?如何在 Javascript API 中获取 Google refresh_token?
【发布时间】:2015-05-26 07:12:26
【问题描述】:

我正在构建一个系统,人们可以通过验证来阅读他们的 gmail。我在 Python 中使用 OAuth2 在我的网站上运行良好;在谷歌的回复中,我得到了一个access_token、一个token_type、一个expires_in和(最重要的是)一个refresh_token

我现在想在 Javascript 中进行同样的工作(对于我正在使用 Ionic 构建的应用程序)。所以我使用ngCordovaOauth通过以下代码进行身份验证:

$cordovaOauth.google(
    'xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com',
    ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/gmail.readonly'],
    {
        'access_type': 'offline',
        'approval_prompt': 'force'
    }
)
    .then(function(result){
        console.log("Response object -> " + JSON.stringify(result));
    }, function(error){
        console.log('Error -> ' + error);
    });

正如预期的那样,这会在我的手机上产生以下屏幕:

但是在我返回的 json 中没有 refresh_token:

{"access_token":"xxxx.xxxxxxxxxxxx","token_type":"Bearer","expires_in":"3599"}

有人知道为什么我在使用 Javascript api 时没有得到refesh_token 吗?欢迎所有提示!

【问题讨论】:

    标签: javascript cordova oauth gmail ngcordova


    【解决方案1】:

    CordovaOauth 使用的是 OAuth 2.0 的 Implicit grant type,根据规范,它适用于“使用 JavaScript 等脚本语言在浏览器中实现的客户端”。通过这个流程,客户端直接获得一个访问令牌,仅此而已。

    Authorization Code grant type 中,客户端获得一个授权码,然后它会交换访问和刷新令牌,但这也包括客户端本身的身份验证,这就是为什么它在服务器到服务器中完成方式。您不希望在面向最终用户的 JavaScript 代码中公开您的 client_id/client_secret。

    还请查看 Google Documentation 解释不同的场景。

    【讨论】:

    • 感谢您的澄清。那么我是否正确理解我无法从我的 Ionic/Angular 应用程序中获取 refresh_token?
    • 虽然我对 Ionic 了解不多,但需要服务器到服务器的通信才能使用授权代码授权类型,这将导致发出刷新令牌(如果请求) .因此,在用户浏览器中运行的纯 JavaScript 解决方案是行不通的。
    • 好的,这是我的新想法:不要使用隐式授权类型,以便我可以在 javascript 中实际获取授权代码。然后我将获取的授权码发送到我的服务器,并使用我的服务器获取访问令牌和刷新令牌。这对你有意义吗?
    • 理论上是的。您可能无法使用 CordovaOauth,至少在没有修改的情况下(小心!)。
    • “理论上是的。”..这也是用js编写的应用程序的常见路线,还是您会建议不同的路线或技术?
    【解决方案2】:

    为什么您不能使用 Cordova/Ionic/Angular 请求刷新令牌? ...

    我有一个获取刷新令牌、访问令牌等的应用程序。因此我使用了以下代码:

    apiKey                  = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
    clientID                = 'xxxxxxxxxxxxxxxxxxxxxxxxxx2ivu3.apps.googleusercontent.com';
    var notiID              = 0;
    var googleapi           = {
    
    authorize:  function(options) {
                    var deferred = $.Deferred();
                    var authUrl = 'https://accounts.google.com/o/oauth2/auth?' + $.param({
                        client_id: options.client_id,
                        redirect_uri: options.redirect_uri,
                        response_type: 'code',
                        scope: options.scope
                    });
    
                    var authWindow = window.open(authUrl, '_blank', 'location=yes');
                    $(authWindow).on('loadstart', function(e) {
                        var url = e.originalEvent.url;
                        var code = /\?code=(.+)$/.exec(url);
                        var error = /\?error=(.+)$/.exec(url);
    
                        if (code || error) {
                            //Always close the browser when match is found
                            authWindow.close();
                            loadingSpinner();
                        }
    
                        if (code) {
                            $.post('https://accounts.google.com/o/oauth2/token', {
                                code: code[1],
                                client_id: options.client_id,
                                client_secret: options.client_secret,
                                redirect_uri: options.redirect_uri,
                                grant_type: 'authorization_code'
                            }).done(function(data) {
                                deferred.resolve(data);
    
                                $("#loginStatus").html('Name: ' + data.given_name);
                            }).fail(function(response) {
                                deferred.reject(response.responseJSON);
                            });
                        } else if (error) {
                            deferred.reject({
                                error: error[1]
                            });
                        }
                    });
    
                    return deferred.promise();
                }
            };
    

    还有这个用于请求访问和刷新令牌:

    function callGoogle()
    {
    
    //  alert('starting');
        googleapi.authorize({
                            client_id: clientID,
                            client_secret: apiKey,
                            redirect_uri: 'http://localhost',
                            scope: 'https://www.googleapis.com/auth/analytics.readonly'
                            }).done(function(data) {
                                    localStorage.accessToken=data.access_token;
                                    localStorage.refreshToken=data.refresh_token;
                                    // console.log(JSON.stringify(data));
                                    // console.log(localStorage.accessToken);
                                    // console.log(localStorage.refreshToken);
                                    getDataProfile();
    
    
                                    });
    
    }
    

    试一试,如果您需要进一步帮助,请告诉我。为此,您只需要 inappbrowser 和控制台插件。当然还有 jQuery。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2020-01-28
    • 2017-04-29
    相关资源
    最近更新 更多