1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 15:53:27 +00:00

[Captcha] Failed login attempts (#698)

* [Captcha] Failed login attempts

* Fix logIn.strategy test

* Updated with the stark majority of requested changes

* Fix typo

* Unused import
This commit is contained in:
Vincent Salucci
2022-03-02 19:47:57 -06:00
committed by GitHub
parent adfc2f234d
commit 48a4c27fe7
7 changed files with 124 additions and 47 deletions

View File

@@ -24,6 +24,7 @@ import {
PasswordLogInCredentials,
SsoLogInCredentials,
} from "jslib-common/models/domain/logInCredentials";
import { TokenRequestTwoFactor } from "jslib-common/models/request/identityToken/tokenRequest";
import { TwoFactorEmailRequest } from "jslib-common/models/request/twoFactorEmailRequest";
import { UpdateTempPasswordRequest } from "jslib-common/models/request/updateTempPasswordRequest";
import { ErrorResponse } from "jslib-common/models/response/errorResponse";
@@ -69,6 +70,8 @@ export class LoginCommand {
let clientId: string = null;
let clientSecret: string = null;
let selectedProvider: any = null;
if (options.apikey != null) {
const apiIdentifiers = await this.apiIdentifiers();
clientId = apiIdentifiers.clientId;
@@ -177,39 +180,17 @@ export class LoginCommand {
);
}
if (response.captchaSiteKey) {
const badCaptcha = Response.badRequest(
"Your authentication request appears to be coming from a bot\n" +
"Please use your API key to validate this request and ensure BW_CLIENTSECRET is correct, if set.\n" +
"(https://bitwarden.com/help/cli-auth-challenges)"
);
const credentials = new PasswordLogInCredentials(email, password);
const handledResponse = await this.handleCaptchaRequired(twoFactor, credentials);
try {
const captchaClientSecret = await this.apiClientSecret(true);
if (Utils.isNullOrWhitespace(captchaClientSecret)) {
return badCaptcha;
}
const secondResponse = await this.authService.logIn(
new PasswordLogInCredentials(email, password, captchaClientSecret, {
provider: twoFactorMethod,
token: twoFactorToken,
remember: false,
})
);
response = secondResponse;
} catch (e) {
if (
(e instanceof ErrorResponse || e.constructor.name === "ErrorResponse") &&
(e as ErrorResponse).message.includes("Captcha is invalid")
) {
return badCaptcha;
} else {
throw e;
}
// Error Response
if (handledResponse instanceof Response) {
return handledResponse;
} else {
response = handledResponse;
}
}
if (response.requiresTwoFactor) {
let selectedProvider: any = null;
const twoFactorProviders = this.twoFactorService.getSupportedProviders(null);
if (twoFactorProviders.length === 0) {
return Response.badRequest("No providers available for this client.");
@@ -276,11 +257,30 @@ export class LoginCommand {
}
}
response = await this.authService.logInTwoFactor({
response = await this.authService.logInTwoFactor(
{
provider: selectedProvider.type,
token: twoFactorToken,
remember: false,
},
null
);
}
if (response.captchaSiteKey) {
const twoFactorRequest: TokenRequestTwoFactor = {
provider: selectedProvider.type,
token: twoFactorToken,
remember: false,
});
};
const handledResponse = await this.handleCaptchaRequired(twoFactorRequest);
// Error Response
if (handledResponse instanceof Response) {
return handledResponse;
} else {
response = handledResponse;
}
}
if (response.requiresTwoFactor) {
@@ -435,6 +435,48 @@ export class LoginCommand {
}
}
private async handleCaptchaRequired(
twoFactorRequest: TokenRequestTwoFactor,
credentials: PasswordLogInCredentials = null
): Promise<AuthResult | Response> {
const badCaptcha = Response.badRequest(
"Your authentication request has been flagged and will require user interaction to proceed.\n" +
"Please use your API key to validate this request and ensure BW_CLIENTSECRET is correct, if set.\n" +
"(https://bitwarden.com/help/cli-auth-challenges)"
);
try {
const captchaClientSecret = await this.apiClientSecret(true);
if (Utils.isNullOrWhitespace(captchaClientSecret)) {
return badCaptcha;
}
let authResultResponse: AuthResult = null;
if (credentials != null) {
credentials.captchaToken = captchaClientSecret;
credentials.twoFactor = twoFactorRequest;
authResultResponse = await this.authService.logIn(credentials);
} else {
authResultResponse = await this.authService.logInTwoFactor(
twoFactorRequest,
captchaClientSecret
);
}
return authResultResponse;
} catch (e) {
if (
e instanceof ErrorResponse ||
(e.constructor.name === "ErrorResponse" &&
(e as ErrorResponse).message.includes("Captcha is invalid"))
) {
return badCaptcha;
} else {
return Response.error(e);
}
}
}
private getPasswordStrengthUserInput() {
let userInput: string[] = [];
const atPosition = this.email.indexOf("@");