1
0
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:
Matt Gibson
2021-07-21 07:55:26 -05:00
committed by GitHub
parent 00acbce556
commit 1006f50ef3
13 changed files with 143 additions and 47 deletions

View File

@@ -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;
}