Einleitung: Warum OAuth 2.0 und JWT in Rust?
\n\nModerne Webanwendungen kommen selten ohne ein Authentifizierungs- und Autorisierungssystem aus. OAuth 2.0 ist der Industriestandard für die Delegierung des Zugriffs, und JWT (JSON Web Tokens) ist eine kompakte und sichere Methode zur Übertragung von Behauptungen zwischen Parteien. Rust wird aufgrund seiner Leistungsfähigkeit und Speichersicherheit immer beliebter für die Erstellung hochbelastbarer Server. In diesem Artikel werden wir praktisch erarbeiten, wie man OAuth 2.0-Autorisierung mit JWT in Rust implementiert, unter Verwendung beliebter Crates und moderner Ansätze.
\n\n1. Projektvorbereitung und Installation der Abhängigkeiten
\n\nZunächst erstellen wir ein neues Rust-Projekt und fügen die notwendigen Abhängigkeiten hinzu. Wir werden actix-web für den Webserver, jsonwebtoken für die Arbeit mit JWT, serde für die Serialisierung und reqwest für HTTP-Anfragen an externe OAuth-Anbieter verwenden.
# Cargo.toml\n[package]\nname = "oauth-jwt-rust"\nversion = "0.1.0"\nedition = "2021"\n\n[dependencies]\nactix-web = "4"\nactix-rt = "2"\njsonwebtoken = "9"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\nreqwest = { version = "0.12", features = ["json"] }\ntokio = { version = "1", features = ["full"] }\ndotenv = "0.15"\nchrono = { version = "0.4", features = ["serde"] }\nuuid = { version = "1", features = ["v4"] }\n\nErstellen wir eine Datei .env zum Speichern der geheimen Schlüssel:
JWT_SECRET=your_super_secret_key_here\nGITHUB_CLIENT_ID=your_github_client_id\nGITHUB_CLIENT_SECRET=your_github_client_secret\n\n2. Grundlegende Struktur von JWT-Tokens
\n\nJWT besteht aus drei Teilen: Header, Payload und Signatur. Definieren wir die Strukturen für die Arbeit mit Tokens.
\n\n// src/jwt.rs\nuse chrono::{Utc, Duration};\nuse jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};\nuse serde::{Deserialize, Serialize};\n\n#[derive(Debug, Serialize, Deserialize)]\npub struct Claims {\n pub sub: String, // Benutzer-ID\n pub email: String, // Benutzer-E-Mail\n pub exp: usize, // Ablaufzeit\n pub iat: usize, // Ausstellungszeit\n}\n\npub fn create_jwt(user_id: &str, email: &str) -> Result {\n let now = Utc::now();\n let expiration = now + Duration::hours(24); // Token ist 24 Stunden gültig\n\n let claims = Claims {\n sub: user_id.to_string(),\n email: email.to_string(),\n exp: expiration.timestamp() as usize,\n iat: now.timestamp() as usize,\n };\n\n let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");\n encode(\n &Header::default(),\n &claims,\n &EncodingKey::from_secret(secret.as_bytes()),\n )\n}\n\npub fn validate_jwt(token: &str) -> Result {\n let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");\n let token_data = decode::(\n token,\n &DecodingKey::from_secret(secret.as_bytes()),\n &Validation::default(),\n )?;\n Ok(token_data.claims)\n} \n\n3. Implementierung von OAuth 2.0 mit GitHub
\n\nBetrachten wir ein klassisches OAuth 2.0-Szenario – die Autorisierung über GitHub. Der Benutzer wird zu GitHub weitergeleitet, erhält nach der Bestätigung einen Code, den wir gegen ein Access Token eintauschen.
\n\n3.1. Endpunkt zum Starten des OAuth-Flows
\n\n// src/oauth.rs\nuse actix_web::{web, HttpResponse, HttpRequest};\nuse reqwest::Client;\nuse serde_json::Value;\n\npub async fn github_login() -> HttpResponse {\n let client_id = std::env::var("GITHUB_CLIENT_ID").unwrap();\n let redirect_uri = "http://localhost:8080/auth/github/callback";\n \n let auth_url = format!(\n "https://github.com/login/oauth/authorize?client_id={}&redirect_uri={}&scope=user:email",\n client_id, redirect_uri\n );\n \n HttpRes