如何确定我在哪个会话上进行 Meteor 中的 OAuth 重新身份验证
How to determine which session I'm on for OAuth reauthentication in Meteor?
我已经编写了自己的自定义身份验证来使用我们的企业OAuth解决方案。 这会导致向我发送 OAuth 访问和刷新令牌。然后,我可以将这些令牌存储在 Meteor 数据库的用户集合中,但是当我想执行重新身份验证时,我需要能够找到正确的会话,以便能够找到我应该使用哪个 OAuth 令牌来刷新它(如果需要(。 由于用户可以从多个设备登录,这使事情复杂化。
这是我用来存储令牌并在服务器端发送结果的代码:
var userId = null;
var user = Meteor.users.findOne({username: userName});
if (!user) {
userId = Meteor.users.insert({username: userName});
} else {
userId = user._id;
}
logger.info("User logged in: " + userId);
var initToken = Accounts._generateStampedLoginToken();
var token = Accounts._hashStampedToken(initToken);
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
// Need way to bind oath.loginTokens with Meteor resume token
Meteor.users.update(userId,
{$push: {'services.oauth.loginTokens': token}}
);
var rslt = {
userId: userId
};
return(rslt);
这是数据库中的结果记录:
"services" : {
"oauth" : {
"loginTokens" : [
{
"when" : ISODate("2014-06-17T17:51:24.635Z"),
"hashedToken" : "ErcosEo9rD+IuT3EyFb3DFS8Bf0enwLzkCIf/nP1JFE=",
"accessToken" : "bhafr3WBDS67EmZ9hFE20af83BJRPFQQS8NGpMlSH6NHVCOiTeTuTJ",
"refreshToken" : "enOAFkBcxB88FlATUh2m0E5NLLG0y8AojyIH5gItnJXdU6",
"ttl" : 3600
}
]
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2014-06-17T17:51:24.637Z"),
"hashedToken" : "uhRZpGdBHnAVKvgBEm7oSWsdflOGRI2YrR9Q21iqjzp+Xc="
}
]
}
},
"username" : "lous"
从上面可以看到,我需要关闭其中一个令牌值,以找到正确的 oauth 信息以进行可能的刷新。在客户端,然后我执行如下所示的操作,但问题是 validateResult
中返回的令牌与存储在数据库中的令牌不同,因此我无法跟踪哪个会话是我的。
Template.login.events({
'submit #login-form': function(e,t) {
e.preventDefault();
var id = t.find('#login-id').value,
password = t.find('#login-password').value;
var req = {id: id, password: password};
Accounts.callLoginMethod({
methodArguments: [req],
validateResult: function (result) {
var token = result.token;
window.localStorage.setItem('token', token);
subscribeToRequests();
$.mobile.changePage('#landingPage', {transition: 'slidefade'});
},
userCallback: function(error) {
if (error) {
console.log("Error: " + error.message);
alert("Login Failure");
}
}
});
return false;
}
});
为什么令牌不一样?关于如何解决这个问题的任何建议? 那么,一旦我确实在客户端存储了令牌,Meteor 是否提供了一种开箱即用的方式来测试令牌的有效性? 这是我用来尝试这样做的findUser方法:
Meteor.methods({
findUser: function(token) {
var user = null;
var hashedToken = Accounts._hashLoginToken(token);
if (this.userId) {
//TODO need user object to include token to do TTL check and reauth if necessary
user = Meteor.users.findOne({_id:this.userId});
var result = refreshUser(user);
if (result.err) {
throw { name: 'System Error', message: 'The following error occurred: ' + result.err
};
}
} else {
throw { name: 'System Error', message: 'No userId available. Please try again.'
};
}
return user;
}
});
在 findUser
方法中,可以调用 Accounts._getLoginToken(this.connection.id)
来获取连接的当前登录令牌。然后,您可以查找与此值关联的 OAuth 访问令牌。
至于您关于为什么客户端上的result.token
与数据库中的不同的原始问题:我认为您正在将未散列令牌(result.token
(与存储在数据库中的散列令牌进行比较。如果是这种情况,您可以将result.token
传递给服务器并通过Accounts._hashLoginToken
传递,然后再在数据库中查找它。
这有意义吗?
以下是我最终如何将我的OAuth令牌与Meteor会话令牌对齐的方式。
我在服务器端创建了以下Meteor.methods
,我的客户端只是在我的Accounts.callLoginMethod
validateResult
调用updateToken
,因此可以通过@emily答案中描述的方法找到我的 oauth 令牌。
每当应用程序启动或刷新时,它都会调用reauthenticateUser
,最后,当用户记录我们的或会话超时到期时,它会调用logoutUser
。
updateToken: function() {
// Update oauth hash token with correct hashed token
var user = Meteor.users.findOne({'_id': this.userId});
var hashedToken = Accounts._getLoginToken(this.connection.id);
// Get last element for OAuth array (safely presuming the last one is the last oauth from current call stack) and update hashedToken
var oauthObj = _.last(user.services.oauth.loginTokens);
Meteor.users.update({'services.oauth.loginTokens': {$elemMatch: {hashedToken: oauthObj.hashedToken}}}, {$set: {'services.oauth.loginTokens.$.hashedToken': hashedToken}});
},
reauthenticateUser: function() {
var user = null;
if (this.userId) {
var hashedToken = Accounts._getLoginToken(this.connection.id);
user = Meteor.users.findOne({$and: [{'_id': this.userId}, {'services.oauth.loginTokens': {$elemMatch: {hashedToken: hashedToken}}}]});
// Get specific oauthTokens (keep in mind multiples per client)
var oauthTokens = _.findWhere(user.services.oauth.loginTokens, {'hashedToken': hashedToken});
var result = refreshUser(this.userId, user.username, oauthTokens);
if (result.err) {
throw { name: 'System Error', message: 'The following error occurred: ' + result.err
};
}
} else {
throw { name: 'System Error', message: 'No userId available. Please try again.'
};
}
return user;
},
logoutUser: function() {
var hashedToken = Accounts._getLoginToken(this.connection.id);
// Remove orphaned Oauth tokens
Meteor.users.update(
{$and: [{'_id': this.userId}, {'services.oauth.loginTokens': {$elemMatch: {hashedToken: hashedToken}}}]},
{$pull: {'services.oauth.loginTokens': {'hashedToken':hashedToken}
}});
return true;
}
一旦我就位了,我很容易在刷新 oauth 令牌后更新它们,或者在用户注销后删除它们。
我不是meteorJS开发人员,但我会尝试建议解决问题的方法。
使用 npm 安装 meteor-cookie 安装 meteor-cookie。
然后:
var initToken = Cookie.get('initToken');
if(!initToken) {
initToken = Accounts._generateStampedLoginToken();
Cookie.set('initToken', initToken, {days: 30});
}
var token = Accounts._hashStampedToken(initToken);
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
或:
var token = Cookie.get('token');
if(!token) {
var initToken = Accounts._generateStampedLoginToken();
token = Accounts._hashStampedToken(initToken);
Cookie.set('token', token, {days: 30});
}
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
也许我的添加中有错误,但我认为您已经理解了诀窍。(:
- Meteor-将选定窗体中的对象添加到集合中
- 将Meteor中的base64 PDF作为电子邮件附件
- 当数据库中的某些内容发生变化时调用HTTP方法Meteor.js
- 从Meteor中的数组中检索字符串
- 如何通过在Meteor中导入不同文件中的es6类来正确使用它们
- 通过Meteor中的ReactiveVar传递数组
- Meteor中的文本复制
- 根据Meteor集合中的元素数量更改css
- 如何在新的Meteor Collection文档中设置服务器上的created_on字段
- Meteor:引用不同目录中的其他javascript类
- 如何在 Meteor 中的 Mongo 查询中使用变量作为字段名称
- 集合中的Meteor Full Calendar事件数组未呈现
- 从客户端 JavaScript 中的 Meteor 集合中获取数据
- 如何更正 NginX 反向代理配置中的 Meteor 基本网址
- 更改事件中的 METEOR 仅在您单击文本区域后才会在文本区域上触发
- Meteor 1.2.1 版本 服务器代码中的 Meteor.method({}) 不起作用
- 发布中的 Meteor find() 返回数据,尽管选择键为空
- MVVM 模型中的 Meteor on Rails 集成
- 访问Jasmine中的Meteor模板帮助程序函数进行集成测试
- Mongoose中的Meteor Simple模式验证器