parse-dashboard 4.2.0-alpha.11 → 4.2.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -30,13 +30,13 @@ function initialize(app, options) {
|
|
|
30
30
|
otpCode: req.body.otpCode
|
|
31
31
|
});
|
|
32
32
|
if (!match.matchingUsername) {
|
|
33
|
-
return cb(null, false, { message: 'Invalid username or password' });
|
|
34
|
-
}
|
|
35
|
-
if (match.otpMissing) {
|
|
36
|
-
return cb(null, false, { message: 'Please enter your one-time password.' });
|
|
33
|
+
return cb(null, false, { message: JSON.stringify({ text: 'Invalid username or password' }) });
|
|
37
34
|
}
|
|
38
35
|
if (!match.otpValid) {
|
|
39
|
-
return cb(null, false, { message: 'Invalid one-time password.' });
|
|
36
|
+
return cb(null, false, { message: JSON.stringify({ text: 'Invalid one-time password.', otpLength: match.otpMissingLength || 6}) });
|
|
37
|
+
}
|
|
38
|
+
if (match.otpMissingLength) {
|
|
39
|
+
return cb(null, false, { message: JSON.stringify({ text: 'Please enter your one-time password.', otpLength: match.otpMissingLength || 6 })});
|
|
40
40
|
}
|
|
41
41
|
cb(null, match.matchingUsername);
|
|
42
42
|
})
|
|
@@ -91,7 +91,7 @@ function authenticate(userToTest, usernameOnly) {
|
|
|
91
91
|
let appsUserHasAccessTo = null;
|
|
92
92
|
let matchingUsername = null;
|
|
93
93
|
let isReadOnly = false;
|
|
94
|
-
let
|
|
94
|
+
let otpMissingLength = false;
|
|
95
95
|
let otpValid = true;
|
|
96
96
|
|
|
97
97
|
//they provided auth
|
|
@@ -104,17 +104,20 @@ function authenticate(userToTest, usernameOnly) {
|
|
|
104
104
|
let usernameMatches = userToTest.name == user.user;
|
|
105
105
|
if (usernameMatches && user.mfa && !usernameOnly) {
|
|
106
106
|
if (!userToTest.otpCode) {
|
|
107
|
-
|
|
107
|
+
otpMissingLength = user.mfaDigits || 6;
|
|
108
108
|
} else {
|
|
109
109
|
const totp = new OTPAuth.TOTP({
|
|
110
110
|
algorithm: user.mfaAlgorithm || 'SHA1',
|
|
111
|
-
secret: OTPAuth.Secret.fromBase32(user.mfa)
|
|
111
|
+
secret: OTPAuth.Secret.fromBase32(user.mfa),
|
|
112
|
+
digits: user.mfaDigits,
|
|
113
|
+
period: user.mfaPeriod,
|
|
112
114
|
});
|
|
113
115
|
const valid = totp.validate({
|
|
114
116
|
token: userToTest.otpCode
|
|
115
117
|
});
|
|
116
118
|
if (valid === null) {
|
|
117
119
|
otpValid = false;
|
|
120
|
+
otpMissingLength = user.mfaDigits || 6;
|
|
118
121
|
}
|
|
119
122
|
}
|
|
120
123
|
}
|
|
@@ -132,7 +135,7 @@ function authenticate(userToTest, usernameOnly) {
|
|
|
132
135
|
return {
|
|
133
136
|
isAuthenticated,
|
|
134
137
|
matchingUsername,
|
|
135
|
-
|
|
138
|
+
otpMissingLength,
|
|
136
139
|
otpValid,
|
|
137
140
|
appsUserHasAccessTo,
|
|
138
141
|
isReadOnly,
|
|
@@ -65,7 +65,19 @@ const generateSecret = ({ app, username, algorithm, digits, period }) => {
|
|
|
65
65
|
secret
|
|
66
66
|
});
|
|
67
67
|
const url = totp.toString();
|
|
68
|
-
|
|
68
|
+
const config = { mfa: secret.base32 };
|
|
69
|
+
config.app = app;
|
|
70
|
+
config.url = url;
|
|
71
|
+
if (algorithm !== 'SHA1') {
|
|
72
|
+
config.mfaAlgorithm = algorithm;
|
|
73
|
+
}
|
|
74
|
+
if (digits != 6) {
|
|
75
|
+
config.mfaDigits = digits;
|
|
76
|
+
}
|
|
77
|
+
if (period != 30) {
|
|
78
|
+
config.mfaPeriod = period;
|
|
79
|
+
}
|
|
80
|
+
return { config };
|
|
69
81
|
};
|
|
70
82
|
const showQR = text => {
|
|
71
83
|
const QRCode = require('qrcode');
|
|
@@ -77,7 +89,10 @@ const showQR = text => {
|
|
|
77
89
|
});
|
|
78
90
|
};
|
|
79
91
|
|
|
80
|
-
const showInstructions = ({ app, username, passwordCopied,
|
|
92
|
+
const showInstructions = ({ app, username, passwordCopied, encrypt, config }) => {
|
|
93
|
+
const {secret, url} = config;
|
|
94
|
+
const mfaJSON = {...config};
|
|
95
|
+
delete mfaJSON.url;
|
|
81
96
|
let orderCounter = 0;
|
|
82
97
|
const getOrder = () => {
|
|
83
98
|
orderCounter++;
|
|
@@ -90,7 +105,7 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,
|
|
|
90
105
|
|
|
91
106
|
console.log(
|
|
92
107
|
`\n${getOrder()}. Add the following settings for user "${username}" ${app ? `in app "${app}" ` : '' }to the Parse Dashboard configuration.` +
|
|
93
|
-
`\n\n ${JSON.stringify(
|
|
108
|
+
`\n\n ${JSON.stringify(mfaJSON)}`
|
|
94
109
|
);
|
|
95
110
|
|
|
96
111
|
if (passwordCopied) {
|
|
@@ -101,14 +116,14 @@ const showInstructions = ({ app, username, passwordCopied, secret, url, encrypt,
|
|
|
101
116
|
|
|
102
117
|
if (secret) {
|
|
103
118
|
console.log(
|
|
104
|
-
`\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
|
|
105
|
-
`\n\n ${secret}` +
|
|
119
|
+
`\n${getOrder()}. Open the authenticator app to scan the QR code above or enter this secret code:` +
|
|
120
|
+
`\n\n ${secret}` +
|
|
106
121
|
'\n\n If the secret code generates incorrect one-time passwords, try this alternative:' +
|
|
107
|
-
`\n\n ${url}` +
|
|
122
|
+
`\n\n ${url}` +
|
|
108
123
|
`\n\n${getOrder()}. Destroy any records of the QR code and the secret code to secure the account.`
|
|
109
124
|
);
|
|
110
125
|
}
|
|
111
|
-
|
|
126
|
+
|
|
112
127
|
if (encrypt) {
|
|
113
128
|
console.log(
|
|
114
129
|
`\n${getOrder()}. Make sure that "useEncryptedPasswords" is set to "true" in your dashboard configuration.` +
|
|
@@ -173,6 +188,7 @@ module.exports = {
|
|
|
173
188
|
const salt = bcrypt.genSaltSync(10);
|
|
174
189
|
data.pass = bcrypt.hashSync(data.pass, salt);
|
|
175
190
|
}
|
|
191
|
+
const config = {};
|
|
176
192
|
if (mfa) {
|
|
177
193
|
const { app } = await inquirer.prompt([
|
|
178
194
|
{
|
|
@@ -182,18 +198,13 @@ module.exports = {
|
|
|
182
198
|
}
|
|
183
199
|
]);
|
|
184
200
|
const { algorithm, digits, period } = await getAlgorithm();
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
data.url = url;
|
|
189
|
-
if (algorithm !== 'SHA1') {
|
|
190
|
-
data.mfaAlgorithm = algorithm;
|
|
191
|
-
}
|
|
192
|
-
showQR(data.url);
|
|
201
|
+
const secret =generateSecret({ app, username, algorithm, digits, period });
|
|
202
|
+
Object.assign(config, secret.config);
|
|
203
|
+
showQR(secret.config.url);
|
|
193
204
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
showInstructions({ app: data.app, username, passwordCopied: true,
|
|
205
|
+
config.user = data.user;
|
|
206
|
+
config.pass = data.pass ;
|
|
207
|
+
showInstructions({ app: data.app, username, passwordCopied: true, encrypt, config });
|
|
197
208
|
},
|
|
198
209
|
async createMFA() {
|
|
199
210
|
console.log('');
|
|
@@ -212,14 +223,9 @@ module.exports = {
|
|
|
212
223
|
]);
|
|
213
224
|
const { algorithm, digits, period } = await getAlgorithm();
|
|
214
225
|
|
|
215
|
-
const {
|
|
216
|
-
showQR(url);
|
|
217
|
-
|
|
226
|
+
const { config } = generateSecret({ app, username, algorithm, digits, period });
|
|
227
|
+
showQR(config.url);
|
|
218
228
|
// Compose config
|
|
219
|
-
|
|
220
|
-
if (algorithm !== 'SHA1') {
|
|
221
|
-
config.mfaAlgorithm = algorithm;
|
|
222
|
-
}
|
|
223
|
-
showInstructions({ app, username, secret, url, config });
|
|
229
|
+
showInstructions({ app, username, config });
|
|
224
230
|
}
|
|
225
231
|
};
|