Introduction à OAuth 2.0 et JWT en Rust
Les applications web modernes nécessitent une authentification fiable et sécurisée. Deux standards clés dans ce domaine sont OAuth 2.0 (protocole d'autorisation) et JWT (JSON Web Token, format de jeton d'accès). Rust, grâce à ses performances et sa sécurité mémoire, devient un excellent choix pour construire des API où la vitesse et la fiabilité sont cruciales.
Dans cet article, nous allons voir comment implémenter OAuth 2.0 et l'autorisation JWT en Rust en utilisant des crates populaires. Vous apprendrez à configurer un serveur, émettre et vérifier des jetons JWT, ainsi qu'à intégrer le flux OAuth 2.0. Ce contenu est destiné aux développeurs familiers avec les bases de Rust et des frameworks web.
Concepts fondamentaux d'OAuth 2.0 et JWT
Qu'est-ce qu'OAuth 2.0 ?
OAuth 2.0 est un protocole d'accès délégué. Il permet à une application d'obtenir un accès limité aux ressources d'un utilisateur sans transmettre ses identifiants (nom d'utilisateur et mot de passe). Les acteurs principaux sont :
- Resource Owner — l'utilisateur propriétaire des données.
- Client — notre application (par exemple, un service web en Rust).
- Authorization Server — le serveur qui délivre les jetons après une authentification réussie.
- Resource Server — l'API fournissant les données protégées.
Qu'est-ce que JWT ?
JWT est un format de jeton compact et sûr pour les URL, composé de trois parties : l'en-tête (header), la charge utile (payload) et la signature (signature). La signature garantit l'intégrité des données. JWT est souvent utilisé comme jeton d'accès (access token) dans OAuth 2.0, car il est autonome : le serveur peut le vérifier sans accès à une base de données.
Implémentation pratique en Rust
Pour l'implémentation, nous aurons besoin des crates suivants :
actix-web— framework web.serdeetserde_json— pour la sérialisation/désérialisation.jsonwebtoken— pour travailler avec JWT.dotenv— pour la gestion de la configuration.chrono— pour travailler avec les dates et heures.
Étape 1 : Configuration du projet et de la structure
Créez un nouveau projet Cargo et ajoutez les dépendances dans Cargo.toml :
[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"] }Créez un fichier .env pour stocker la clé secrète :
JWT_SECRET=my_super_secret_key_12345Étape 2 : Création du modèle de données et des fonctions JWT
Définissons les structures pour JWT et implémentons les fonctions de création et de vérification des jetons.
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, // identifiant de l'utilisateur pub exp: usize, // timestamp d'expiration pub iat: usize, // timestamp d'émission}
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); // le jeton vit 24 heures
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::errors::Error> { let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); let token_data = decode::<Claims>( token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::default(), )?; Ok(token_data.claims)}