### Create and Verify Credential (Complete Example) Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Demonstrates a full setup for creating and verifying a credential using production-like configuration presets, including storage TTL and time window. ```rust use nonce_auth::{ CredentialBuilder, CredentialVerifier, ConfigPreset, NonceConfig, storage::MemoryStorage }; use std::sync::Arc; # async fn example() -> Result<(), nonce_auth::NonceError> { // Setup let storage = Arc::new(MemoryStorage::new()); let config: NonceConfig = ConfigPreset::Production.into(); // Create credential let credential = CredentialBuilder::new(b"api_secret") .sign(b"important_request")?; // Verify credential CredentialVerifier::new(storage) .with_secret(b"api_secret") .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window) .verify(&credential, b"important_request") .await?; println!("Request authenticated!"); # Ok(()) # } ``` -------------------------------- ### Example Usage of NonceConfig Validation and Summary Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Shows how to create a NonceConfig, validate its settings, and print a summary. This example requires importing NonceConfig and Duration. ```rust use nonce_auth::NonceConfig; use std::time::Duration; let config = NonceConfig { storage_ttl: Duration::from_secs(600), time_window: Duration::from_secs(120), }; let warnings = config.validate(); for warning in warnings { println!("Warning: {}", warning); } println!("{}", config.summary()); ``` -------------------------------- ### Complete CredentialVerifier Example Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-verifier.md A full example showing how to create a credential, verify it, and attempt a replay attack which is then prevented. This covers the typical lifecycle of using the verifier. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; use std::time::Duration; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = Arc::new(MemoryStorage::new()); let secret = b"shared_secret_key"; // 1. Create a credential let credential = CredentialBuilder::new(secret) .sign(b"important_request")?; // 2. Verify the credential let verifier = CredentialVerifier::new(Arc::clone(&storage)) .with_secret(secret) .with_time_window(Duration::from_secs(60)); verifier.verify(&credential, b"important_request").await?; // 3. Attempt replay attack (will fail) let result = CredentialVerifier::new(storage) .with_secret(secret) .verify(&credential, b"important_request") .await; assert!(matches!(result, Err(nonce_auth::NonceError::DuplicateNonce))); # Ok(()) # } ``` -------------------------------- ### MemoryStorage Example Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-storage.md Demonstrates creating, signing, verifying, and managing stats for MemoryStorage. Includes cleanup of expired nonces. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; use std::time::Duration; async fn example() -> Result<(), nonce_auth::NonceError> { // Create storage let storage = Arc::new(MemoryStorage::with_capacity(1000)); // Create and verify a credential let credential = CredentialBuilder::new(b"secret").sign(b"data")?; let verifier = CredentialVerifier::new(Arc::clone(&storage)) .with_secret(b"secret") .with_storage_ttl(Duration::from_secs(600)) .with_time_window(Duration::from_secs(60)); verifier.verify(&credential, b"data").await?; // Get storage stats let stats = storage.get_stats().await?; println!("Stored nonces: {}", stats.total_records); println!("Info: {}", stats.backend_info); // Manual cleanup let cutoff = chrono::Local::now().timestamp() - 300; // 5 minutes ago let removed = storage.cleanup_expired(cutoff).await?; println!("Removed {} expired nonces", removed); Ok(()) } ``` -------------------------------- ### Usage Example for NonceCredential Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Demonstrates how to create, serialize, and deserialize a NonceCredential. Ensure you have the `serde_json` crate and `nonce_auth` library available. ```rust use nonce_auth::NonceCredential; use serde_json; let credential = NonceCredential { timestamp: 1234567890, nonce: "unique-nonce-value".to_string(), signature: "base64encodedSignature".to_string(), }; // Serialize for transmission let json = serde_json::to_string(&credential)?; // Deserialize from received JSON let received: NonceCredential = serde_json::from_str(&json)?; ``` -------------------------------- ### MemoryStorage Cleanup Example Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Demonstrates how to clean up expired nonces from MemoryStorage. This example removes nonces older than 5 minutes. ```rust use nonce_auth::storage::MemoryStorage; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = MemoryStorage::new(); // Cleanup all nonces created before this time let cutoff = (time::OffsetDateTime::now_utc().unix_timestamp() - 300) as i64; // 5 min ago let removed = storage.cleanup_expired(cutoff).await?; println!("Removed {} expired nonces", removed); # Ok(()) # } ``` -------------------------------- ### Example Usage of StorageStats Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Demonstrates how to retrieve and print storage statistics from a MemoryStorage backend. Ensure the nonce_auth crate is imported. ```rust use nonce_auth::storage::MemoryStorage; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = MemoryStorage::new(); let stats = storage.get_stats().await?; println!("Total nonces: {}", stats.total_records); println!("Backend info: {}", stats.backend_info); # Ok(()) # } ``` -------------------------------- ### Basic Nonce Authentication Example Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Demonstrates the basic workflow of generating and verifying a credential using memory storage. Ensure you have the necessary dependencies and a secret key. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, MemoryStorage}; use std::sync::Arc; use std::time::Duration; #[tokio::main] async fn main() -> Result<(), Box> { let secret = b"your-secret-key"; let payload = b"hello world"; // Create storage let storage = Arc::new(MemoryStorage::new()); // Generate credential let credential = CredentialBuilder::new(secret) .sign(payload)?; // Verify credential CredentialVerifier::new(storage) .with_secret(secret) .verify(&credential, payload) .await?; println!("Verification successful!"); Ok(()) } ``` -------------------------------- ### Minimal Usage of CredentialBuilder and CredentialVerifier Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/INDEX.md Demonstrates the most basic setup for creating and verifying credentials using in-memory storage. Ensure you have the necessary imports. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; let storage = Arc::new(MemoryStorage::new()); let cred = CredentialBuilder::new(b"secret").sign(b"data")?; CredentialVerifier::new(storage) .with_secret(b"secret") .verify(&cred, b"data") .await?; ``` -------------------------------- ### Rust: Using the Same Secret for Signing and Verifying Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example shows the correct approach of using the same shared secret for both signing credentials and verifying them, ensuring successful authentication. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn right_secrets() -> Result<(), nonce_auth::NonceError> { let secret = b"shared-secret-key"; let storage = Arc::new(MemoryStorage::new()); // ✅ Sign with shared secret let credential = CredentialBuilder::new(secret).sign(b"data")?; // ✅ Verify with same secret CredentialVerifier::new(storage) .with_secret(secret) // Same secret! .verify(&credential, b"data") .await?; # Ok(()) # } ``` -------------------------------- ### Example Usage of HybridCleanupStrategy Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Demonstrates creating a HybridCleanupStrategy instance with a request threshold of 100 and a time threshold of 5 minutes. ```rust use nonce_auth::HybridCleanupStrategy; use std::time::Duration; let strategy = HybridCleanupStrategy::new( 100, // requests Duration::from_secs(300), // 5 minutes ); ``` -------------------------------- ### Context Isolation Example (Multi-Tenant/User) Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Illustrates how the same nonce can be used independently in different contexts, such as for different tenants or users. This is achieved by storing nonces alongside their respective contexts. ```text Tenant A: nonce="abc123" → Stored in context="tenant_a" Tenant B: nonce="abc123" → Stored in context="tenant_b" Both are allowed because they're in different contexts! User 123: nonce="xyz" → Stored in context="user_123" User 456: nonce="xyz" → Stored in context="user_456" Both users can use the same nonce independently. ``` -------------------------------- ### Get Configuration Summary Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Retrieve a human-readable summary of the current Nonce Auth configuration. This is useful for debugging and understanding the active settings. ```rust use nonce_auth::{NonceConfig, ConfigPreset}; let config: NonceConfig = ConfigPreset::Production.into(); println!("{}", config.summary()); // Output: NonceConfig { Storage TTL: 300s, Time Window: 60s } ``` -------------------------------- ### Full Example of Nonce Auth Components Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/module-index.md Demonstrates the complete workflow of creating, signing, and verifying a nonce credential using various components of the nonce-auth crate, including storage, cleanup strategies, and configuration. ```rust use nonce_auth::{ // Core CredentialBuilder, CredentialVerifier, NonceCredential, NonceError, // Configuration NonceConfig, ConfigPreset, // Storage storage::{MemoryStorage, NonceStorage}, // Cleanup HybridCleanupStrategy, CleanupStrategy, }; use std::sync::Arc; use std::time::Duration; # async fn full_example() -> Result<(), nonce_auth::NonceError> { // 1. Create storage let storage: Arc = Arc::new(MemoryStorage::new()); // 2. Create cleanup strategy let cleanup = HybridCleanupStrategy::new(100, Duration::from_secs(300)); // 3. Create configuration let config: NonceConfig = ConfigPreset::Production.into(); // 4. Create and sign a credential let credential = CredentialBuilder::new(b"shared_secret") .sign(b"important_data")?; // 5. Verify the credential let verifier = CredentialVerifier::new(storage) .with_secret(b"shared_secret") .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window); verifier.verify(&credential, b"important_data").await?; // 6. Check storage stats let stats = storage.get_stats().await?; println!("Stored {} nonces", stats.total_records); # Ok(()) # } ``` -------------------------------- ### Sign Payload and Print Credential Details Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-builder.md Example demonstrating how to sign a payload and then print the generated nonce, timestamp, and signature. Ensure you have the `nonce_auth` crate imported. ```rust use nonce_auth::CredentialBuilder; let cred = CredentialBuilder::new(b"shared_secret") .sign(b"user_request")?; println!("Nonce: {}", cred.nonce); println!("Timestamp: {}", cred.timestamp); println!("Signature: {}", cred.signature); # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Custom Signing and Verification Logic Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example shows how to implement custom signing and verification logic using the CredentialBuilder and CredentialVerifier, allowing for extended signing formats. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use hmac::Mac; use std::sync::Arc; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = Arc::new(MemoryStorage::new()); // Custom signing with additional context let credential = CredentialBuilder::new(b"secret") .sign_with(|mac, ts, nonce| { mac.update(b"v1:"); mac.update(ts.as_bytes()); mac.update(b":"); mac.update(nonce.as_bytes()); mac.update(b":extra"); })?; // Custom verification with matching structure CredentialVerifier::new(storage) .with_secret(b"secret") .verify_with(&credential, |mac| { mac.update(b"v1:"); mac.update(credential.timestamp.to_string().as_bytes()); mac.update(b":"); mac.update(credential.nonce.as_bytes()); mac.update(b":extra"); }) .await?; # Ok(()) # } ``` -------------------------------- ### Rust: Using Different Secrets for Signing and Verifying Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example illustrates a common mistake where credentials are signed with one secret and verified with a different one. This will lead to verification failure. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn wrong_secrets() { let storage = Arc::new(MemoryStorage::new()); // ❌ Signed with one secret let credential = CredentialBuilder::new(b"secret1").sign(b"data").unwrap(); // ❌ Verified with different secret let result = CredentialVerifier::new(storage) .with_secret(b"secret2") // Wrong! .verify(&credential, b"data") .await; assert!(result.is_err()); // Will fail with InvalidSignature # } ``` -------------------------------- ### Rust: Verifying with the Same Payload Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example shows the correct way to verify a credential by ensuring the payload used during verification matches the payload that was originally signed. This is crucial for security. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn right_payload() -> Result<(), nonce_auth::NonceError> { let payload = b"important_request"; let storage = Arc::new(MemoryStorage::new()); // ✅ Sign payload let credential = CredentialBuilder::new(b"secret").sign(payload)?; // ✅ Verify same payload CredentialVerifier::new(storage) .with_secret(b"secret") .verify(&credential, payload) // Same payload! .await?; # Ok(()) # } ``` -------------------------------- ### Static Preset Configuration Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Use this pattern when your application's configuration is fixed and does not need to change at runtime. It simplifies setup by using predefined presets. ```rust use nonce_auth::{ CredentialVerifier, ConfigPreset, NonceConfig, storage::MemoryStorage }; use std::sync::Arc; let storage = Arc::new(MemoryStorage::new()); let config: NonceConfig = ConfigPreset::Production.into(); let verifier = CredentialVerifier::new(storage) .with_secret(b"shared_secret") .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window); ``` -------------------------------- ### Load NonceConfig from Environment Variables Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Load NonceConfig settings from environment variables using ConfigPreset::FromEnv. This example demonstrates setting a custom storage TTL via the environment. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; // Environment: // export NONCE_AUTH_STORAGE_TTL=900 let config: NonceConfig = ConfigPreset::FromEnv.into(); assert_eq!(config.storage_ttl.as_secs(), 900); ``` -------------------------------- ### Load Time Window from Environment Variables Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Load NonceConfig settings from environment variables using ConfigPreset::FromEnv. This example demonstrates setting a custom time window via the environment. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; // Environment: // export NONCE_AUTH_DEFAULT_TIME_WINDOW=120 let config: NonceConfig = ConfigPreset::FromEnv.into(); assert_eq!(config.time_window.as_secs(), 120); ``` -------------------------------- ### NTP Setup for Time Synchronization Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Ensures client and server time are synchronized using NTP. Use `ntpdate` for Linux/macOS or `timedatectl` for systemd-based systems. ```bash # Linux/macOS sudo ntpdate -s time.nist.gov # or timedatectl set-ntp true ``` -------------------------------- ### Rust: Correctly Setting Shared Secret on Verifier Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example demonstrates the correct way to verify a credential by setting the shared secret on the verifier using `with_secret`. This ensures successful verification. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn right_example() -> Result<(), nonce_auth::NonceError> { let storage = Arc::new(MemoryStorage::new()); let credential = CredentialBuilder::new(b"secret").sign(b"data")?; // ✅ Right: Secret set on verifier CredentialVerifier::new(storage) .with_secret(b"secret") // Add this! .verify(&credential, b"data") .await?; # Ok(()) # } ``` -------------------------------- ### CredentialBuilder Method Chaining Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-builder.md Demonstrates flexible method chaining with CredentialBuilder. Configuration options like nonce generation and time provision can be applied in any order before signing data. Both examples produce identical credentials. ```rust use nonce_auth::CredentialBuilder; // Configuration can be applied in any order let cred1 = CredentialBuilder::new(b"secret") .with_nonce_generator(|| "nonce".to_string()) .with_time_provider(|| Ok(1234567890)) .sign(b"data")?; let cred2 = CredentialBuilder::new(b"secret") .with_time_provider(|| Ok(1234567890)) .with_nonce_generator(|| "nonce".to_string()) .sign(b"data")?; // Both produce identical credentials assert_eq!(cred1.signature, cred2.signature); # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Sign with Custom MAC for API Versioning Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-builder.md Example of using `sign_with` to incorporate API versioning and extra context into the signature. The closure receives the HMAC instance, timestamp, and nonce. ```rust use nonce_auth::CredentialBuilder; use hmac::Mac; let credential = CredentialBuilder::new(b"secret") .sign_with(|mac, ts, nonce| { mac.update(b"API_V1:"); mac.update(ts.as_bytes()); mac.update(b":"); mac.update(nonce.as_bytes()); mac.update(b":extra_context"); })?; # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Configure Kubernetes Deployment with Environment Variables Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Example of configuring NonceAuth in a Kubernetes deployment using environment variables. The `ConfigPreset::FromEnv` allows dynamic configuration based on deployment settings. ```yaml # deployment.yaml env: - name: NONCE_AUTH_STORAGE_TTL value: "300" - name: NONCE_AUTH_DEFAULT_TIME_WINDOW value: "60" - name: DEPLOYMENT_ENV value: "production" ``` ```rust use nonce_auth::{CredentialVerifier, ConfigPreset, NonceConfig, storage::MemoryStorage}; use std::sync::Arc; let config: NonceConfig = ConfigPreset::FromEnv.into(); eprintln!("Configuration: {}", config.summary()); let verifier = CredentialVerifier::new(Arc::new(MemoryStorage::new())) .with_secret(b"k8s_secret") .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window); ``` -------------------------------- ### Sign Structured API Request Components Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-builder.md Example of signing structured data for an API request using `sign_structured`. The order of components is critical for signature generation. ```rust use nonce_auth::CredentialBuilder; // API endpoint with structured data let cred = CredentialBuilder::new(b"api_secret") .sign_structured(&[ b"GET", b"/api/users", b"page=1", ])?; # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Handling CryptoError in Credential Verification Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/errors.md This example demonstrates how to handle a `CryptoError` that occurs when a `CredentialVerifier` is used without properly setting the secret key. It shows a common configuration error where `with_secret()` is forgotten. ```rust use nonce_auth::{CredentialVerifier, storage::MemoryStorage, NonceError}; use std::sync::Arc; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = Arc::new(MemoryStorage::new()); let credential = nonce_auth::CredentialBuilder::new(b"secret").sign(b"data")?; // Verify without setting secret match CredentialVerifier::new(storage) // .with_secret(b"secret") // Oops, forgot this! .verify(&credential, b"data") .await { Err(NonceError::CryptoError(msg)) => { assert!(msg.contains("secret")); println!("Configuration error: {}", msg); } _ => {} } # Ok(()) # } ``` -------------------------------- ### Implement Custom NonceStorage Trait Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Implement the `NonceStorage` trait to create a custom backend for nonce persistence. This example shows the required methods for initialization, retrieval, storage, existence checks, cleanup, and statistics. ```rust use nonce_auth::storage::{NonceStorage, NonceEntry, StorageStats}; use nonce_auth::NonceError; use async_trait::async_trait; use std::time::Duration; pub struct CustomStorage { // Your storage implementation } #[async_trait] impl NonceStorage for CustomStorage { async fn init(&self) -> Result<(), NonceError> { // Initialize Ok(()) } async fn get(&self, nonce: &str, context: Option<&str>) -> Result, NonceError> { // Retrieve nonce todo!() } async fn set(&self, nonce: &str, context: Option<&str>, ttl: Duration) -> Result<(), NonceError> { // Store nonce todo!() } async fn exists(&self, nonce: &str, context: Option<&str>) -> Result { // Check existence todo!() } async fn cleanup_expired(&self, cutoff_time: i64) -> Result { // Remove expired nonces todo!() } async fn get_stats(&self) -> Result { // Return statistics todo!() } } ``` -------------------------------- ### Using Nonce Authentication Configuration Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Demonstrates how to initialize NonceConfig using predefined presets or custom values. ```rust use nonce_auth::{NonceConfig, ConfigPreset}; use std::time::Duration; // Use preset let config = NonceConfig::from_preset(ConfigPreset::Production); // Custom configuration let config = NonceConfig { storage_ttl: Duration::from_secs(300), time_window: Duration::from_secs(30), }; ``` -------------------------------- ### Get Storage Statistics Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Retrieve statistics about the current state of the storage, such as the total number of nonces and backend information. Requires an async context. ```rust use nonce_auth::storage::MemoryStorage; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = MemoryStorage::new(); let stats = storage.get_stats().await?; println!("Total nonces: {}", stats.total_records); println!("Backend: {}", stats.backend_info); # Ok(()) # } ``` -------------------------------- ### Use Development Configuration Settings Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Quickly apply development-friendly settings for nonce authentication. This is a shortcut to load a predefined configuration suitable for development environments. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::Development.into(); ``` -------------------------------- ### Rust: Verifying with a Different Payload Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example demonstrates the error of attempting to verify a credential with a payload that differs from the original signed payload. This will result in an `InvalidSignature` error. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn wrong_payload() { let storage = Arc::new(MemoryStorage::new()); // ❌ Signed with one payload let credential = CredentialBuilder::new(b"secret").sign(b"original").unwrap(); // ❌ Verified with different payload let result = CredentialVerifier::new(storage) .with_secret(b"secret") .verify(&credential, b"modified") // Wrong! .await; assert!(result.is_err()); // Will fail with InvalidSignature # } ``` -------------------------------- ### Add Nonce Auth to Project Source: https://github.com/kookyleo/nonce-auth/blob/main/README.md Add the nonce-auth and tokio crates to your Cargo.toml file to begin using the library. ```bash cargo add nonce-auth tokio ``` -------------------------------- ### Rust: Forgetting Shared Secret on Verifier Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md This example shows the incorrect way to verify a credential without setting the shared secret on the verifier. This will result in an error. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn wrong_example() { let storage = Arc::new(MemoryStorage::new()); let credential = CredentialBuilder::new(b"secret").sign(b"data").unwrap(); // ❌ Wrong: No secret set on verifier! let result = CredentialVerifier::new(storage) .verify(&credential, b"data") .await; assert!(result.is_err()); // Will fail # } ``` -------------------------------- ### Basic Credential Creation and Verification Source: https://github.com/kookyleo/nonce-auth/blob/main/README.md Demonstrates creating a signed credential with a payload and verifying it. Includes a test for replay attack detection. Requires tokio for async execution and MemoryStorage for simplicity. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage, storage::NonceStorage}; use std::sync::Arc; #[tokio::main] async fn main() -> Result<(), Box> { // Shared secret between credential creator and verifier let secret = b"my-super-secret-key"; let payload = b"important_api_request_data"; // Create storage backend (in-memory for this example) let storage: Arc = Arc::new(MemoryStorage::new()); // 1. Create a credential let credential = CredentialBuilder::new(secret) .sign(payload)?; println!("✅ Generated credential with nonce: {}", credential.nonce); // 2. Verify the credential CredentialVerifier::new(Arc::clone(&storage)) .with_secret(secret) .verify(&credential, payload) .await?; println!("✅ First verification successful!"); // 3. Replay attack is automatically rejected let replay_result = CredentialVerifier::new(storage) .with_secret(secret) .verify(&credential, payload) .await; assert!(replay_result.is_err()); println!("✅ Replay attack correctly rejected!"); Ok(()) } ``` -------------------------------- ### Add Nonce Auth Dependencies (Basic) Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Configure your project's Cargo.toml to include the nonce-auth crate and tokio for asynchronous operations, using only memory storage. ```toml [dependencies] nonce-auth = "0.5" tokio = { version = "1.0", features = ["full"] } ``` -------------------------------- ### Verify Credentials with Multi-User Context Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/INDEX.md Illustrates how to verify credentials in a multi-user environment by providing a user context. This is useful when different users share the same secret or when secrets are user-specific. ```rust CredentialVerifier::new(storage) .with_context(Some(user_id)) .with_secret(user_secret) .verify(&credential, payload) .await?; ``` -------------------------------- ### Get Stable Error Code with `code()` Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/errors.md Use the `code()` method to retrieve a stable string code for programmatic error handling. This is useful for matching specific error types. ```rust use nonce_auth::NonceError; let error = NonceError::DuplicateNonce; assert_eq!(error.code(), "duplicate_nonce"); match error.code() { "duplicate_nonce" => { /* handle replay */ } "invalid_signature" => { /* handle auth failure */ } "timestamp_out_of_window" => { /* handle stale request */ } "storage_error" => { /* handle system error */ } "crypto_error" => { /* handle config/crypto error */ } _ => unreachable!(), } ``` -------------------------------- ### Web Framework Authentication Middleware Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Pseudocode demonstrating how to integrate nonce authentication as middleware in a web framework. Ensure credentials and payload are correctly extracted. ```rust // Pseudocode for web framework integration async fn auth_middleware( request: HttpRequest, ) -> Result { let credential: NonceCredential = extract_credential(&request)?; let payload = extract_payload(&request)?; let verifier = CredentialVerifier::new(storage.clone()) .with_secret(secret) .with_context(Some(user_id)); verifier.verify(&credential, &payload).await?; Ok(next_handler().await) } ``` -------------------------------- ### NonceStorage Trait Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md The core trait that all storage backends must implement. It defines methods for initializing storage, getting, setting, checking existence, cleaning up expired entries, and retrieving storage statistics. ```APIDOC ## NonceStorage Trait ### Description Core trait that all storage backends must implement. ### Methods - `init(&self) -> Result<(), NonceError>`: Initialize storage (optional). - `get(&self, nonce: &str, context: Option<&str>) -> Result, NonceError>`: Get nonce entry. - `set(&self, nonce: &str, context: Option<&str>, ttl: Duration) -> Result<(), NonceError>`: Store nonce. - `exists(&self, nonce: &str, context: Option<&str>) -> Result`: Check if nonce exists. - `cleanup_expired(&self, cutoff_time: i64) -> Result`: Clean up expired entries. - `get_stats(&self) -> Result`: Get storage statistics. ``` -------------------------------- ### Initialize SQLiteStorage Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Initializes SQLite storage. Requires the 'sqlite-storage' feature to be enabled. Provide the path to the SQLite database file. ```rust #[cfg(feature = "sqlite-storage")] use nonce_auth::SQLiteStorage; let storage = SQLiteStorage::new("nonces.db").await?; ``` -------------------------------- ### NonceStorage Trait Definition Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md The core trait that all storage backends must implement, defining methods for initializing, getting, setting, checking existence, cleaning up expired entries, and retrieving statistics for nonces. ```rust #[async_trait] pub trait NonceStorage: Send + Sync { // Initialize storage (optional) async fn init(&self) -> Result<(), NonceError>; // Get nonce entry async fn get(&self, nonce: &str, context: Option<&str>) -> Result, NonceError>; // Store nonce async fn set(&self, nonce: &str, context: Option<&str>, ttl: Duration) -> Result<(), NonceError>; // Check if nonce exists async fn exists(&self, nonce: &str, context: Option<&str>) -> Result; // Clean up expired entries async fn cleanup_expired(&self, cutoff_time: i64) -> Result; // Get storage statistics async fn get_stats(&self) -> Result; } ``` -------------------------------- ### Add Nonce Auth Dependencies (Full Feature) Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Configure your project's Cargo.toml to include the nonce-auth crate with features for Redis and SQLite storage, and metrics, along with tokio for async operations. ```toml [dependencies] nonce-auth = { version = "0.5", features = [ "redis-storage", "sqlite-storage", "metrics" ] } tokio = { version = "1.0", features = ["full"] } ``` -------------------------------- ### Configure CredentialVerifier with Production Settings Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/INDEX.md Shows how to apply pre-defined configuration presets, such as production settings, to the CredentialVerifier. You can customize storage TTL and time windows. ```rust use nonce_auth::{CredentialVerifier, ConfigPreset}; let config = ConfigPreset::Production.into(); // Use config.storage_ttl and config.time_window ``` -------------------------------- ### Simple Signing with CredentialBuilder Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Demonstrates the standard signing process using CredentialBuilder. This method signs the timestamp, nonce, and payload. It is suitable for most common use cases. ```rust use nonce_auth::CredentialBuilder; let credential = CredentialBuilder::new(b"secret") .sign(b"payload")?; # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Create Custom Nonce Configuration Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Define a custom NonceConfig with specific storage TTL and time window durations. The configuration is then validated, and any generated warnings are printed. ```rust use nonce_auth::NonceConfig; use std::time::Duration; let config = NonceConfig { storage_ttl: Duration::from_secs(600), time_window: Duration::from_secs(120), }; let warnings = config.validate(); for warning in warnings { eprintln!("Warning: {}", warning); } ``` -------------------------------- ### Minimal Imports for Single Credential Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/module-index.md Demonstrates minimal imports required for building and verifying a single credential using MemoryStorage. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; let credential = CredentialBuilder::new(b"secret").sign(b"data")?; let storage = Arc::new(MemoryStorage::new()); CredentialVerifier::new(storage).with_secret(b"secret").verify(&credential, b"data").await?; ``` -------------------------------- ### Configure Web API with Production Preset Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Recommended settings for a REST API with synchronized server clocks using the `Production` preset. This configuration balances security and performance for typical web services. ```rust use nonce_auth::{CredentialVerifier, ConfigPreset, storage::MemoryStorage}; use std::sync::Arc; use std::time::Duration; let config = ConfigPreset::Production.into(); let verifier = CredentialVerifier::new(Arc::new(MemoryStorage::new())) .with_secret(b"api_secret") .with_storage_ttl(Duration::from_secs(300)) .with_time_window(Duration::from_secs(60)); ``` -------------------------------- ### Create Verifiers with Different Configurations Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Demonstrates how to create multiple `CredentialVerifier` instances, each with a distinct configuration, to handle different security requirements for requests. This approach is useful when runtime configuration changes are needed. ```rust use nonce_auth::{CredentialVerifier, ConfigPreset, storage::MemoryStorage}; use std::sync::Arc; let storage = Arc::new(MemoryStorage::new()); // Create verifier for normal requests let normal_verifier = CredentialVerifier::new(Arc::clone(&storage)) .with_secret(b"secret") .with_storage_ttl(ConfigPreset::Production.into().storage_ttl); // Create verifier for high-security requests let secure_verifier = CredentialVerifier::new(Arc::clone(&storage)) .with_secret(b"secret") .with_storage_ttl(ConfigPreset::HighSecurity.into().storage_ttl); ``` -------------------------------- ### verify_with Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-verifier.md Verifies a Nonce Credential using a custom MAC construction function. This allows for flexible MAC generation logic, provided it matches the logic used during signing. ```APIDOC ## verify_with ### Description Verifies using a custom MAC construction function. This method allows for advanced verification scenarios where the MAC generation logic differs from the standard HMAC-SHA256, provided the logic precisely matches the signing process. ### Method `async verify_with(self, credential: &NonceCredential, mac_fn: F) -> Result<(), NonceError>` ### Parameters #### Path Parameters - **credential** (`&NonceCredential`) - Required - The NonceCredential to verify. - **mac_fn** (`F where F: FnOnce(&mut Hmac)`) - Required - A closure that builds the MAC for comparison. It receives the timestamp and nonce from the credential and uses `mac.update()` to add data in the same order as signing. ### Notes - Must match the MAC construction from `sign_with()`. - The closure receives timestamp and nonce from the credential. - Use `mac.update()` to add data in the same order as signing. ### Response #### Success Response (200) - `()` - Indicates successful verification. #### Errors - `NonceError::TimestampOutOfWindow` — Request is too old or too new. - `NonceError::InvalidSignature` — Signature verification failed. - `NonceError::DuplicateNonce` — Nonce has already been used. - `NonceError::CryptoError` — Cryptographic operation failed (no secret configured). - `NonceError::StorageError` — Backend storage operation failed. ``` -------------------------------- ### Use High Security Configuration Settings Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Quickly apply high-security settings for nonce authentication. This is a shortcut to load a predefined configuration prioritizing security over performance. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::HighSecurity.into(); ``` -------------------------------- ### Environment Variable Configuration Preset Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md The FromEnv preset is ideal for containerized deployments and infrastructure as code. It allows runtime configuration via environment variables NONCE_AUTH_STORAGE_TTL and NONCE_AUTH_DEFAULT_TIME_WINDOW, with default values provided. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::FromEnv.into(); // Reads from environment variables with defaults: // - NONCE_AUTH_STORAGE_TTL (default: 300) // - NONCE_AUTH_DEFAULT_TIME_WINDOW (default: 60) ``` -------------------------------- ### Initialize RedisStorage Source: https://github.com/kookyleo/nonce-auth/blob/main/docs/USERGUIDE.md Initializes Redis storage. Requires the 'redis-storage' feature to be enabled. Specify the Redis connection URL and a unique application name. ```rust #[cfg(feature = "redis-storage")] use nonce_auth::RedisStorage; let storage = RedisStorage::new("redis://localhost:6379", "myapp")?; ``` -------------------------------- ### Convert ConfigPreset to NonceConfig Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Demonstrates how to convert a `ConfigPreset` enum variant into a `NonceConfig` struct. This is useful for initializing the authentication configuration. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::Production.into(); ``` -------------------------------- ### Custom Signing with CredentialBuilder Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Shows how to implement custom signing logic using a closure. This provides maximum flexibility for complex signing requirements, protocol-specific needs, or integrating with legacy systems. ```rust use nonce_auth::CredentialBuilder; use hmac::Mac; let credential = CredentialBuilder::new(b"secret") .sign_with(|mac, timestamp, nonce| { mac.update(b"API_V2:"); mac.update(timestamp.as_bytes()); mac.update(b":"); mac.update(nonce.as_bytes()); mac.update(b":custom_context"); })?; # Ok::<(), nonce_auth::NonceError>(()) ``` -------------------------------- ### Complete Imports for All Features Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/module-index.md Shows a comprehensive set of imports for utilizing all features of the nonce-auth crate, including core types, storage, signature algorithms, cleanup strategies, and optional metrics. ```rust // Core types use nonce_auth::{ CredentialBuilder, CredentialVerifier, NonceCredential, NonceError, NonceConfig, ConfigPreset, }; // Storage use nonce_auth::storage::{NonceStorage, MemoryStorage, NonceEntry, StorageStats}; // Signature algorithms use nonce_auth::signature::{SignatureAlgorithm, MacLike}; // Cleanup strategies use nonce_auth::{CleanupStrategy, HybridCleanupStrategy, CustomCleanupStrategy}; // Metrics (if enabled) #[cfg(feature = "metrics")] use nonce_auth::{MetricsCollector, NonceMetrics}; ``` -------------------------------- ### Initialize MemoryStorage Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/core-concepts.md Instantiate the in-memory storage for nonces. This is suitable for single-instance applications where data persistence across restarts is not required. ```rust use nonce_auth::storage::MemoryStorage; let storage = MemoryStorage::new(); ``` -------------------------------- ### Production Configuration Preset Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Use the Production preset for general API servers and web services. It balances security with storage usage, setting storage TTL to 5 minutes and time window to 1 minute. ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::Production.into(); // storage_ttl: 300 seconds (5 minutes) // time_window: 60 seconds (1 minute) ``` -------------------------------- ### Import Core and Storage for Nonce Auth Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Imports necessary components for credential building and verification, including memory storage. ```rust use nonce_auth::{CredentialBuilder, CredentialVerifier, storage::MemoryStorage}; use std::sync::Arc; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = Arc::new(MemoryStorage::new()); let credential = CredentialBuilder::new(b"secret").sign(b"data")?; CredentialVerifier::new(storage) .with_secret(b"secret") .verify(&credential, b"data") .await?; # Ok(()) # } ``` -------------------------------- ### Run All Performance Tests Source: https://github.com/kookyleo/nonce-auth/blob/main/tests/README.md Execute all integration performance tests to compare backends and detect regressions. This command runs the main integration test file. ```bash cargo test --test integration_performance ``` -------------------------------- ### Custom Configuration Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Use this pattern when presets do not meet your specific needs. It allows fine-grained control over parameters like storage TTL and time window. ```rust use nonce_auth::{ CredentialVerifier, NonceConfig, storage::MemoryStorage }; use std::sync::Arc; use std::time::Duration; // Customize for specific application requirements let config = NonceConfig { // Allow 10 minutes of nonce lifetime for batch operations storage_ttl: Duration::from_secs(600), // Allow up to 2 minutes for slow clients or high-latency networks time_window: Duration::from_secs(120), }; // Validate configuration let warnings = config.validate(); if let Some(warning) = warnings.iter().find(|w| w.contains("TTL should be")) { eprintln!("Note: {}", warning); } let storage = Arc::new(MemoryStorage::new()); let verifier = CredentialVerifier::new(storage) .with_secret(b"shared_secret") .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window); ``` -------------------------------- ### Development Configuration Preset Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md The Development preset is suitable for local testing and debugging environments. It offers a more relaxed security posture with a longer storage TTL (10 minutes) and time window (2 minutes). ```rust use nonce_auth::{ConfigPreset, NonceConfig}; let config: NonceConfig = ConfigPreset::Development.into(); // storage_ttl: 600 seconds (10 minutes) // time_window: 120 seconds (2 minutes) ``` -------------------------------- ### Run Integration Tests with All Features Source: https://github.com/kookyleo/nonce-auth/blob/main/tests/README.md Execute all integration performance tests with all available features enabled. This provides a comprehensive performance validation across all functionalities. ```bash cargo test --test integration_performance --all-features ``` -------------------------------- ### CredentialBuilder Usage Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-credential-builder.md Demonstrates how to use the CredentialBuilder to create signed credentials. The builder supports method chaining in any order, allowing flexible configuration of nonce generation and time provision before signing data. ```APIDOC ## Method Chaining The builder supports flexible method chaining in any order. ```rust use nonce_auth::CredentialBuilder; // Configuration can be applied in any order let cred1 = CredentialBuilder::new(b"secret") .with_nonce_generator(|| "nonce".to_string()) .with_time_provider(|| Ok(1234567890)) .sign(b"data")?; let cred2 = CredentialBuilder::new(b"secret") .with_time_provider(|| Ok(1234567890)) .with_nonce_generator(|| "nonce".to_string()) .sign(b"data")?; // Both produce identical credentials assert_eq!(cred1.signature, cred2.signature); # Ok::<(), nonce_auth::NonceError>(()) ``` ``` -------------------------------- ### NonceStorage::init Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/api-reference-storage.md Optional initialization method called once when storage is first used. Useful for resource allocation like schema creation or connection pool initialization. ```APIDOC ## NonceStorage::init ### Description Optional initialization method called once when storage is first used. ### Method `init` ### Parameters None ### Returns - `Ok(())` — Initialization successful - `Err(NonceError)` — Storage operation failed ### Use cases: - Schema creation for database-backed storage - Connection pool initialization - Resource allocation ``` -------------------------------- ### Use Batch Operations for Storage Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/quick-reference.md Compares individual storage operations with efficient batch operations. Use `batch_set` for inserting multiple nonces at once. ```rust use nonce_auth::storage::MemoryStorage; use std::time::Duration; # async fn example() -> Result<(), nonce_auth::NonceError> { let storage = MemoryStorage::new(); // Bad: individual operations for i in 0..100 { storage.set(&format!("nonce{}", i), None, Duration::from_secs(300)).await?; } // Good: batch operation let nonces: Vec<_> = (0..100) .map(|i| (format!("nonce{}", i).leak() as &str, None)) .collect(); storage.batch_set(nonces, Duration::from_secs(300)).await?; # Ok(()) # } ``` -------------------------------- ### Direct NonceConfig Creation Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Create a custom NonceConfig directly using the struct. This is useful for setting specific storage TTL and time window values programmatically. The configuration can be validated for correctness. ```rust use nonce_auth::NonceConfig; use std::time::Duration; let config = NonceConfig { storage_ttl: Duration::from_secs(600), time_window: Duration::from_secs(120), }; // Validate configuration let warnings = config.validate(); for warning in warnings { eprintln!("Warning: {}", warning); } println!("{}", config.summary()); ``` -------------------------------- ### Strategy Pattern for Runtime Configuration Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/configuration.md Implements a strategy pattern using an enum to select and apply different Nonce Auth configurations at runtime. This allows for dynamic adjustment of verifier settings based on request type. ```rust use nonce_auth::{CredentialVerifier, ConfigPreset, NonceConfig, storage::MemoryStorage}; use std::sync::Arc; enum RequestSecurity { Normal, HighSecurity, } fn create_verifier( storage: Arc, security: RequestSecurity, secret: &[u8], ) -> CredentialVerifier { let config: NonceConfig = match security { RequestSecurity::Normal => ConfigPreset::Production.into(), RequestSecurity::HighSecurity => ConfigPreset::HighSecurity.into(), }; CredentialVerifier::new(storage) .with_secret(secret) .with_storage_ttl(config.storage_ttl) .with_time_window(config.time_window) } ``` -------------------------------- ### Handle NonceError using match and helper methods Source: https://github.com/kookyleo/nonce-auth/blob/main/_autodocs/types.md Shows how to handle `NonceError` variants using a match statement and how to use helper methods like `code()`, `is_authentication_error()`, and `is_temporary()` for error classification and debugging. ```rust use nonce_auth::NonceError; let error = NonceError::DuplicateNonce; match error.code() { "duplicate_nonce" => println!("Replay attack detected"), "invalid_signature" => println!("Tampered request"), "timestamp_out_of_window" => println!("Stale request"), _ => println!("Other error"), } // Classification if error.is_authentication_error() { println!("Authentication failed"); } if error.is_temporary() { println!("Might succeed if retried"); } ```