mirror of
https://github.com/bitwarden/browser
synced 2026-01-07 11:03:30 +00:00
Feature/use hcaptcha if bot (#1089)
* Add captcha to login page * pull out shared method * Update parse parameter logic * Load captcha * responsive iframe height * correct i18n * site key provided by server * Fix locale parsing * Add optional success callbackUri * Make captcha connector responsive * Handle parameter versions in webauthn * Move variables to top of script * Add captcha to registration * Move captcha above `<hr>` div to be part of input form * Add styled mobile captcha connector * Linter Fixes * Remove duplicate import * Use listener to load captcha * PR review
This commit is contained in:
@@ -1,9 +1,14 @@
|
||||
import { getQsParam } from './common';
|
||||
import { b64Decode, getQsParam } from './common';
|
||||
|
||||
declare var hcaptcha: any;
|
||||
|
||||
// tslint:disable-next-line
|
||||
require('./captcha.scss');
|
||||
if (window.location.pathname.includes('mobile')) {
|
||||
// tslint:disable-next-line
|
||||
require('./captcha-mobile.scss');
|
||||
} else {
|
||||
// tslint:disable-next-line
|
||||
require('./captcha.scss');
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
init();
|
||||
@@ -14,15 +19,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
let parentUrl: string = null;
|
||||
let parentOrigin: string = null;
|
||||
let callbackUri: string = null;
|
||||
let sentSuccess = false;
|
||||
|
||||
function init() {
|
||||
start();
|
||||
async function init() {
|
||||
await start();
|
||||
onMessage();
|
||||
info('ready');
|
||||
}
|
||||
|
||||
function start() {
|
||||
async function start() {
|
||||
sentSuccess = false;
|
||||
|
||||
const data = getQsParam('data');
|
||||
@@ -40,15 +45,49 @@ function start() {
|
||||
parentOrigin = new URL(parentUrl).origin;
|
||||
}
|
||||
|
||||
hcaptcha.render('captcha', {
|
||||
sitekey: 'bc38c8a2-5311-4e8c-9dfc-49e99f6df417',
|
||||
callback: 'captchaSuccess',
|
||||
'error-callback': 'captchaError',
|
||||
let decodedData: any;
|
||||
try {
|
||||
decodedData = JSON.parse(b64Decode(data));
|
||||
}
|
||||
catch (e) {
|
||||
error('Cannot parse data.');
|
||||
return;
|
||||
}
|
||||
callbackUri = decodedData.callbackUri;
|
||||
|
||||
let src = 'https://hcaptcha.com/1/api.js?render=explicit';
|
||||
|
||||
// Set language code
|
||||
if (decodedData.locale) {
|
||||
src += `&hl=${decodedData.locale ?? 'en'}`;
|
||||
}
|
||||
|
||||
// Set captchaRequired subtitle for mobile
|
||||
const subtitleEl = document.getElementById('captchaRequired');
|
||||
if (decodedData.captchaRequiredText && subtitleEl) {
|
||||
subtitleEl.textContent = decodedData.captchaRequiredText;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.addEventListener('load', e => {
|
||||
hcaptcha.render('captcha', {
|
||||
sitekey: decodedData.siteKey,
|
||||
callback: 'captchaSuccess',
|
||||
'error-callback': 'captchaError',
|
||||
});
|
||||
watchHeight();
|
||||
});
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
function captchaSuccess(response: string) {
|
||||
success(response);
|
||||
if (callbackUri) {
|
||||
document.location.replace(callbackUri + '?token=' + encodeURIComponent(response));
|
||||
}
|
||||
}
|
||||
|
||||
function captchaError() {
|
||||
@@ -79,7 +118,24 @@ function success(data: string) {
|
||||
sentSuccess = true;
|
||||
}
|
||||
|
||||
function info(message: string) {
|
||||
parent.postMessage('info|' + message, parentUrl);
|
||||
function info(message: string | object) {
|
||||
parent.postMessage('info|' + JSON.stringify(message), parentUrl);
|
||||
}
|
||||
|
||||
async function watchHeight() {
|
||||
const imagesDiv = document.body.lastChild as HTMLElement;
|
||||
while (true) {
|
||||
info({
|
||||
height: imagesDiv.style.visibility === 'hidden' ?
|
||||
document.documentElement.offsetHeight :
|
||||
document.documentElement.scrollHeight,
|
||||
width: document.documentElement.scrollWidth,
|
||||
});
|
||||
await sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
async function sleep(ms: number) {
|
||||
await new Promise(r => setTimeout(r, ms));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user