mirror of
https://github.com/bitwarden/jslib
synced 2026-01-06 18:43:14 +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:
22
common/src/misc/captcha_iframe.ts
Normal file
22
common/src/misc/captcha_iframe.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { I18nService } from '../abstractions/i18n.service';
|
||||
import { IFrameComponent } from './iframe_component';
|
||||
|
||||
export class CaptchaIFrame extends IFrameComponent {
|
||||
constructor(win: Window, webVaultUrl: string,
|
||||
private i18nService: I18nService, successCallback: (message: string) => any, errorCallback: (message: string) => any,
|
||||
infoCallback: (message: string) => any) {
|
||||
super(win, webVaultUrl, 'captcha-connector.html', 'hcaptcha_iframe', successCallback, errorCallback, (message: string) => {
|
||||
const parsedMessage = JSON.parse(message);
|
||||
if (typeof (parsedMessage) !== 'string') {
|
||||
this.iframe.height = (parsedMessage.height).toString();
|
||||
this.iframe.width = (parsedMessage.width).toString();
|
||||
} else {
|
||||
infoCallback(parsedMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init(siteKey: string): void {
|
||||
super.initComponent(this.createParams({ siteKey: siteKey, locale: this.i18nService.translationLocale }, 1));
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,16 @@
|
||||
import { I18nService } from '../abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from '../abstractions/platformUtils.service';
|
||||
|
||||
export class WebAuthn {
|
||||
private iframe: HTMLIFrameElement = null;
|
||||
export abstract class IFrameComponent {
|
||||
iframe: HTMLIFrameElement;
|
||||
private connectorLink: HTMLAnchorElement;
|
||||
private parseFunction = this.parseMessage.bind(this);
|
||||
|
||||
constructor(private win: Window, private webVaultUrl: string, private webAuthnNewTab: boolean,
|
||||
private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
|
||||
private successCallback: Function, private errorCallback: Function, private infoCallback: Function) {
|
||||
constructor(private win: Window, protected webVaultUrl: string, private path: string, private iframeId: string,
|
||||
public successCallback?: (message: string) => any,
|
||||
public errorCallback?: (message: string) => any, public infoCallback?: (message: string) => any) {
|
||||
this.connectorLink = win.document.createElement('a');
|
||||
}
|
||||
|
||||
init(data: any): void {
|
||||
const params = new URLSearchParams({
|
||||
data: this.base64Encode(JSON.stringify(data)),
|
||||
parent: encodeURIComponent(this.win.document.location.href),
|
||||
btnText: encodeURIComponent(this.i18nService.t('webAuthnAuthenticate')),
|
||||
v: '1',
|
||||
});
|
||||
|
||||
if (this.webAuthnNewTab) {
|
||||
// Firefox fallback which opens the webauthn page in a new tab
|
||||
params.append('locale', this.i18nService.translationLocale);
|
||||
this.platformUtilsService.launchUri(`${this.webVaultUrl}/webauthn-fallback-connector.html?${params}`);
|
||||
} else {
|
||||
this.connectorLink.href = `${this.webVaultUrl}/webauthn-connector.html?${params}`;
|
||||
this.iframe = this.win.document.getElementById('webauthn_iframe') as HTMLIFrameElement;
|
||||
this.iframe.allow = 'publickey-credentials-get ' + new URL(this.webVaultUrl).origin;
|
||||
this.iframe.src = this.connectorLink.href;
|
||||
|
||||
this.win.addEventListener('message', this.parseFunction, false);
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.sendMessage('stop');
|
||||
}
|
||||
@@ -60,6 +37,22 @@ export class WebAuthn {
|
||||
this.win.removeEventListener('message', this.parseFunction, false);
|
||||
}
|
||||
|
||||
protected createParams(data: any, version: number) {
|
||||
return new URLSearchParams({
|
||||
data: this.base64Encode(JSON.stringify(data)),
|
||||
parent: encodeURIComponent(this.win.document.location.href),
|
||||
v: version.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
protected initComponent(params: URLSearchParams): void {
|
||||
this.connectorLink.href = `${this.webVaultUrl}/${this.path}?${params}`;
|
||||
this.iframe = this.win.document.getElementById(this.iframeId) as HTMLIFrameElement;
|
||||
this.iframe.src = this.connectorLink.href;
|
||||
|
||||
this.win.addEventListener('message', this.parseFunction, false);
|
||||
}
|
||||
|
||||
private parseMessage(event: MessageEvent) {
|
||||
if (!this.validMessage(event)) {
|
||||
return;
|
||||
26
common/src/misc/webauthn_iframe.ts
Normal file
26
common/src/misc/webauthn_iframe.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { I18nService } from '../abstractions/i18n.service';
|
||||
import { PlatformUtilsService } from '../abstractions/platformUtils.service';
|
||||
import { IFrameComponent } from './iframe_component';
|
||||
|
||||
export class WebAuthnIFrame extends IFrameComponent {
|
||||
constructor(win: Window, webVaultUrl: string, private webAuthnNewTab: boolean,
|
||||
private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
|
||||
successCallback: (message: string) => any, errorCallback: (message: string) => any,
|
||||
infoCallback: (message: string) => any) {
|
||||
super(win, webVaultUrl, 'webauthn-connector.html', 'webauthn_iframe', successCallback, errorCallback, infoCallback);
|
||||
}
|
||||
|
||||
|
||||
init(data: any): void {
|
||||
const params = this.createParams({ data: JSON.stringify(data), btnText: this.i18nService.t('webAuthnAuthenticate') }, 2);
|
||||
|
||||
if (this.webAuthnNewTab) {
|
||||
// Firefox fallback which opens the webauthn page in a new tab
|
||||
params.append('locale', this.i18nService.translationLocale);
|
||||
this.platformUtilsService.launchUri(`${this.webVaultUrl}/webauthn-fallback-connector.html?${params}`);
|
||||
} else {
|
||||
super.initComponent(params);
|
||||
this.iframe.allow = 'publickey-credentials-get ' + new URL(this.webVaultUrl).origin;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user