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:
@@ -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("@");
|
||||
|
||||
Reference in New Issue
Block a user