-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
123 lines (107 loc) · 3.09 KB
/
index.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import Meteor, { Accounts } from '@ajaybhatia/react-native-meteor';
import {
authorizeActionChallengeHandler,
authorizeActionCompletionHandler,
resetPasswordCheckMFARequired,
registrationChallengeHandlerTOTP,
registrationCompletionHandlerTOTP,
resetPasswordChallengeHandler,
registrationChallengeHandlerU2F,
registerCompletionHandlerU2F,
loginChallengeHandler,
loginCompletionHandler,
} from './method-names';
let useU2FAuthorizationCode = function (code) {
if (typeof code !== 'string' || code.length !== 6) {
throw new Error('Invalid Code');
}
return { U2FAuthorizationCode: code };
};
let assembleChallengeCompletionArguments = async function (
finishLoginParams,
code
) {
let { res } = finishLoginParams;
let methodArguments = [];
if (res.method === 'u2f') {
let assertion;
if (code && code.U2FAuthorizationCode) {
/*
We require that the MFA.useU2FAuthorizationCode method is used
even though we just pull the code out to make sure the code isn't
actually an OTP due to a coding error.
*/
let { challengeId, challengeSecret } = finishLoginParams.res;
assertion = { challengeId, challengeSecret, ...code };
} else {
throw new Error('Code must be a U2FAuthorizationCode');
}
methodArguments.push(assertion);
}
if (res.method === 'otp' || res.method === 'totp') {
if (!code) {
throw new Meteor.Error('otp-required', 'An OTP is required');
}
methodArguments.push({ ...res, code });
}
return methodArguments;
};
let finishLogin = (finishLoginParams, code) =>
new Promise(async (resolve, reject) => {
let methodName = loginCompletionHandler();
let methodArguments = await assembleChallengeCompletionArguments(
finishLoginParams,
code
);
Meteor._startLoggingIn();
Meteor.call(methodName, ...methodArguments, (err, result) => {
Meteor._endLoggingIn();
Meteor._handleLoginCallback(err, result);
if (err) {
reject(err);
} else {
resolve();
}
});
});
let loginWithMFA = (username, password) =>
new Promise((resolve, reject) => {
Meteor.call(
loginChallengeHandler(),
username,
Accounts._hashPassword(password),
async (err, res) => {
if (err) {
return reject(err);
}
let finishLoginParams = { res, _type: 'login' };
let doesSupportU2FLogin = false;
resolve({
supportsU2FLogin: doesSupportU2FLogin,
method: res.method,
finishLoginParams,
finishParams: finishLoginParams,
});
}
);
});
let login = (username, password) =>
new Promise((resolve, reject) => {
Meteor.loginWithPassword(username, password, (err) => {
if (err) {
if (err.error === 'mfa-required') {
loginWithMFA(username, password).then(resolve).catch(reject);
} else {
reject(err);
}
} else {
resolve({ method: null });
}
});
});
export default {
useU2FAuthorizationCode,
finishLogin,
loginWithMFA,
login,
};