JWT vs PHP-Style Tokens in Rust: Secure Token Authentication Explained

4 min readSep 15, 2024

In our latest video, “JWT vs PHP-Style Tokens in Rust: Secure Token Authentication Explained,” we dive into two popular methods for handling authentication tokens: JSON Web Tokens (JWT) and classic PHP-style tokens. This tutorial provides a comprehensive look at both methods using Rust, focusing on their security features and practical implementations.

Understanding JWT and PHP-Style Tokens

JSON Web Tokens (JWT) are widely used for modern web authentication. They consist of three parts: a header, payload, and signature. JWTs allow for compact, URL-safe tokens that are easy to use across different platforms. However, they come with their own set of security concerns, including the potential risks of token tampering and the challenge of managing token expiration effectively.

On the other hand, PHP-style tokens typically involve simpler mechanisms with global and per-user salts to ensure token security. This traditional approach provides a more straightforward way to manage tokens, including their expiration and validity checks, though it may lack some of the flexibility offered by JWTs.

What You’ll Learn

In this video, you will:

  • Understand JWT: Learn about the structure and use cases of JSON Web Tokens.
  • Explore JWT Security Issues: Examine common security concerns with JWTs.
  • Discover PHP-Style Tokens: Explore a traditional approach to token authentication and its security features.
  • Delve into Authorization: Learn why handling authorization closer to the transaction level can improve security.
  • Code Walkthrough: View detailed Rust code examples for both JWT and PHP-style token authentication.

Rust Code Examples

1. JWT Authentication

Dependencies in Cargo.toml:

jsonwebtoken = "8.1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Code Example (src/main.rs):

use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey};
use serde::{Serialize, Deserialize};
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
}

fn create_jwt(user_id: &str, secret_key: &str) -> String {
let claims = Claims {
sub: user_id.to_owned(),
exp: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 3600) as usize, // 1 hour expiration
};
encode(&Header::default(), &claims, &EncodingKey::from_secret(secret_key.as_bytes())).unwrap()
}

fn validate_jwt(token: &str, secret_key: &str) -> bool {
let validation = Validation { leeway: 0, validate_exp: true, ..Validation::default() };
match decode::<Claims>(token, &DecodingKey::from_secret(secret_key.as_bytes()), &validation) {
Ok(_) => true,
Err(_) => false,
}
}

fn main() {
let secret_key = "your_secret_key";
let user_id = "user123";
let token = create_jwt(user_id, secret_key);
println!("Generated JWT: {}", token);

let is_valid = validate_jwt(&token, secret_key);
println!("Is the token valid? {}", is_valid);
}

Explanation:

  • Dependencies: jsonwebtoken for JWT operations and serde for serialization.
  • Claims Struct: Defines the payload of the JWT, including the user ID and expiration time.
  • create_jwt Function: Generates a JWT with a specified expiration time.
  • validate_jwt Function: Validates the JWT and checks its expiration.

2. PHP-Style Token Authentication

Dependencies in Cargo.toml:

[dependencies]
sha2 = "0.10.5"

Code Example (src/main.rs):

use sha2::{Sha256, Digest};
use std::time::{SystemTime, UNIX_EPOCH};

fn generate_token(username: &str, user_salt: &str, global_salt: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(format!("{}{}", username, user_salt));
let identifier = format!("{:x}", hasher.finalize());

let start = SystemTime::now();
let duration = start.duration_since(UNIX_EPOCH).unwrap().as_secs();
let token_data = format!("{}.{}", identifier, duration);

let mut hasher = Sha256::new();
hasher.update(format!("{}{}", token_data, global_salt));
let signature = format!("{:x}", hasher.finalize());

format!("{}.{}", token_data, signature)
}

fn validate_token(token: &str, global_salt: &str, user_salt: &str) -> bool {
let parts: Vec<&str> = token.split('.').collect();
if parts.len() != 3 {
return false;
}

let identifier = parts[0];
let timestamp: u64 = parts[1].parse().unwrap_or(0);
let signature = parts[2];

let token_data = format!("{}.{}", identifier, timestamp);
let mut hasher = Sha256::new();
hasher.update(format!("{}{}", token_data, global_salt));
let expected_signature = format!("{:x}", hasher.finalize());

let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
if signature == expected_signature && current_time - timestamp <= 3600 {
true
} else {
false
}
}

fn main() {
let username = "user123";
let user_salt = "unique_user_salt";
let global_salt = "global_salt_key";

let token = generate_token(username, user_salt, global_salt);
println!("Generated Token: {}", token);

let is_valid = validate_token(&token, global_salt, user_salt);
println!("Is the token valid? {}", is_valid);

// Extract the identifier and timestamp from the token
let parts: Vec<&str> = token.split('.').collect();
if parts.len() != 3 {
println!("Invalid token format.");
return;
}
let identifier = parts[0];
let timestamp: u64 = parts[1].parse().unwrap_or(0);

// Create an expired token by manipulating the timestamp
let expired_token = format!("{}x.{}", identifier, timestamp - 3601);
let is_expired_valid = validate_token(&expired_token, global_salt, user_salt);
println!("Is the expired token valid? {}", is_expired_valid);
}

Explanation:

  • Dependencies: sha2 for hashing.
  • generate_token Function: Creates a token by hashing the username and salt values, and includes a timestamp.
  • validate_token Function: Validates the token by checking its components and expiration time.

Watch the Full Tutorial

For a detailed walkthrough of these implementations and explanations, watch the full video:

Watch the Video

Engage and Support

Your feedback is crucial! Share your thoughts and questions in the comments section of the video. Your support helps us continue producing high-quality content.

Support the channel and help us create more valuable content by making a donation:

Donate Here 💖

--

--

Aarambh Dev Hub
Aarambh Dev Hub

Written by Aarambh Dev Hub

Rust developer sharing coding tutorials, backend tips, and insights. Follow for deep dives into Rust, programming challenges, and modern development practices.

No responses yet