Introdução ao OAuth 2.0 e JWT em Rust
As aplicações web modernas exigem autenticação robusta e segura. Dois padrões-chave nesta área são OAuth 2.0 (protocolo de autorização) e JWT (JSON Web Token, formato de token de acesso). Rust, graças ao seu desempenho e segurança de memória, torna-se uma excelente escolha para construir APIs onde velocidade e confiabilidade são críticas.
Neste artigo, vamos abordar como implementar autorização OAuth 2.0 e JWT em Rust usando crates populares. Você aprenderá como configurar um servidor, emitir e validar tokens JWT, bem como integrar o fluxo OAuth 2.0. O material é voltado para desenvolvedores familiarizados com os fundamentos de Rust e frameworks web.
Conceitos Principais de OAuth 2.0 e JWT
O que é OAuth 2.0?
OAuth 2.0 é um protocolo de acesso delegado. Ele permite que uma aplicação obtenha acesso limitado aos recursos de um usuário sem transmitir suas credenciais (login e senha). Os principais participantes são:
- Resource Owner — o usuário proprietário dos dados.
- Client — nossa aplicação (por exemplo, um serviço web em Rust).
- Authorization Server — servidor que emite tokens após autenticação bem-sucedida.
- Resource Server — a API que fornece dados protegidos.
O que é JWT?
JWT é um formato de token compacto e seguro para URL, composto por três partes: cabeçalho (header), payload (payload) e assinatura (signature). A assinatura garante a integridade dos dados. O JWT é frequentemente usado como token de acesso (access token) no OAuth 2.0, pois é autossuficiente: o servidor pode validá-lo sem consultar um banco de dados.
Implementação Prática em Rust
Para a implementação, precisaremos dos seguintes crates:
actix-web— framework web.serdeeserde_json— para serialização/desserialização.jsonwebtoken— para trabalhar com JWT.dotenv— para gerenciamento de configuração.chrono— para trabalhar com datas e horas.
Passo 1: Configuração do Projeto e Estrutura
Crie um novo projeto Cargo e adicione as dependências no 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"] }Crie um arquivo .env para armazenar a chave secreta:
JWT_SECRET=my_super_secret_key_12345Passo 2: Criação do Modelo de Dados e Funções JWT
Vamos definir as estruturas para JWT e implementar funções de criação e validação de 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, // identificador do usuário pub exp: usize, // tempo de expiração (timestamp) pub iat: usize, // tempo de emissão (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 válido por 24 horas
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
```