如何从ember-simple-auth会话的响应头中更新JWT令牌
我正在使用ember-simple-auth & ember-simple-auth-token在Ember上维护会话。我不想使用刷新令牌方法,而是想从每个服务请求的响应头中接收新的jwt令牌。如何从ember-simple-auth会话的响应头中更新JWT令牌
我每次收到服务器的响应时,如何通过更新会话中的jwt令牌来保持会话活动?
这可以完成,但需要延长ember-simple-auth
和ember-simple-auth-token
。不建议使用您的方法,访问令牌和刷新令牌绝对是首选方法。由于您的资源服务器不需要进行身份验证,只需授权和验证令牌,它的规模也会更好。它还增加了一些开销,为每个请求生成一个新的令牌。虽然我不建议这样做当然,这里是它如何可以做到:
正如你已经发现,你不能直接更新会话,但如果你深入到源代码,你会发现,ember-simple-auth
使用一个event来更新它。但是,如果您覆盖/定制authenticator
,此事件将仅适用。可能ember-simple-auth-token
的authenticators/jwt.js
。如果你看看他们的身份证明,你可以看到一个如何update the session的例子。
因此,我建议创建自己的定制JWT令牌认证器,它可以扩展ember-simple-auth-token
的。它可能会添加一个方法来更新session
或更好地处理包含新访问令牌的原始请求标头。
完成后,您可以选择。您可以覆盖自己的adapter
并从那里自己调用该函数,或者更好的选择是覆盖ember-simple-auth
的mixin。
如果覆盖ember-simple-auth
data-adapter-mixin
,这似乎是最好的起点:handleResponse
。如果您覆盖该功能,您应该可以访问原始API响应,您可以从中调用您的更新会话功能。
正如你所看到的,这不是一个微不足道的变化。这绝对是与这些图书馆最初设计的目标背道而驰的,但如果你投入了大量的工作,这应该是可能的。
更新为OP的评论
其实我之前实现这两方面的要求:“1)有会话超时后预先配置的空闲时间2)允许某一组用户代理在和开关的情况下。即时登录用户“。事实证明,使用刷新令牌模型实现起来其实很简单。
要支持#1,刷新令牌过期应设置为注销前空闲时间的长度。例如如果刷新令牌设置为在30分钟内过期并且访问令牌在5分钟内过期。客户端每隔5分钟就会自动获取新的访问令牌(以及可选的刷新令牌),这是基于灵活性的。但是,如果用户离开页面超过30分钟,则刷新令牌将过期,并且需要重新进行身份验证。
对于#2,不幸的是,它确实需要一些重要的ember-simple-auth-token
工作,但它相对容易,而且我已经实施了一些。基本上你创建了一个自定义的认证器,它有一个附加功能来交换和访问具有更新的上下文/状态的新的令牌。见下面我的实现:
ember-simple-auth-token
重写认证:
/**
Provides a public method to call to exchange an access token for an
updated access token with updated data encoded in it. This method
essentially asks the backend to update an access token with different
values. This is, at the moment, is only used to switch the company root
attribute in the token (AKA switch companies for admins).
@param {string} token - The valid access token
@param {object} [headers] - An optional object which can add additional
headers to the request
@param {object} additionalData - An object which contains the data which should be updated on the token. It should look something like this:
```
{
company_root_id: '<UUID of a valid company root>'
}
```
@return {Promise} A promise which is the request. It will either resolve
with the updated session data or reject with the error.
*/
exchangeAccessToken(token, headers, additionalData) {
const data = this.makeRefreshData(token);
Ember.merge(data, additionalData);
return new Ember.RSVP.Promise((resolve, reject) => {
this.makeRequest(this.serverTokenRefreshEndpoint, data, headers).then(response => {
Ember.run(() => {
try {
const sessionData = this.handleAuthResponse(response);
this.trigger('sessionDataUpdated', sessionData);
resolve(sessionData);
} catch(error) {
reject(error);
}
});
}, (xhr, status, error) => {
Ember.Logger.warn(`Access token could not be refreshed - server responded with ${error}.`);
reject();
});
});
}
行动触发代币兑换:
switchCompany(companyId) {
let session = this.get('_session.session');
if(!this.get('isAdministrator')) {
throw new Error('Logged in user is not an administrator, they cannot switch companies.');
}
let token = session.get('authenticated.access_token');
let appInstance = Ember.getOwner(this);
let authorizerName = session.get('authenticator');
let authorizer = appInstance.lookup(authorizerName);
if(!authorizer) {
throw new Error(`Authorizer (${authorizerName}) does not exist`);
}
if(typeof authorizer.exchangeAccessToken !== 'function') {
throw new Error(`Authorizer (${authorizerName}) does not have an \`exchangeAccessToken\` method.`);
}
return authorizer.exchangeAccessToken(token, null, {
company_root_id: companyId
});
}
后端会显然需要扩展到接受刷新令牌附加参数端点,允许用户切换角色,如果授权。
嗨迈克尔, 谢谢你宝贵的建议。我对刷新令牌的想法基于两个要求:1)在预先配置的空闲时间后会话超时。 2)允许特定的用户集合进行代理并在运行中切换登录用户的上下文。正如你所建议的,我正在评估其他方法来完成这些任务,并且不必重写ember-simple-auth的基本实现。如果这些方法失败了,那么将尝试扩展身份验证器和mixin作为最后的手段。 –
@PrajwalBoloor,我更新了我的答案,以展示如何使用刷新令牌模型完成您的需求。 –
我正在接收JWT令牌,作为来自后端服务的每个响应头的一部分。我们的想法是,在认证期间最初设置的到期时间为30分钟,然后在每次与退出交互时尝试捕获新令牌并使用适配器 - > handelResponse方法在会话中更新它。简而言之,我所要做的只是滑动会话。 –
我面临的问题是Ember-simple-auth在session.data.authenticated中存储了令牌和失效时间,在文档中这被称为只读。如果我不允许更新令牌,我怎么能保持会话活着? –