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

Feature/use hcaptcha on register if bot (#434)

* Parse captcha required from error messages

CaptchaProtectedAttribute produces an error with captcha information.
We want to parse that data out to make it easily accessible to components

* Don't show error on catpcha

The component should hande this situation.

* Add captchaResponse to captcha protected api endpoints

* Extract captcha logic to abstract base class

* Add captcha to register

* linter fixes

* Make sure to log Captcha required responses

* Match file naming convention

* Separate import into logical groups by folder

* PR review
This commit is contained in:
Matt Gibson
2021-07-22 12:28:45 -05:00
committed by GitHub
parent ea0c8267d4
commit e9d9cd0182
8 changed files with 117 additions and 64 deletions

View File

@@ -0,0 +1,3 @@
export abstract class CaptchaProtectedRequest {
captchaResponse: string = null;
}

View File

@@ -3,28 +3,18 @@ import { ReferenceEventRequest } from './referenceEventRequest';
import { KdfType } from '../../enums/kdfType';
export class RegisterRequest {
name: string;
email: string;
masterPasswordHash: string;
import { CaptchaProtectedRequest } from './captchaProtectedRequest';
export class RegisterRequest implements CaptchaProtectedRequest {
masterPasswordHint: string;
key: string;
keys: KeysRequest;
token: string;
organizationUserId: string;
kdf: KdfType;
kdfIterations: number;
referenceData: ReferenceEventRequest;
constructor(email: string, name: string, masterPasswordHash: string, masterPasswordHint: string, key: string,
kdf: KdfType, kdfIterations: number, referenceData: ReferenceEventRequest) {
this.name = name;
this.email = email;
this.masterPasswordHash = masterPasswordHash;
constructor(public email: string, public name: string, public masterPasswordHash: string,
masterPasswordHint: string, public key: string, public kdf: KdfType, public kdfIterations: number,
public referenceData: ReferenceEventRequest, public captchaResponse: string) {
this.masterPasswordHint = masterPasswordHint ? masterPasswordHint : null;
this.key = key;
this.kdf = kdf;
this.kdfIterations = kdfIterations;
this.referenceData = referenceData;
}
}

View File

@@ -1,8 +1,9 @@
import { TwoFactorProviderType } from '../../enums/twoFactorProviderType';
import { CaptchaProtectedRequest } from './captchaProtectedRequest';
import { DeviceRequest } from './deviceRequest';
export class TokenRequest {
export class TokenRequest implements CaptchaProtectedRequest {
email: string;
masterPasswordHash: string;
code: string;
@@ -10,14 +11,10 @@ export class TokenRequest {
redirectUri: string;
clientId: string;
clientSecret: string;
token: string;
provider: TwoFactorProviderType;
remember: boolean;
captchaToken: string;
device?: DeviceRequest;
constructor(credentials: string[], codes: string[], clientIdClientSecret: string[], provider: TwoFactorProviderType,
token: string, remember: boolean, captchaToken: string, device?: DeviceRequest) {
constructor(credentials: string[], codes: string[], clientIdClientSecret: string[], public provider: TwoFactorProviderType,
public token: string, public remember: boolean, public captchaResponse: string, device?: DeviceRequest) {
if (credentials != null && credentials.length > 1) {
this.email = credentials[0];
this.masterPasswordHash = credentials[1];
@@ -29,11 +26,7 @@ export class TokenRequest {
this.clientId = clientIdClientSecret[0];
this.clientSecret = clientIdClientSecret[1];
}
this.token = token;
this.provider = provider;
this.remember = remember;
this.device = device != null ? device : null;
this.captchaToken = captchaToken;
}
toIdentityToken(clientId: string) {
@@ -73,8 +66,8 @@ export class TokenRequest {
obj.twoFactorRemember = this.remember ? '1' : '0';
}
if (this.captchaToken != null) {
obj.captchaResponse = this.captchaToken;
if (this.captchaResponse != null) {
obj.captchaResponse = this.captchaResponse;
}

View File

@@ -1,9 +1,13 @@
import { Utils } from '../../misc/utils';
import { BaseResponse } from './baseResponse';
export class ErrorResponse extends BaseResponse {
message: string;
validationErrors: { [key: string]: string[]; };
statusCode: number;
captchaRequired: boolean;
captchaSiteKey: string;
constructor(response: any, status: number, identityResponse?: boolean) {
super(response);
@@ -20,6 +24,8 @@ export class ErrorResponse extends BaseResponse {
if (errorModel) {
this.message = this.getResponseProperty('Message', errorModel);
this.validationErrors = this.getResponseProperty('ValidationErrors', errorModel);
this.captchaSiteKey = this.validationErrors?.HCaptcha_SiteKey?.[0];
this.captchaRequired = !Utils.isNullOrWhitespace(this.captchaSiteKey);
} else {
if (status === 429) {
this.message = 'Rate limit exceeded. Try again later.';