mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 01:03:35 +00:00
Feature/use hcaptcha if bot (#430)
* Handle hcaptch required identity response * Refactor iframe component for captcha and webauthn * Send captcha token to server * Add captcha callback * Clear captcha state * Remove captcha storage * linter fixes * Rename iframe components to include IFrame * Remove callback in favor of extenting submit * Limit publickey credentials access * Use captcha bypass token to bypass captcha for twofactor auth flows * Linter fixes * Set iframe version in components
This commit is contained in:
@@ -87,6 +87,7 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
clientSecret: string;
|
||||
twoFactorProvidersData: Map<TwoFactorProviderType, { [key: string]: string; }>;
|
||||
selectedTwoFactorProviderType: TwoFactorProviderType = null;
|
||||
captchaToken: string;
|
||||
|
||||
private key: SymmetricCryptoKey;
|
||||
|
||||
@@ -120,14 +121,14 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
TwoFactorProviders[TwoFactorProviderType.Yubikey].description = this.i18nService.t('yubiKeyDesc');
|
||||
}
|
||||
|
||||
async logIn(email: string, masterPassword: string): Promise<AuthResult> {
|
||||
async logIn(email: string, masterPassword: string, captchaToken?: string): Promise<AuthResult> {
|
||||
this.selectedTwoFactorProviderType = null;
|
||||
const key = await this.makePreloginKey(masterPassword, email);
|
||||
const hashedPassword = await this.cryptoService.hashPassword(masterPassword, key);
|
||||
const localHashedPassword = await this.cryptoService.hashPassword(masterPassword, key,
|
||||
HashPurpose.LocalAuthorization);
|
||||
return await this.logInHelper(email, hashedPassword, localHashedPassword, null, null, null, null, null,
|
||||
key, null, null, null);
|
||||
key, null, null, null, captchaToken);
|
||||
}
|
||||
|
||||
async logInSso(code: string, codeVerifier: string, redirectUrl: string): Promise<AuthResult> {
|
||||
@@ -146,7 +147,7 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
remember?: boolean): Promise<AuthResult> {
|
||||
return await this.logInHelper(this.email, this.masterPasswordHash, this.localMasterPasswordHash, this.code,
|
||||
this.codeVerifier, this.ssoRedirectUrl, this.clientId, this.clientSecret, this.key, twoFactorProvider,
|
||||
twoFactorToken, remember);
|
||||
twoFactorToken, remember, this.captchaToken);
|
||||
}
|
||||
|
||||
async logInComplete(email: string, masterPassword: string, twoFactorProvider: TwoFactorProviderType,
|
||||
@@ -272,7 +273,7 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
|
||||
private async logInHelper(email: string, hashedPassword: string, localHashedPassword: string, code: string,
|
||||
codeVerifier: string, redirectUrl: string, clientId: string, clientSecret: string, key: SymmetricCryptoKey,
|
||||
twoFactorProvider?: TwoFactorProviderType, twoFactorToken?: string, remember?: boolean): Promise<AuthResult> {
|
||||
twoFactorProvider?: TwoFactorProviderType, twoFactorToken?: string, remember?: boolean, captchaToken?: string): Promise<AuthResult> {
|
||||
const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(email);
|
||||
const appId = await this.appIdService.getAppId();
|
||||
const deviceRequest = new DeviceRequest(appId, this.platformUtilsService);
|
||||
@@ -300,24 +301,27 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
let request: TokenRequest;
|
||||
if (twoFactorToken != null && twoFactorProvider != null) {
|
||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret, twoFactorProvider,
|
||||
twoFactorToken, remember, deviceRequest);
|
||||
twoFactorToken, remember, captchaToken, deviceRequest);
|
||||
} else if (storedTwoFactorToken != null) {
|
||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret, TwoFactorProviderType.Remember,
|
||||
storedTwoFactorToken, false, deviceRequest);
|
||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret,
|
||||
TwoFactorProviderType.Remember, storedTwoFactorToken, false, captchaToken, deviceRequest);
|
||||
} else {
|
||||
request = new TokenRequest(emailPassword, codeCodeVerifier, clientIdClientSecret, null,
|
||||
null, false, deviceRequest);
|
||||
null, false, captchaToken, deviceRequest);
|
||||
}
|
||||
|
||||
const response = await this.apiService.postIdentityToken(request);
|
||||
|
||||
this.clearState();
|
||||
const result = new AuthResult();
|
||||
result.twoFactor = !(response as any).accessToken;
|
||||
result.captchaSiteKey = (response as any).siteKey;
|
||||
if (!!result.captchaSiteKey) {
|
||||
return result;
|
||||
}
|
||||
result.twoFactor = !!(response as any).twoFactorProviders2;
|
||||
|
||||
if (result.twoFactor) {
|
||||
// two factor required
|
||||
const twoFactorResponse = response as IdentityTwoFactorResponse;
|
||||
this.email = email;
|
||||
this.masterPasswordHash = hashedPassword;
|
||||
this.localMasterPasswordHash = localHashedPassword;
|
||||
@@ -327,8 +331,10 @@ export class AuthService implements AuthServiceAbstraction {
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
this.key = this.setCryptoKeys ? key : null;
|
||||
const twoFactorResponse = response as IdentityTwoFactorResponse;
|
||||
this.twoFactorProvidersData = twoFactorResponse.twoFactorProviders2;
|
||||
result.twoFactorProviders = twoFactorResponse.twoFactorProviders2;
|
||||
this.captchaToken = twoFactorResponse.captchaToken;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user