JWT tokens in Rust: libraries and authentication implementation

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

JWT tokens in Rust: libraries and authentication implementation

JSON Web Token (JWT) is an open standard for creating access tokens based on the JSON format. In the Rust ecosystem, working with JWT is implemented through several high-quality libraries, among which jsonwebtoken is the leader. This tool provides a full cycle of working with tokens: creation, signing, verification, and decoding.



Main libraries for JWT in Rust

Currently, the most popular crates for working with JWT are:

  • jsonwebtoken — the main library with support for HS256, RS256, EdDSA algorithms
  • jwt — a lighter alternative with basic functionality
  • biscuit — an advanced library with support for complex scenarios

In this article, we will focus on jsonwebtoken as the most mature and documented solution.



Installation and setup

Add the dependency to Cargo.toml:

[dependencies]jsonwebtoken = "9.3"serde = { version = "1.0", features = ["derive"] }chrono = "0.4"


Creating and verifying JWT tokens

Let's look at a complete example of implementing authentication with JWT:



use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Serialize, Deserialize};use chrono::{Utc, Duration};

#[derive(Debug, Serialize, Deserialize)]struct Claims { sub: String, // user identifier exp: usize, // token expiration time iat: usize, // token creation time role: String, // user role}

fn create_token(user_id: &str, role: &str, secret: &str) -> Result { let now = Utc::now(); let claims = Claims { sub: user_id.to_string(), exp: (now + Duration::hours(24)).timestamp() as usize, iat: now.timestamp() as usize, role: role.to_string(), }; encode( &Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()) )}

fn verify_token(token: &str, secret: &str) -> Result { let token_data = decode::( token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::default() )?; Ok(token_data.claims)}


Practical use in a web application

Integrating JWT with web frameworks (e.g., Actix-web or Axum) requires creating middleware for token verification:



use actix_web::{HttpRequest, HttpResponse, web, App, HttpServer, middleware::from_fn};use std::sync::Arc;

// Middleware for JWT verificationasync fn auth_middleware( req: HttpRequest,) -> Result { let auth_header = req.headers() .get("Authorization") .and_then(|v| v.to_str().ok()) .ok_or(HttpResponse::Unauthorized().json("Missing token"))?; let token = auth_header .strip_prefix("Bearer ") .ok_or(HttpResponse::Unauthorized().json("Invalid token format"))?; verify_token(token, SECRET) .map_err(|_| HttpResponse::Unauthorized().json("Invalid token"))}

// Protected endpointasync fn protected_endpoint(claims: Claims) -> HttpResponse { HttpResponse::Ok().json(claims)}


Advanced features and best practices

  • Refresh tokens — use short-lived access tokens (15-30 minutes) and long-lived refresh tokens (7-30 days)
  • Secret storage — never store secret keys in code, use environment variables or a secure vault
  • Signature algorithms — for production, use RS256 (asymmetric encryption) instead of HS256
  • Va

Recommendations