Recaptcha v3 Integration in Svelte/SvelteKit
Der Dienst reCAPTCHA ist weit verbreitet im Einsatz. Bisher war die Integration in php Webseiten immer recht einfach. Nun hatte ich aber das Vergnügen, es in Javascript Frameworks einzusetzen. Genauer gesagt, in SvelteKit. Bisher fand ich nur einige Beispiele für die Integration von v2, nicht aber v3.
Die Integration von reCAPTCHA v3 wird hier bei Google offiziell beschrieben. Man kann sich entscheiden, ob die Integration automatic bind oder programmatically zum Einsatz kommen soll. Letzteres hatte ich gewählt. Die Api zu google habe ich dann entsprechend in der betroffenen .svelte Datei über den head-Tag hinzufügt:
<svelte:head>
<script src="https://www.google.com/recaptcha/api.js?render=publickey1234" async defer>
</script>
</svelte:head>
Wird der public key als Parameter mitgegeben, dann wird das google reCAPTCHA (als kleines Icon rechts unten) nach dem Seitenaufbau gerendert. Das Problem war bei meiner svelte Applikation, dass es kurz nach dem rendern wieder verschwand bzw. manchmal gar nicht angezeigt wurde.
Wenn dann ein .execute ausgeführt wurde, wurde eine Anfrage gestartet die mit einem Timeout endete. Die Verifizierung von reCAPTCHA war damit nicht möglich.
Es gibt also ein Problem bei dem automatischen rendern durch die api.js. Der nächste Schritt war also, dass rendern selbst (also durch meine svelte Anwendung) auszulösen und am Besten gleich in einem onMount() zu stopfen, damit es gar nicht erst zu einem Problem mit dem Lifecycle kommen kann.
Dazu muss man etwas tiefer in der Google Dokumentation graben. Genauer gesagt im Abschnitt „customize rendering v3„. Zunächst wird also nicht mehr der Parameter render mit dem publickey übergeben, sondern stattdessen ein .render Aufruf in einer onMount() verpackt. Die Überarbeitung sieht dann wie folgt aus:
<script>
import { onMount } from 'svelte';
onMount(async () => {
window.grecaptcha.ready(() => {
grecaptchaclient = grecaptcha.render('recaptchabox', {
'sitekey' : GOOGLE_KEY,
'size' : 'invisible'
});
})
});
</script>
<svelte:head>
<script src="https://www.google.com/recaptcha/api.js" async defer>
</script>
</svelte:head>
<div id="recaptchabox"></div>
Ganz wichtig für die Funktion render(): Die Rückgabe ist eine Client-Id, die entsprechend bei der späteren .execute() Funktion als Key übergeben wird! Wenn bei der .execute() Funktion auch wieder der publickey übergeben wird, dann erhält man sonst die Fehlermeldung: „Invalid site key or not loaded in api.js“.
Für die render() Funktion wird dann noch ein Element definiert (recaptchabox, div). Als Parameter sind müssen mindestens der sitekey (der publickey) und size definiert werden. Size spielt vor allem für v3 eine wichtige Rolle und gibt an, dass es sich hierbei um die unsichtbare reCAPTCHA Variante handelt. Gibt man dies nicht an oder einen falschen Wert, bekommt man die Fehlermeldung „falscher Schlüssel“ etc.
Mit diesen Anpassungen kann nun die Verifizierung klappen. Hier noch ein Beispiel:
<script>
async function doLoginSubmit() {
window.grecaptcha.ready(function() {
grecaptcha.execute(grecaptchaclient, {action: 'submit'}).then(function(token) {
// ...
});
});
}
</script>
<form on:submit|preventDefault={doLoginSubmit}>
<button>Senden</button>
</form>
Damit ist die Integration von reCAPTCHA v3 auch in svelte kein Problem. Ich hoffe ich konnte einige Hilfestellung geben und somit die Zeit für intensivere Recherchen verkürzen.