AtAuth
at main 124 lines 4.1 kB view raw
1//! Session store example 2//! 3//! This example demonstrates how to use the session management system 4//! with SQLite backend. 5//! 6//! Run with: cargo run --example with_session_store --features session-sqlite 7 8use atauth::session::{SessionManager, SqliteSessionStore}; 9use atauth::{TokenPayload, TokenVerifier}; 10use std::collections::HashMap; 11 12fn main() -> Result<(), Box<dyn std::error::Error>> { 13 // Setup - secret must be at least 32 bytes (256 bits) 14 let secret = b"your-super-secret-key-at-least-32-bytes-long!"; 15 let verifier = TokenVerifier::new(secret)?; 16 17 // Create an in-memory session store (use file path for persistence) 18 let session_store = SqliteSessionStore::in_memory()?; 19 20 // Create session manager with auto-extend enabled 21 let sessions = SessionManager::new(session_store) 22 .with_default_duration(86400) // 24 hours 23 .with_auto_extend(true, 3600); // Extend by 1 hour on each access 24 25 println!("=== Session Management Example ===\n"); 26 27 // Simulate user login 28 println!("1. User Login"); 29 println!(" Verifying token..."); 30 31 let test_payload = create_test_payload(); 32 let token = verifier.sign(&test_payload)?; 33 34 match verifier.verify(&token) { 35 Ok(payload) => { 36 println!(" [OK] Token verified for: {}", payload.handle); 37 38 // Create session 39 let session = sessions.create_session(&payload, token.clone())?; 40 println!(" [OK] Session created"); 41 println!(" Token: {}...", &session.token[..20]); 42 println!(" Expires in: {} seconds", session.remaining_seconds()); 43 } 44 Err(e) => { 45 println!(" [FAIL] Verification failed: {}", e); 46 return Ok(()); 47 } 48 } 49 50 println!(); 51 println!("2. Subsequent Request"); 52 println!(" Validating session..."); 53 54 // Simulate subsequent request with session token 55 match sessions.validate(&token) { 56 Ok(session) => { 57 println!(" [OK] Session valid for: {}", session.handle); 58 println!(" DID: {}", session.did); 59 println!(" User ID: {:?}", session.user_id); 60 } 61 Err(e) => { 62 println!(" [FAIL] Session invalid: {}", e); 63 } 64 } 65 66 println!(); 67 println!("3. Get All User Sessions"); 68 69 let user_sessions = sessions.get_user_sessions(&test_payload.did)?; 70 println!( 71 " Found {} session(s) for {}", 72 user_sessions.len(), 73 test_payload.did 74 ); 75 76 println!(); 77 println!("4. Create Another Session (same user, different device)"); 78 79 // Create another session for same user 80 let second_token = verifier.sign(&test_payload)?; 81 sessions.create_session(&test_payload, second_token)?; 82 println!(" [OK] Second session created"); 83 84 let user_sessions = sessions.get_user_sessions(&test_payload.did)?; 85 println!(" Now has {} sessions", user_sessions.len()); 86 87 println!(); 88 println!("5. Logout (invalidate first session)"); 89 sessions.invalidate(&token)?; 90 println!(" [OK] First session invalidated"); 91 92 let user_sessions = sessions.get_user_sessions(&test_payload.did)?; 93 println!(" Remaining sessions: {}", user_sessions.len()); 94 95 println!(); 96 println!("6. Logout All Devices"); 97 let deleted = sessions.invalidate_all_for_did(&test_payload.did)?; 98 println!(" [OK] Deleted {} session(s)", deleted); 99 100 println!(); 101 println!("7. Session Cleanup"); 102 // In production, run this periodically (e.g., every hour) 103 let cleaned = sessions.cleanup()?; 104 println!(" Cleaned up {} expired session(s)", cleaned); 105 106 println!(); 107 println!("=== Example Complete ==="); 108 109 Ok(()) 110} 111 112fn create_test_payload() -> TokenPayload { 113 let now = chrono::Utc::now().timestamp(); 114 TokenPayload { 115 did: "did:plc:testuser123".to_string(), 116 handle: "testuser.bsky.social".to_string(), 117 user_id: Some(1), 118 app_id: Some("session-example".to_string()), 119 iat: now, 120 exp: now + 3600, 121 nonce: format!("nonce-{}", now), 122 extra: HashMap::new(), 123 } 124}