获得两个版本的 ember-simple-auth 一起玩

Get two versions of ember-simple-auth to play well together

我们正在使用两个 ember 应用程序,每个应用程序 运行 不同版本的 ember 和 ember-simple-auth,并希望获得 ember-simple-auth 可以很好地与两个版本一起使用。

旧应用程序

新应用

我们正在尝试更改旧版本的会话 API,以便它正确存储访问和刷新令牌,以便新应用程序可以使用它。

到目前为止,我们已经尝试覆盖 setupupdateStore 方法来处理 authenticated 嵌套对象,但仍然 运行 遇到问题。

免责声明 - Patrick Berkeley 和我一起工作。在发布这个我想我会分享的问题后,我们找到了一个解决方案。

为了使 ember-simple-auth 的 cookie 存储的 0.7.3 版本能够与 1.0.0 版本很好地兼容,我们确实必须规范化 cookie 在应用程序中的格式化方式早期版本在几个关键位置,主要围绕 session 对象(the 0.7.3 session 是一个 ObjectProxy,可以在消费应用程序中扩展以创建您自己的自定义会话)。

我们需要重写的方法集中在传递到 cookie 存储以持久保存的数据结构以及恢复会话时返回的内容。关键区别在于版本 0.7.3,access_token 等存储在会话的 content 对象 属性 的顶层。随着 1.0.0。 this 嵌套在 content 中的另一个对象中,属性 名称为 authenticated。因此,我们需要确保在我们假设在顶层设置或获取 access_token 的任何地方,我们应该取而代之的是检索更深一层。考虑到这一点,我们想出了在我们的自定义 session 对象中覆盖这些方法:

// alias access_token to point to new place
access_token: Ember.computed.alias('content.authenticated.access_token'),

// overridden methods to handle v2 cookie structure
restore: function() {
  return new Ember.RSVP.Promise((resolve, reject) => {
    const restoredContent = this.store.restore();
    const authenticator   = restoredContent.authenticated.authenticator;

    if (!!authenticator) {
      delete restoredContent.authenticated.authenticator;
      this.container.lookup(authenticator).restore(restoredContent.authenticated).then(function(content) {
        this.setup(authenticator, content);
        resolve();
      }, () => {
        this.store.clear();
        reject();
      });
    } else {
      this.store.clear();
      reject();
    }
  });
},

updateStore: function() {
  let data = this.content;
  if (!Ember.isEmpty(this.authenticator)) {
    Ember.set(data, 'authenticated', Ember.merge({ authenticator: this.authenticator }, data.authenticated || {}));
  }

  if (!Ember.isEmpty(data)) {
    this.store.persist(data);
  }
},

setup(authenticator, authenticatedContent, trigger) {
  trigger = !!trigger && !this.get('isAuthenticated');

  this.beginPropertyChanges();
  this.setProperties({
    isAuthenticated: true,
    authenticator
  });
  Ember.set(this, 'content.authenticated', authenticatedContent);
  this.bindToAuthenticatorEvents();
  this.updateStore();
  this.endPropertyChanges();

  if (trigger) {
    this.trigger('sessionAuthenticationSucceeded');
  }
},

clear: function(trigger) {
  trigger = !!trigger && this.get('isAuthenticated');

  this.beginPropertyChanges();
  this.setProperties({
    isAuthenticated: false,
    authenticator:   null
  });
  Ember.set(this.content, 'authenticated', {});
  this.store.clear();
  this.endPropertyChanges();

  if (trigger) {
    this.trigger('sessionInvalidationSucceeded');
  }
},

bindToStoreEvents: function() {
  this.store.on('sessionDataUpdated', (content) => {
    const authenticator = content.authenticated.authenticator;

    this.set('content', content);

    if (!!authenticator) {
      delete content.authenticated.authenticator;
      this.container.lookup(authenticator).restore(content.authenticated).then((content) => {
        this.setup(authenticator, content, true);
      }, () => {
        this.clear(true);
      });
    } else {
      this.clear(true);
    }
  });
}.observes('store'),

这让我们完成了大部分工作。我们只需要确保我们使用的身份验证器名称与 1.0.0 上的名称相匹配。我们需要通过初始化程序将身份验证器重命名为 'authenticator:oauth2',而不是 'simple-auth-authenticator:oauth2-password-grant'。这确保了具有较新版本的应用程序将能够在 cookie 会话数据更改时处理正确的身份验证器事件。初始化逻辑很简单:

import OAuth2 from 'simple-auth-oauth2/authenticators/oauth2';

export default {
  name:   'oauth2',
  before: 'simple-auth',

  initialize: function(container) {
    container.register('authenticator:oauth2', OAuth2);
  }
};

以上内容满足了我们的需求——我们可以使用 ember-simple-auth 0.7.3 登录应用程序,并正确存储和格式化 cookie 会话,以便由 [=40] 上的另一个应用程序处理=]-简单验证 1.0.0.

理想情况下,我们会根据业务需要更新应用程序的 Ember 和 Ember 简单授权版本新的代码库)促使我们沿着这条路走下去。