简体   繁体   English

Firefox上的Ember简单身份验证:身份验证引发错误

[英]Ember Simple Auth on Firefox: authentication throws Error

I am extending Ember Simple Auth's base authentication class to allow authentication with Google. 我正在扩展Ember Simple Auth的基本身份验证类,以允许通过Google进行身份验证。 So far, it works on Safari 8 and Chrome 41 (both on Yosemite) with no errors. 到目前为止,它可以在Safari 8和Chrome 41(均在优胜美地上使用)上正常运行,没有错误。 However, on Firefox 35, it throws an Error that does not occur on the other browsers. 但是,在Firefox 35上,它将引发在其他浏览器上不会发生的错误。 Here is my Google authenticator class: 这是我的Google身份验证器类:

App.GoogleAuthenticator = SimpleAuth.Authenticators.Base.extend({
    // constants for Google API
    GAPI_CLIENT_ID: 'the client id',
    GAPI_SCOPE: ['email'],
    GAPI_TOKEN_VERIFICATION_ENDPOINT: 'https://www.googleapis.com/oauth2/v2/tokeninfo',

    // method for scheduleing a single token refresh
    // time in milliseconds
    scheduleSingleTokenRefresh: function(time) {
        var self = this;
        return new Ember.RSVP.Promise(function(resolve, reject) {
            Ember.run.later(self, function() {
                gapi.auth.authorize({
                    client_id: self.GAPI_CLIENT_ID,
                    scope: self.GAPI_SCOPE,
                    immediate: true
                }, function(data) {
                    if (data && !data.error) {
                        resolve(data);
                    } else {
                        reject((data || {}).error);
                    }
                });
            }, time);
        });
    },
    // WIP: recursive method that reschedules another token refresh after the previous scheduled one was fulfilled
    // usage: scheduleTokenRefreshes(time until token should refresh for the first time, time between subsequent refreshes)
    // usage: scheduleTokenRefreshes(time between refreshes)
    scheduleTokenRefreshes: function(time1, time2) {
        var self = this;
        // if there is a time2, schedule a single refresh, wait for it to be fulfilled, then call myself to schedule again
        if (!Ember.isEmpty(time2)) {
            self.scheduleSingleTokenRefresh(time1)
            .then(function() {
                self.scheduleTokenRefreshes(time2);
            });
        // if there isn't a time2, simply schedule a single refresh, then call myself to schedule again
        } else {
            self.scheduleSingleTokenRefresh(time1)
            .then(function() {
                self.scheduleTokenRefreshes(time1);
            });
        }
    },

    // method that restores the session on reload
    restore: function(data) {
        var self = this;
        return new Ember.RSVP.Promise(function(resolve, reject) {
            console.log(data);
            if (Ember.isEmpty(data.access_token)) {
                reject();
                return;
            }
            // schedule a refresh 15 minutes before it expires or immediately if it expires in < 15
            var timeNow = Math.floor(Date.now() / 1000);
            var expiresAt = +data.expires_at;
            var timeDifference = expiresAt - timeNow;
            var schedulingDelay = Math.floor(timeDifference - 15 * 60);
            schedulingDelay = schedulingDelay < 0 ? 0 : schedulingDelay;
            self.scheduleTokenRefreshes(schedulingDelay * 1000, 45 * 60);
            resolve(data);
        });
    },
    // method that authenticates
    authenticate: function() {
        var self = this;
        return new Ember.RSVP.Promise(function(resolve, reject) {
            gapi.auth.authorize({
                client_id: self.GAPI_CLIENT_ID,
                scope: self.GAPI_SCOPE
            }, function(data) {
                if (data && !data.error) {
                    // schedule a refresh in 45 minutes
                    var schedulingDelay = 45 * 60;
                    self.scheduleTokenRefreshes(schedulingDelay * 1000);
                    resolve(data);
                } else {
                    reject((data || {}).error);
                }
            });
        });
    },
    // method that logs the user out and revokes the token
    invalidate: function(data) {
        var self = this;
        return new Ember.RSVP.Promise(function(resolve, reject) {
            // send a GET request to revoke the token
            Ember.$.ajax({
                type: 'GET',
                url: 'https://accounts.google.com/o/oauth2/revoke?token=' + self.get('session.access_token'),
                contentType: 'application/json',
                dataType: 'jsonp'
            })
            .done(function(successData) {
                resolve(successData);
            })
            .fail(function(error) {
                reject(error);
            });
        });
    }
});

When the popup window closes after a successful login on Google's end, this error appears on Firefox's console: 在Google端成功登录后,当弹出窗口关闭时,此错误将显示在Firefox的控制台上:

Error: Assertion Failed: Error: Permission denied to access property 'toJSON' ember.js:13749
"__exports__.default<.persist@http://127.0.0.1/~jonchan/test/bower_components/ember-simple-auth/simple-auth.js:1524:1
__exports__.default<.updateStore@http://127.0.0.1/~jonchan/test/bower_components/ember-simple-auth/simple-auth.js:1195:11
__exports__.default<.setup@http://127.0.0.1/~jonchan/test/bower_components/ember-simple-auth/simple-auth.js:1149:9
__exports__.default<.authenticate/</<@http://127.0.0.1/~jonchan/test/bower_components/ember-simple-auth/simple-auth.js:1066:13
tryCatch@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:47982:16
invokeCallback@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:47994:17
publish@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:47965:11
@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:29462:9
Queue.prototype.invoke@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:848:11
Queue.prototype.flush@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:913:13
DeferredActionQueues.prototype.flush@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:718:13
Backburner.prototype.end@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:143:11
createAutorun/backburner._autorun<@http://127.0.0.1/~jonchan/test/bower_components/ember/ember.js:546:9
" ember.js:29488

Here is the version information: 这是版本信息:

DEBUG: Ember             : 1.9.1
DEBUG: Ember Data        : 1.0.0-beta.14.1
DEBUG: Handlebars        : 2.0.0
DEBUG: jQuery            : 2.1.3
DEBUG: Ember Simple Auth : 0.7.2

The most confounding thing is that this only appears on Firefox. 最令人困惑的是,它仅出现在Firefox上。 Is it a bug in Ember Simple Auth or Ember? 它是Ember Simple Auth还是Ember中的错误? How do I fix it? 我如何解决它?

I do not know about only Firefox throwing an error (I've had a similar error with Chrome 40), but there is a bug in ember-simple-auth 0.7.2 with Ember 1.9 that prohibits sending an actual error response in the authenticate method in the authenticator. 我不只知道Firefox会引发错误(我在Chrome 40中也遇到过类似的错误),但是使用Ember 1.9的ember-simple-auth 0.7.2中存在一个错误,该错误禁止在authenticate发送实际的错误响应身份验证器中的方法。

If you return reject() in the rejection function of authenticate it will not throw an additional error. 如果您在authenticate的拒绝函数中返回reject() ,则不会引发其他错误。 This will however not propagate the errorstatus or message, so I consider this a bug. 但是,这不会传播错误状态或消息,因此我认为这是一个错误。

A work-around was proposed on github about this issue by setting Ember.onerror=Ember.K temporarily so additional errors will not be propagated, although it will propagate the original authenticate rejection with the error-status. 在github上针对此问题提出了一种解决方法,方法是暂时设置Ember.onerror=Ember.K以便不会传播其他错误,尽管它将传播带有错误状态的原始authenticate拒绝。

The issue in the github repo only mentions problems with testing this, but I've had this problem in normal code. github存储库中的问题仅提到测试此问题,但是我在普通代码中遇到了此问题。

see: https://github.com/simplabs/ember-simple-auth/issues/407 参见: https : //github.com/simplabs/ember-simple-auth/issues/407

Turns out the error was on the resolve part of the authenticate method. 原来错误是在authenticate方法的resolve部分上。 Here is what fixed it: 这是解决问题的方法:

App.GoogleAuthenticator = SimpleAuth.Authenticators.Base.extend({
    authenticate: function() {
        return new Ember.RSVP.Promise(function(resolve, reject) {
            gapi.auth.authorize({
                client_id: 'the client id',
                scope: ['the scopes'],
            }, function(data) {
                if (data && !data.error) {
                    resolve({
                        access_token: data.access_token // !! passing the entire 'data' object caused the error somehow
                    });
                } else {
                    reject((data || {}).error);
                }
            });
        });
    },
    // ...
});

I'm still not quite sure why this caused the error. 我仍然不太确定为什么这会导致错误。 Perhaps the Google API's response (in its entirety) is somehow incompatible with Ember Simple Auth. 也许Google API的响应(整体上)与Ember Simple Auth不兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM