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:
3
common/src/models/request/captchaProtectedRequest.ts
Normal file
3
common/src/models/request/captchaProtectedRequest.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export abstract class CaptchaProtectedRequest {
|
||||
captchaResponse: string = null;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.';
|
||||
|
||||
Reference in New Issue
Block a user