Client OAuth pour Rust : bibliothèque oauth2-rs

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Bibliothèque oauth2-rs : implémentation d'OAuth 2.0 en Rust

\n\n

Dans le développement web moderne, OAuth 2.0 est le protocole standard pour la délégation d'accès. La bibliothèque oauth2-rs fournit une implémentation complète du client OAuth 2.0 en langage Rust. Elle permet d'intégrer l'authentification via des services populaires : Google, GitHub, Yandex, VK et autres.

\n\n

Cette bibliothèque prend en charge tous les flux (flows) clés : Authorization Code, Client Credentials, Implicit, ainsi que Refresh Token. Une attention particulière est portée à la sécurité : utilisation de PKCE (Proof Key for Code Exchange) pour les clients publics et validation obligatoire des jetons.

\n\n

Installation de oauth2-rs

\n\n

Ajoutez la dépendance dans Cargo.toml :

\n\n
[dependencies]\noauth2 = "4.4"\ntokio = { version = "1", features = ["full"] }\nreqwest = { version = "0.11", features = ["json"] }\nserde = { version = "1.0", features = ["derive"] }
\n\n

Un client HTTP (recommandé reqwest avec support async) et le sérialiseur serde pour travailler avec JSON sont également nécessaires.

\n\n

Configuration de base du client OAuth

\n\n

Prenons l'exemple de Google OAuth 2.0. Créons d'abord la configuration :

\n\n
use oauth2::{\n    AuthorizationCode, AuthUrl, ClientId, ClientSecret, \n    RedirectUrl, TokenUrl, CsrfToken, Scope,\n    basic::BasicClient, TokenResponse\n};\n\nlet client_id = ClientId::new("YOUR_GOOGLE_CLIENT_ID".to_string());\nlet client_secret = ClientSecret::new("YOUR_GOOGLE_CLIENT_SECRET".to_string());\nlet auth_url = AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string())\n    .expect("URL d'authentification invalide");\nlet token_url = TokenUrl::new("https://oauth2.googleapis.com/token".to_string())\n    .expect("URL de jeton invalide");\n\nlet client = BasicClient::new(\n    client_id,\n    Some(client_secret),\n    auth_url,\n    Some(token_url)\n).set_redirect_uri(\n    RedirectUrl::new("http://localhost:8080/callback".to_string())\n        .expect("URL de redirection invalide")\n);
\n\n

Génération de l'URL d'autorisation

\n\n

Créons le lien vers lequel rediriger l'utilisateur :

\n\n
let (auth_url, csrf_token) = client\n    .authorize_url(CsrfToken::new_random)\n    .add_scope(Scope::new("openid".to_string()))\n    .add_scope(Scope::new("email".to_string()))\n    .url();\n\nprintln!("Suivez le lien : {}", auth_url);\n// Sauvegardez csrf_token pour vérification lors du callback
\n\n

CsrfToken protège contre les attaques de falsification de requête intersite (CSRF). Il doit être temporairement sauvegardé (par exemple, dans une session ou des cookies) et vérifié lors du traitement du callback.

\n\n

Traitement du callback et obtention du jeton

\n\n

Une fois que l'utilisateur a confirmé l'accès, le service le redirige vers redirect_uri avec le paramètre code. Exemple de gestionnaire en Rust :

\n\n
use actix_web::{web, HttpRequest, HttpResponse};\nuse oauth2::AuthorizationCode;\n\nasync fn callback(query: web::Query<std::collections::HashMap<String, String>>) -> HttpResponse {\n    let code = query.get("code")\n        .expect("Code d'autorisation manquant");\n    let state = query.get("state")\n        .expect("État manquant");\n\n    // Vérifiez state par rapport au csrf_token sauvegardé\n    // ...\n\n    let token_result = client\n        .exchange_code(AuthorizationCode::new(code.clone()))\n        .request_async(&reqwest::Client::new())\n        .await;\n\n    match token_result {\n        Ok(token) => {\n            let access_token = token.access_token().secret();\n            let refresh_token = token.refresh_token()\n                .map(|rt| rt.secret().clone());\n            // Sauvegardez les jetons dans la base de données ou la session\n            HttpResponse::Ok().body("Autorisation réussie !")\n        },\n        Err(e) => {\n            eprintln!("Erreur d'échange de code : {:?}", e);\n            HttpResponse::InternalServer                    

Recommendations