forked from Differential/reststop2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.js
99 lines (82 loc) · 2.96 KB
/
auth.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
var userQueryValidator = Match.Where(function (user) {
check(user, {
id: Match.Optional(String),
username: Match.Optional(String),
email: Match.Optional(String)
});
if (_.keys(user).length !== 1)
throw new Match.Error("User property must have exactly one field");
return true;
});
var selectorFromUserQuery = function (user) {
if (user.id)
return {_id: user.id};
else if (user.username)
return {username: user.username};
else if (user.email)
return {"emails.address": user.email};
throw new Error("shouldn't happen (validation missed something)");
};
var loginWithPassword = function (options) {
if (!options.password || !options.user)
return undefined; // don't handle
check(options, {user: userQueryValidator, password: String});
var selector = selectorFromUserQuery(options.user);
var user = Meteor.users.findOne(selector);
if (!user)
throw new Meteor.Error(403, "User not found");
if (!user.services || !user.services.password ||
!user.services.password.srp)
throw new Meteor.Error(403, "User has no password set");
// Just check the verifier output when the same identity and salt
// are passed. Don't bother with a full exchange.
var verifier = user.services.password.srp;
var newVerifier = SRP.generateVerifier(options.password, {
identity: verifier.identity, salt: verifier.salt});
if (verifier.verifier !== newVerifier.verifier)
throw new Meteor.Error(403, "Incorrect password");
var stampedLoginToken = Accounts._generateStampedLoginToken();
Meteor.users.update(
user._id, {$push: {'services.resume.loginTokens': stampedLoginToken}});
return {loginToken: stampedLoginToken.token, userId: user._id};
};
_RESTstop.prototype.initAuth = function() {
RESTstop.add('login', {'method': 'POST'}, function() {
var user = {};
if(this.params.user.indexOf('@') == -1) {
user.username = this.params.user;
} else {
user.email = this.params.user;
}
try {
var login = loginWithPassword({
'user': user,
'password': this.params.password
});
} catch(e) {
return [e.error, {success: false, message: e.reason}];
}
// Get the user object
var context = [];
if(login.userId && login.loginToken) {
context.user = Meteor.users.findOne({
_id: login.userId,
"services.resume.loginTokens.token": login.loginToken
});
}
RESTstop._config.onLoggedIn.apply(context);
login.success = true;
return login;
});
RESTstop.add('logout', {'method': 'GET', require_login: true}, function() {
var loginToken = this.params.loginToken;
if(this.request.headers['x-login-token']) {
loginToken = this.request.headers['x-login-token'];
}
// Log the user out
Meteor.users.update(
this.user._id, {$pull: {'services.resume.loginTokens': {token: loginToken}}});
RESTstop._config.onLoggedOut.call(this);
return {success: true, message: "You've been logged out!"};
});
};