Einführung in OAuth 2.0 und JWT mit Rust
Moderne Webanwendungen erfordern eine zuverlässige und sichere Authentifizierung. Zwei Schlüsselstandards in diesem Bereich sind OAuth 2.0 (Autorisierungsprotokoll) und JWT (JSON Web Token, Zugriffstoken-Format). Rust ist aufgrund seiner Leistung und Speichersicherheit eine hervorragende Wahl für den Aufbau von APIs, bei denen Geschwindigkeit und Zuverlässigkeit entscheidend sind.
In diesem Artikel werden wir uns ansehen, wie man OAuth 2.0- und JWT-Autorisierung mit Rust unter Verwendung beliebter Crates implementiert. Sie erfahren, wie Sie einen Server einrichten, JWT-Tokens ausstellen und überprüfen sowie einen OAuth 2.0-Flow integrieren. Das Material richtet sich an Entwickler, die mit den Grundlagen von Rust und Web-Frameworks vertraut sind.
Grundlegende Konzepte von OAuth 2.0 und JWT
Was ist OAuth 2.0?
OAuth 2.0 ist ein Protokoll für delegierten Zugriff. Es ermöglicht einer Anwendung, eingeschränkten Zugriff auf die Ressourcen eines Benutzers zu erhalten, ohne dessen Anmeldedaten (Benutzername und Passwort) zu übertragen. Die Hauptbeteiligten sind:
- Resource Owner — der Benutzer, der die Daten besitzt.
- Client — unsere Anwendung (z. B. ein Webdienst in Rust).
- Authorization Server — der Server, der nach erfolgreicher Authentifizierung Tokens ausstellt.
- Resource Server — die API, die geschützte Daten bereitstellt.
Was ist JWT?
JWT ist ein kompaktes, URL-sicheres Token-Format, das aus drei Teilen besteht: Header, Payload und Signatur. Die Signatur gewährleistet die Datenintegrität. JWT wird häufig als Zugriffstoken (access token) in OAuth 2.0 verwendet, da es eigenständig ist: Der Server kann es überprüfen, ohne auf eine Datenbank zugreifen zu müssen.
Praktische Implementierung in Rust
Für die Implementierung benötigen wir die folgenden Crates:
actix-web— Web-Framework.serdeundserde_json— für Serialisierung/Deserialisierung.jsonwebtoken— für die Arbeit mit JWT.dotenv— für die Konfigurationsverwaltung.chrono— für die Arbeit mit Datum und Uhrzeit.
Schritt 1: Projekteinrichtung und Struktur
Erstellen Sie ein neues Cargo-Projekt und fügen Sie die Abhängigkeiten in Cargo.toml hinzu:
[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"jsonwebtoken = "9"dotenv = "0.15"chrono = { version = "0.4", features = ["serde"] }uuid = { version = "1", features = ["v4"] }Erstellen Sie eine .env-Datei zum Speichern des geheimen Schlüssels:
JWT_SECRET=my_super_secret_key_12345Schritt 2: Erstellung des Datenmodells und der JWT-Funktionen
Definieren wir die Strukturen für JWT und implementieren Funktionen zum Erstellen und Überprüfen von Tokens.
use chrono::{Utc, Duration};use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Deserialize, Serialize};use std::env;
#[derive(Debug, Serialize, Deserialize)]pub struct Claims { pub sub: String, // Benutzer-ID pub exp: usize, // Ablaufzeit (Timestamp) pub iat: usize, // Ausstellungszeit (Timestamp)}
pub fn create_jwt(user_id: &str) -> Result<String, jsonwebtoken::errors::Error> { let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); let now = Utc::now(); let expiration = now + Duration::hours(24); // Token ist 24 Stunden gültig
let claims = Claims { sub: user_id.to_owned(), exp: expiration.timestamp() as usize, iat: now.timestamp() as usize, };
let token = encode( &Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()), )?; Ok(token)}
pub fn validate_jwt(token: &str) -> Result<Claims, jsonwebtoken