Ablauf von reCAPTCHA-Tokens: Wie lange Tokens gültig bleiben

recaptcha token expiration - reCAPTCHA Token Expiration: How Long Tokens Stay Valid

Ein reCAPTCHA-Token läuft nach zwei Minuten ab. Die Dokumentation von Google sagt es klar: Jedes Antwort-Token ist zwei Minuten gültig und kann nur einmal verifiziert werden. Verfehlen Sie eine der beiden Hälften, bekommt Ihr Server denselben wenig hilfreichen Fehler zurück. Dieser Beitrag behandelt die drei getrennten Uhren, die oft für eine einzige gehalten werden, wohin diese 120 Sekunden in einem automatisierten Ablauf tatsächlich gehen, und die Änderung der Reihenfolge, die fast jeden Bug mit abgelaufenen Tokens behebt.

Zwei Minuten, und genau eine Verifizierung

Die Regel hat zwei Hälften, und beide haben es in sich.

Zwei Minuten. Die Uhr startet, wenn das Token ausgegeben wird, nicht wenn Ihr Formular abgeschickt wird. Ein Token, das in einem versteckten Feld liegt, während ein Nutzer zu Ende tippt, verbraucht sein Budget bereits.

Eine Verifizierung. Dasselbe Token zweimal an Google zu senden, schlägt beim zweiten Mal fehl, auch eine Sekunde später. Das ist Absicht: Es verhindert, dass ein abgefangenes Token erneut abgespielt wird. Wenn Ihr Backend einmal in einer Middleware und noch einmal im Handler verifiziert, schlägt der zweite Aufruf fehl, und der Bug sieht sporadisch aus.

Beide Fehlerfälle liefern dasselbe zurück. Die von Google gelieferte Verifizierungsantwort enthält dann success mit dem Wert false und den Fehlercode timeout-or-duplicate, was bedeutet, dass die Antwort entweder zu alt ist oder bereits verwendet wurde. Sie sagt Ihnen nicht, welches von beidem zutrifft, behandeln Sie beides also als eine einzige Fehlerklasse und prüfen Sie beides.

Drei Uhren, nicht eine

Die meiste Verwirrung entsteht hier dadurch, dass drei verschiedene Timer zu einer einzigen Vorstellung von “Token-Ablauf” zusammenfallen. Sie sind getrennt und laufen unabhängig voneinander ab.

UhrDauerWas passiert, wenn sie abläuft
Die eigene Antwort des Widgets, v2-Checkbox2 MinutenDas Widget löscht sich selbst und feuert den expired-Callback. Das versteckte Feld wird leer
Das Antwort-Token, serverseitig2 MinutenDie Verifizierung liefert timeout-or-duplicate
Ihre Session auf der ZielseiteVon der Seite abhängigUnabhängig von reCAPTCHA. Ein frisches Token repariert keine tote Session

Die erste ist die, die niemand kommen sieht, weil sie clientseitig und lautlos ist. Bei einer v2-Checkbox macht das Widget seine eigene Antwort nach zwei Minuten ungültig und ruft die Funktion auf, die Sie als expired-Callback registriert haben. Haben Sie nichts registriert, bleibt das Häkchen auf dem Bildschirm gesetzt, während das versteckte Feld dahinter leer ist, das Formular wird also ganz ohne Token abgeschickt und der Server meldet einen Fehler wegen fehlender Eingabe statt eines abgelaufenen Tokens.

<!-- Register the callback. Without it the box looks ticked
     while the value behind it is already gone. -->
<div class="g-recaptcha"
     data-sitekey="YOUR_SITEKEY"
     data-callback="onSolved"
     data-expired-callback="onExpired"></div>

<script>
function onExpired() {
  // Reset the widget and re-enable whatever you disabled.
  grecaptcha.reset();
}
</script>

Wie lange halten andere Challenges?

Zwei Minuten gelten nicht überall. Wenn Sie mehr als einen Challenge-Typ verarbeiten, unterscheiden sich die Budgets deutlich genug, um eine Rolle zu spielen.

ChallengeToken gültig fürWiederverwendbar
reCAPTCHA v2, Checkbox und Invisible2 MinutenNein
reCAPTCHA v32 MinutenNein
reCAPTCHA Enterprise2 MinutenNein
Cloudflare Turnstile5 MinutenNein
GeeTest v3Schicken Sie es sofort zurückNein

Turnstile ist der großzügige Fall. Der Leitfaden zur serverseitigen Validierung von Cloudflare gibt einem Token 300 Sekunden und weist ein erneut gesendetes Token mit demselben Code timeout-or-duplicate ab, den auch Google verwendet. GeeTest v3 funktioniert andersherum: Der Challenge-Wert, den Sie in den Solve geben, ist nur einmal verwendbar und läuft nach etwa einer Minute ab, die Frist liegt also vor dem Lösen statt danach. Holen Sie ihn unmittelbar vor dem Lösen, niemals am Anfang eines Skripts.

Wohin die zwei Minuten tatsächlich gehen

In einem von Hand bedienten Formular ist das Budget riesig. In einem automatisierten Ablauf ist es knapper, als es aussieht, denn das Lösen geht nicht sofort.

SchrittTypische Zeit
Seite laden und den sitekey auslesen1 bis 3 Sekunden
Ein reCAPTCHA v2 lösen15 bis 20 Sekunden
Ein reCAPTCHA v3 lösen10 bis 15 Sekunden
Token einspeisen und absendenunter einer Sekunde
Übrigetwa 95 Sekunden

Fünfundneunzig Sekunden Puffer sind bequem, bis sich etwas anderes dazwischenschiebt. Die üblichen Verdächtigen sind ein Proxy-Handshake, ein Login-Schritt zwischen Solve und Submit, ein Rate Limiter, der Ihren Worker schlafen legt, oder eine Queue, die gelöste Tokens für die spätere Verwendung sammelt. Das Letzte funktioniert nie: Ein Token ist verderblich und keine Ressource, die Sie auf Vorrat halten können.

Holen Sie sich das Token zuletzt

Die Lösung für fast jeden Bug mit abgelaufenen Tokens ist die Reihenfolge. Erledigen Sie alles Langsame zuerst und holen Sie das Token als letzten Schritt vor der Anfrage, die es verbraucht.

# pip install capskip
from capskip import CapSkip

solver = CapSkip(host="127.0.0.1", port=8080)

# Slow things first: log in, warm the session, pick up cookies.
session = build_session()
sitekey = read_sitekey(session, PAGE_URL)

# Then solve, so the clock starts as late as possible.
result = solver.recaptcha(sitekey=sitekey, url=PAGE_URL)

# And submit straight away. Nothing goes between these two lines.
session.post(PAGE_URL, data={"g-recaptcha-response": result["code"]})

Daraus folgen zwei Regeln, und die decken den größten Teil des Rests ab.

  • Cachen Sie ein Token niemals. Nicht in Redis, nicht in einer Variable, die die Anfrage überlebt, nicht über einen Retry hinweg. Lösen Sie stattdessen erneut
  • Verifizieren Sie niemals zweimal. Verifizieren Sie an genau einer Stelle. Wenn eine Middleware das Token bereits geprüft hat, muss der Route-Handler dieses Ergebnis lesen, statt Google erneut aufzurufen

Retries verdienen ein eigenes Wort. Wenn das Absenden fehlschlägt und Sie es wiederholen, ist das bereits gesendete Token verbraucht, der Retry braucht also einen neuen Solve. Die gesamte Arbeitseinheit zu wiederholen ist richtig. Nur den HTTP-Aufruf mit dem alten Token zu wiederholen liefert Ihnen jedes Mal timeout-or-duplicate und sieht so aus, als würde der Löser schlechte Antworten liefern.

Latenz, und wo der Löser läuft

Weil CapSkip auf Ihrer eigenen Hardware läuft, geht nichts vom Zwei-Minuten-Budget dafür drauf, einen Drittanbieter-Endpunkt über das Internet zu erreichen. Der Local-Modus lauscht auf 127.0.0.1, und der Aufruf verlässt die Maschine nie.

Der Server-Modus ändert das ein wenig, und es lohnt sich zu wissen, um wie viel. Wenn Sie Ihre Worker auf einen gemeinsamen Löser in Ihrem Netzwerk oder auf einem VPS mit öffentlicher IP zeigen lassen, kommt pro Aufruf ein Netzwerk-Hop dazu, das sind Millisekunden im LAN und einige zehn Millisekunden zu einem VPS in derselben Region. Gegen 120 Sekunden gerechnet ist das Rauschen, und dafür bedient ein Löser eine ganze Flotte. Beide Modi konfigurieren Sie in den Verbindungseinstellungen, und für den Server-Fall wird eine statische öffentliche IP empfohlen.

Ein CapSkip-Detail gehört ebenfalls hierher: Ein gelöstes Ergebnis ist einmal lesbar. Dieselbe Job-ID ein zweites Mal abzufragen liefert die Antwort nicht noch einmal, speichern Sie das Token also beim ersten Lesen, statt es später erneut abzuholen.

FAQ

Kann ich die zwei Minuten verlängern?

Nein. Das Fenster wird von Google durchgesetzt, und es gibt keine Einstellung, keinen Parameter und keinen Tarif, der daran etwas ändert. Der einzige Hebel, den Sie haben, ist, zwischen Solve und Submit weniger zu tun.

Läuft ein v3-Token wegen des Scores schneller ab?

Nein. v3-Tokens bekommen dieselben zwei Minuten wie v2. Der Score ist etwas völlig anderes: Er beschreibt, wie der Traffic aussah, nicht wie lange die Antwort hält, und er verfällt nicht, während das Token ungenutzt liegt. Beachten Sie, dass CapSkip keine Option für einen Mindest-Score hat, auf der Löse-Seite ist also ebenfalls nichts daran gebunden.

Mein Token funktioniert lokal und läuft in der Produktion ab. Warum?

Fast immer eine Queue. Lokale Läufe gehen direkt vom Lösen zum Absenden, während die Produktion den Job erst durch einen Broker, einen Worker-Pool oder einen Rate Limiter schickt. Messen Sie in der Produktion den Abstand zwischen den beiden Zeitstempeln, und Sie werden meist feststellen, dass er über 120 Sekunden liegt. Verlegen Sie den Solve in den Worker, der das Absenden übernimmt.

Ist timeout-or-duplicate jemals ein Fehler der Zielseite?

Manchmal. Eine Seite, die das Token selbst verifiziert, bevor sie Ihre Anfrage weiterleitet, verbraucht es, Ihre eigene Verifizierung schlägt dann als Duplikat fehl. Proxy-Schichten und Web Application Firewalls tun gelegentlich dasselbe. Wenn ein Token bei der ersten Verwendung mit sauberem Zeitstempel fehlschlägt, verdächtigen Sie etwas, das vor Ihnen liegt und es bereits verbraucht hat.

Die Kurzfassung

Zwei Minuten, eine Verifizierung und drei getrennte Uhren, die oft für eine einzige gehalten werden. Registrieren Sie den expired-Callback, damit der Browser-Fall sichtbar wird, lösen Sie so spät wie möglich und cachen oder wiederholen Sie ein Token niemals. Ein erneutes Lösen kostet nichts, denn bei Ihnen läuft ein lokaler Captcha-Löser, deshalb ist ein zweiter Lösevorgang immer die richtige Antwort auf ein abgelaufenes Token. Zur Funktionsweise der einzelnen Versionen siehe den Leitfaden zu reCAPTCHA v2 und den Leitfaden zu v3, die Turnstile-Seite für den Fünf-Minuten-Fall, und was reCAPTCHA ist für den Hintergrund.