Skip to content

Instantly share code, notes, and snippets.

@34r7h
Created August 8, 2024 16:24
Show Gist options
  • Save 34r7h/c3c51167fcc7a75f76fb6c0a2d8218c5 to your computer and use it in GitHub Desktop.
Save 34r7h/c3c51167fcc7a75f76fb6c0a2d8218c5 to your computer and use it in GitHub Desktop.
simple auth
// src/user_management/authenticate_user.rs
use serde_json::{self, Value, json};
use std::sync::Arc;
use tokio::sync::Mutex;
use redis::aio::MultiplexedConnection;
use redis::AsyncCommands;
use futures_util::future::{BoxFuture, FutureExt};
use sha2::{Sha256, Digest};
use chrono::Utc;
use base64::prelude::*;
pub fn authenticate_user_endpoint(body: Vec<u8>, pool: Arc<Mutex<MultiplexedConnection>>) -> BoxFuture<'static, String> {
async move {
let body_str = String::from_utf8(body).unwrap();
if let Ok(data) = serde_json::from_str::<Value>(&body_str) {
let email = data["email"].as_str().unwrap_or("");
let pass_hash = data["pass_hash"].as_str().unwrap_or("");
let request_time = data["request_time"].as_i64().unwrap_or_default(); // Retrieve request_time from the request JSON
match authenticate(email, pass_hash, request_time, pool.clone()).await { // Pass request_time to the authenticate function
Ok((session_token, timestamp)) => json!({
"status": "success",
"token": session_token,
"timestamp": timestamp,
"request_time": request_time // Include the same request_time in the response
}).to_string(),
Err(_) => json!({"status": "error", "message": "Authentication failed"}).to_string(),
}
} else {
json!({"status": "error", "message": "Invalid JSON"}).to_string()
}
}.boxed()
}
async fn authenticate(email: &str, pass_hash: &str, request_time: i64, pool: Arc<Mutex<MultiplexedConnection>>) -> redis::RedisResult<(String, i64)> {
let mut conn = pool.lock().await;
let key = format!("users:{}:password_hash", email);
let stored_pass_hash: String = conn.get(&key).await?;
if pass_hash == stored_pass_hash {
let timestamp = Utc::now().timestamp_millis();
let mut hasher = Sha256::new();
hasher.update(format!("{}{}{}", email, pass_hash, timestamp));
let hash_bytes = hasher.finalize();
let session_token = BASE64_STANDARD.encode(&hash_bytes);
let session_key = format!("sessions:{}", session_token);
conn.set(&session_key, timestamp).await?;
Ok((session_token, timestamp))
} else {
Err(redis::RedisError::from((redis::ErrorKind::AuthenticationFailed, "Invalid credentials")))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment