1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-27 12:36:14 +01:00

two-step login prompts

This commit is contained in:
Kyle Spearrin 2018-05-15 14:21:42 -04:00
parent 9ce758e859
commit e3eea736ed
4 changed files with 94 additions and 17 deletions

11
package-lock.json generated
View File

@ -19,6 +19,12 @@
"integrity": "sha512-MFFKFv2X4iZy/NFl1m1E8uwE1CR96SGwJjgHma09PLtqOWoj3nqeJHMG+P/EuJGVLvC2I6MdQRQsr4TcRduIow==",
"dev": true
},
"@types/readline-sync": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@types/readline-sync/-/readline-sync-1.4.3.tgz",
"integrity": "sha512-YP9NVli96E+qQLAF2db+VjnAUEeZcFVg4YnMgr8kpDUFwQBnj31rPLOVHmazbKQhaIkJ9cMHsZhpKdzUeL0KTg==",
"dev": true
},
"acorn": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
@ -3186,6 +3192,11 @@
"set-immediate-shim": "1.0.1"
}
},
"readline-sync": {
"version": "1.4.9",
"resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.9.tgz",
"integrity": "sha1-PtqOZfI80qF+YTAbHwADOWr17No="
},
"regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",

View File

@ -35,6 +35,7 @@
"devDependencies": {
"@types/commander": "^2.12.2",
"@types/node": "^10.0.8",
"@types/readline-sync": "^1.4.3",
"clean-webpack-plugin": "^0.1.17",
"copy-webpack-plugin": "^4.2.0",
"cross-env": "^5.1.4",
@ -49,6 +50,7 @@
"commander": "2.15.1",
"node-fetch": "2.1.2",
"node-forge": "0.7.1",
"node-localstorage": "1.3.1"
"node-localstorage": "1.3.1",
"readline-sync": "1.4.9"
}
}

View File

@ -1,4 +1,5 @@
import * as program from 'commander';
import * as readline from 'readline-sync';
import { AuthResult } from 'jslib/models/domain/authResult';
@ -10,9 +11,57 @@ export class LoginCommand {
constructor(private authService: AuthService) { }
async run(email: string, password: string, cmd: program.Command) {
if (email == null || email === '') {
email = readline.question('Email Address: ');
}
if (email == null || email.trim() === '') {
return Response.badRequest('Email address is required.');
}
if (email.indexOf('@') === -1) {
return Response.badRequest('Email address is invalid.');
}
if (password == null || password === '') {
password = readline.question('Master Password: ', {
hideEchoBack: true,
mask: '*',
});
}
if (password == null || password === '') {
return Response.badRequest('Master password is required.');
}
try {
const result = await this.authService.logIn(email, password);
// TODO: 2FA
const response = await this.authService.logIn(email, password);
if (response.twoFactor) {
let selectedProvider: any = null;
const twoFactorProviders = this.authService.getSupportedTwoFactorProviders(null);
if (twoFactorProviders.length === 0) {
return Response.badRequest('No providers available for this client.');
}
if (twoFactorProviders.length === 1) {
selectedProvider = twoFactorProviders[0];
} else {
const options = twoFactorProviders.map((p) => p.name);
const i = readline.keyInSelect(options, 'Two-step login method: ', { cancel: 'Cancel' });
if (i < 0) {
return Response.error('Login failed.');
}
selectedProvider = twoFactorProviders[i];
}
const twoFactorToken = readline.question('Two-step login token for ' + selectedProvider.name + ': ');
if (twoFactorToken == null || twoFactorToken === '') {
return Response.badRequest('Token is required.');
}
const twoFactorResponse = await this.authService.logInTwoFactor(selectedProvider.type,
twoFactorToken, false);
if (twoFactorResponse.twoFactor) {
return Response.error('Login failed.');
}
}
return Response.success();
} catch (e) {
return Response.error(e);

View File

@ -46,6 +46,20 @@ export class Program {
// TODO
});
program
.command('lock')
.description('Lock the vault and destroy the current session token.')
.action((cmd) => {
// TODO
});
program
.command('unlock <password>')
.description('Unlock the vault and obtain a new session token.')
.action((cmd) => {
// TODO
});
program
.command('sync')
.description('Sync user\'s vault from server.')
@ -117,23 +131,24 @@ export class Program {
}
private processResponse(response: Response, cmd: program.Command) {
if (response.success) {
if (response.data != null) {
if (response.data.object === 'string') {
process.stdout.write((response.data as StringResponse).data);
} else if (response.data.object === 'list') {
this.printJson((response.data as ListResponse).data, cmd);
} else if (response.data.object === 'template') {
this.printJson((response.data as TemplateResponse).template, cmd);
} else {
this.printJson(response.data, cmd);
}
}
process.exit();
} else {
if (!response.success) {
process.stdout.write(chalk.redBright(response.message));
process.exit(1);
return;
}
if (response.data != null) {
if (response.data.object === 'string') {
process.stdout.write((response.data as StringResponse).data);
} else if (response.data.object === 'list') {
this.printJson((response.data as ListResponse).data, cmd);
} else if (response.data.object === 'template') {
this.printJson((response.data as TemplateResponse).template, cmd);
} else {
this.printJson(response.data, cmd);
}
}
process.exit();
}
private printJson(obj: any, cmd: program.Command) {