Konto-Abläufe (Zurücksetzen, Verifizieren, Magic Link)
Die Abläufe, die jede Anwendung am Rande der Anmeldung braucht: Passwort-Zurücksetzung, E-Mail-Verifizierung und Magic-Link-Anmeldung (passwortlos). Alle drei haben dieselbe Form — dem Benutzer einen manipulationssicheren, zeitlich begrenzten Link per E-Mail schicken und dann handeln, wenn er darauf klickt — und Rustango baut sie auf einem einzigen Fundament auf: signierten URLs. Eine signierte URL ist eine normale URL mit angehängter HMAC-Signatur, sodass der Server ihren Parametern vertrauen kann, ohne irgendetwas zu speichern.
Ein Begriff hier neu für Sie? HMAC, Token, Ablauf — siehe das Glossar.
Quelle:
rustango::signed_url(sign,verify,SignedUrlError) undrustango::auth_flows(PasswordReset,EmailVerification,MagicLink,confirm_password_reset_pool_into) — hinter den Featuressigned_url/auth_flows(standardmäßig aktiv; die Reset-Bestätigung braucht zusätzlichpasswords+ ein DB-Backend).Ausführbare Version: jeder Ausschnitt ist aus
auth_flows_doc.rskopiert (cargo test -p rustango --features sqlite --test auth_flows_doc).
Inhaltsverzeichnis
- Signierte URLs: das Fundament
- Passwort-Zurücksetzung
- E-Mail-Verifizierung
- Magic-Link-Anmeldung
- Einmal-Tokens
- Was Sie bereitstellen
- Siehe auch
Signierte URLs: das Fundament
sign hängt eine HMAC-SHA256-Signatur (und einen optionalen Ablauf) über den Pfad + die Query der
URL an. verify berechnet sie neu: Manipulieren Sie irgendeinen Parameter, verwenden Sie das
falsche Secret oder lassen Sie sie ablaufen, und sie schlägt fehl.
use rustango::signed_url::{sign, verify, SignedUrlError};
let url = "https://app.example.com/files/42?user_id=7";
let signed = sign(url, secret, None); // None = never expires
assert!(verify(&signed, secret).is_ok());
// Flip any signed byte → InvalidSignature.
let tampered = signed.replace("user_id=7", "user_id=8");
assert_eq!(verify(&tampered, secret), Err(SignedUrlError::InvalidSignature));
Fügen Sie eine TTL hinzu, und ein abgelaufener Link wird abgewiesen (sign_at / verify_at
nehmen explizite Unix-Sekunden für deterministische Tests):
use rustango::signed_url::{sign_at, verify_at, SignedUrlError};
let signed = sign_at(url, secret, Some(100)); // expires at t=100
assert!(verify_at(&signed, secret, 50).is_ok()); // before → ok
assert_eq!(verify_at(&signed, secret, 1000), Err(SignedUrlError::Expired));
Die Query wird vor dem Signieren sortiert, die Reihenfolge der Parameter spielt also keine Rolle.
Die Fehler sind MissingSignature, MalformedSignature, InvalidSignature, Expired.
Passwort-Zurücksetzung
Die auth_flows-Helfer umhüllen signierte URLs mit einer Zweck-Markierung (damit ein
Reset-Token nicht als Magic Link wiederverwendet werden kann) und kodieren die Benutzer-ID.
PasswordReset liefert außerdem einen Bestätigungshelfer, der das Token verifiziert und den
gespeicherten Hash rotiert — in einem einzigen Aufruf.
use std::time::Duration;
use rustango::auth_flows::{PasswordReset, confirm_password_reset_pool_into};
// 1. User asks to reset → look them up → issue a link → email it.
let url = PasswordReset::issue(
"https://app.example.com/auth/reset", // your callback route
user_id, // encoded in the token
secret,
Duration::from_secs(3600), // 1-hour TTL
);
mailer.send(&Email::new().to(addr).subject("Reset your password").body(&url)).await?;
// 2. User clicks + submits a new password → verify + rotate the hash.
let user_id = confirm_password_reset_pool_into(
&pool, &url, "a-brand-new-strong-password", secret,
"rustango_users", "id", "password_hash", // table, pk col, password col
).await?;
Der Bestätigungshelfer erzwingt eine Mindestlänge, hasht das neue Passwort mit argon2id und schreibt es — wobei er schwache, abgelaufene, manipulierte oder mit falschem Secret versehene Eingaben abweist, ohne die Zeile anzurühren:
// valid token + strong pw → hash rotated (starts "$argon2…")
// "short" → Err(WeakPassword), nothing written
// user_id tampered → Err(InvalidSignature), nothing written
confirm_password_reset_poolist die bequeme Form, die die Standardwerterustango_users/id/password_hashannimmt; verwenden Sie_into, um auf Ihre eigene Tabelle/Spalten zu verweisen.
E-Mail-Verifizierung
EmailVerification kodiert sowohl die Benutzer-ID als auch die E-Mail, sodass Sie bei der
Verifizierung beide zurückerhalten und bestätigen können, dass die Adresse immer noch übereinstimmt
(um Links abzufangen, die vor einer E-Mail-Änderung versendet wurden). Hier gibt es keinen
integrierten DB-Schreibvorgang — Sie setzen Ihre eigene Spalte „verifiziert“:
use rustango::auth_flows::EmailVerification;
// On signup:
let url = EmailVerification::issue(callback, user_id, &email, secret, Duration::from_secs(86_400));
mailer.send(&Email::new().to(&email).subject("Confirm your email").body(&url)).await?;
// On click:
let (user_id, email) = EmailVerification::verify(&url, secret)?;
// → if email still matches the user's current address, mark them verified
Magic-Link-Anmeldung
MagicLink kodiert nur die E-Mail — der Benutzer klickt, Sie schlagen das Konto nach und prägen
eine Session. Halten Sie die TTL kurz (10–30 Min) und machen Sie ihn
einmalig nutzbar (nächster Abschnitt), denn der Link ist die Zugangsberechtigung:
use rustango::auth_flows::MagicLink;
let url = MagicLink::issue(callback, &email, secret, Duration::from_secs(900));
mailer.send(&Email::new().to(&email).subject("Your sign-in link").body(&url)).await?;
// On click:
let email = MagicLink::verify_single_use(&url, secret, &cache).await?;
// → look up the user by email, create a session
Einmal-Tokens
verify allein prüft nur Signatur + Ablauf, ein durchgesickerter Link ist also bis zum Ablauf
wiederholbar. Für Anmeldung und Zurücksetzung bevorzugen Sie verify_single_use(url, secret, &cache) — es hält die Signatur des Tokens in einem Cache fest und verweigert eine zweite
Nutzung:
// first click → Ok(email)
// same link reused → Err(AuthFlowError::AlreadyUsed)
Untermauern Sie es in der Produktion mit einem gemeinsam genutzten Cache (Redis), damit ein Token nicht gegen ein anderes Replikat wiederholt werden kann. Die Prüfung schlägt geschlossen fehl (ein Cache-Fehler verweigert, statt einen Wiederholungsangriff zu riskieren).
Was Sie bereitstellen
Das Framework stellt Tokens aus/verifiziert sie und schreibt (beim Zurücksetzen) den Hash; Ihre Anwendung liefert den Rest:
- Ein Secret (ein stabiler App-Schlüssel; per Konvention 32 Byte).
- Ein Mailer zum Versenden der Links —
rustango::emailliefertConsoleMailer,SmtpMailerundInMemoryMailer(praktisch in Tests). - Eine Benutzertabelle mit den Spalten, die jeder Ablauf braucht (E-Mail für die Verifizierungs-/Magic-Link-Suche; eine Passwort-Hash-Spalte für die Zurücksetzung; eine Spalte „verifiziert“, die Ihnen gehört).
- Die Callback-Routen, die den Klick empfangen, und die Session-Prägung für die Magic-Link-Anmeldung.
Siehe auch
- Passwörter — das Hashing, das die Zurücksetzung rotiert.
- Sessions — was die Magic-Link-Anmeldung bei Erfolg erzeugt.
- HMAC-Request-Signierung — dieselbe HMAC-Primitive, angewandt auf API-Requests statt auf URLs.
- Sicherheitsleitfaden — die umfassendere Härtungs-Checkliste.
