auth-framework 0.5.0-rc19

A comprehensive, production-ready authentication and authorization framework for Rust applications
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# Storage Backends Guide


This guide covers the various storage backends available in auth-framework and
how to configure them for different use cases.

## Quick Decision Guide


Choose the right backend for your deployment scenario:

| Scenario                                     | Recommended backend |           Feature flag           |
| -------------------------------------------- | ------------------: | :------------------------------: |
| Local development or automated tests         |           In-memory |   *(none — always available)*    |
| Single-node production deployment            |          PostgreSQL | `postgres-storage` (**default**) |
| Multi-node or horizontally scaled deployment |  PostgreSQL + Redis |         `tiered-storage`         |
| Session caching / distributed rate limiting  |               Redis |         `redis-storage`          |
| Existing MySQL/MariaDB infrastructure        |               MySQL |         `mysql-storage`          |
| High-throughput, single-process              |      UnifiedStorage |   `performance-optimization`     |

**Default build:** The `postgres-storage` feature is enabled by default. New
projects connect to PostgreSQL without any feature selection. If you do not have
a PostgreSQL instance, the in-memory backend is still available for local
development and tests, but it should not be treated as a production fallback.

### Which backends are default vs. optional?


| Backend           |       Default        | Rationale                                              |
| ----------------- | :------------------: | ------------------------------------------------------ |
| In-memory         |     ✅ (no flag)      | Zero-dependency dev/test backend; always present       |
| **PostgreSQL**    |`postgres-storage` | Production-grade ACID store; most users need it        |
| Redis             |`redis-storage`   | Requires a Redis cluster; opt-in for performance/scale |
| MySQL             |`mysql-storage`   | Alternative to Postgres; bring your own infra          |
| Tiered (Redis+PG) |`tiered-storage`  | Optimization feature; higher operational complexity    |
| UnifiedStorage    |`performance-optimization` | In-process DashMap; single-process only       |

To opt out of PostgreSQL (e.g. for a read-only CLI tool), use
`default-features = false`:

```toml
[dependencies]
auth-framework = { version = "0.5", default-features = false, features = ["redis-storage"] }
```

---

## Overview


Auth-framework supports multiple storage backends:

- **In-Memory** (`MemoryStorage`): Fast, lightweight, perfect for development
- **Redis** (`RedisStorage`): High-performance distributed caching
- **PostgreSQL** (`PostgresStorage`): Robust ACID-compliant storage
- **MySQL** (`MySqlStorage`): Alternative relational storage
- **UnifiedStorage**: DashMap-based high-performance in-process storage
- **EncryptedStorage**: Transparent encryption wrapper for any backend

All backends implement the `AuthStorage` trait:

```rust
#[async_trait]

pub trait AuthStorage: Send + Sync {
    async fn store_token(&self, token: &AuthToken) -> Result<()>;
    async fn get_token(&self, token_id: &str) -> Result<Option<AuthToken>>;
    async fn get_token_by_access_token(&self, access_token: &str) -> Result<Option<AuthToken>>;
    async fn update_token(&self, token: &AuthToken) -> Result<()>;
    async fn delete_token(&self, token_id: &str) -> Result<()>;
    async fn list_user_tokens(&self, user_id: &str) -> Result<Vec<AuthToken>>;

    async fn store_session(&self, session_id: &str, data: &SessionData) -> Result<()>;
    async fn get_session(&self, session_id: &str) -> Result<Option<SessionData>>;
    async fn delete_session(&self, session_id: &str) -> Result<()>;
    async fn list_user_sessions(&self, user_id: &str) -> Result<Vec<SessionData>>;
    async fn count_active_sessions(&self) -> Result<u64>;

    async fn store_kv(&self, key: &str, value: &[u8], ttl: Option<Duration>) -> Result<()>;
    async fn get_kv(&self, key: &str) -> Result<Option<Vec<u8>>>;
    async fn delete_kv(&self, key: &str) -> Result<()>;
    async fn list_kv_keys(&self, prefix: &str) -> Result<Vec<String>>;

    async fn cleanup_expired(&self) -> Result<()>;
}
```

---

## In-Memory Storage


The in-memory storage backend stores all data in RAM and is ideal for
development, testing, and single-instance applications.

### Setup


```rust
use auth_framework::storage::MemoryStorage;

// Basic — uses default cleanup interval and TTL
let storage = MemoryStorage::new();
```

### Builder Pattern


```rust
use auth_framework::storage::InMemoryConfig;
use std::time::Duration;

let storage = InMemoryConfig::new()
    .with_cleanup_interval(Duration::from_secs(60))
    .with_default_ttl(Duration::from_secs(1800))
    .build();
```

### Configuration Options


| Option | Default | Description |
|--------|---------|-------------|
| `cleanup_interval` | 5 minutes | How often to remove expired data |
| `default_ttl` | 1 hour | Default expiration time for stored data |

### Using with AuthFramework


`AuthFramework::new(config)` uses in-memory storage by default — no extra
setup required:

```rust
use auth_framework::{AuthFramework, config::AuthConfig};

let config = AuthConfig::new();
let mut auth = AuthFramework::new(config);
auth.initialize().await?;
```

### Use Cases


- **Development**: Quick setup without external dependencies
- **Testing**: Isolated test environments with fast cleanup
- **Single-instance apps**: Applications that don't need persistence
- **Caching layer**: Temporary storage with automatic expiration

---

## Redis Storage


Redis provides high-performance, distributed storage with optional persistence.
Requires the `redis-storage` feature.

### Setup


Add the feature to your `Cargo.toml`:

```toml
[dependencies]
auth-framework = { version = "0.5", features = ["redis-storage"] }
```

```rust
use auth_framework::storage::RedisStorage;
use std::time::Duration;

// Basic setup
let storage = RedisStorage::new("redis://localhost:6379").await?;

// With custom configuration
let storage = RedisStorage::with_config(
    "redis://localhost:6379",
    "auth:",                      // key prefix
    Duration::from_secs(3600),    // default TTL
).await?;
```

### Using with AuthFramework


```rust
use auth_framework::{AuthFramework, config::AuthConfig};
use auth_framework::storage::RedisStorage;
use std::sync::Arc;

let storage = RedisStorage::new("redis://localhost:6379").await?;
let config = AuthConfig::new();
let mut auth = AuthFramework::new_with_storage(config, Arc::new(storage));
auth.initialize().await?;
```

### Data Structure


Redis storage uses the following key patterns:

```text
{prefix}token:{token_id}         -> AuthToken (JSON)
{prefix}access:{access_token}    -> token_id (String)
{prefix}user:{user_id}:tokens    -> [token_ids] (List)
{prefix}session:{session_id}     -> SessionData (JSON)
{prefix}kv:{key}                 -> value (Bytes)
```

### Use Cases


- Distributed applications across multiple nodes
- High-throughput with persistence needs
- Session caching and rate limiting
- Horizontal scaling scenarios

---

## PostgreSQL Storage


PostgreSQL provides robust, ACID-compliant storage and is the recommended
choice for production. Requires the `postgres-storage` feature (enabled by
default).

### Setup


```toml
[dependencies]
auth-framework = { version = "0.5" }  # postgres-storage is on by default
```

```rust
use auth_framework::storage::PostgresStorage;
use sqlx::PgPool;

let pool = PgPool::connect("postgres://user:pass@localhost/auth_db").await?;
let storage = PostgresStorage::new(pool);
storage.migrate().await?;  // Creates tables if they don't exist
```

### Using with AuthFramework


```rust
use auth_framework::{AuthFramework, config::AuthConfig};
use auth_framework::storage::PostgresStorage;
use sqlx::PgPool;
use std::sync::Arc;

let pool = PgPool::connect("postgres://user:pass@localhost/auth_db").await?;
let storage = PostgresStorage::new(pool);
storage.migrate().await?;

let config = AuthConfig::new();
let mut auth = AuthFramework::new_with_storage(config, Arc::new(storage));
auth.initialize().await?;
```

### Database Schema


The `migrate()` method automatically creates these tables:

```sql
CREATE TABLE IF NOT EXISTS auth_tokens (
    token_id    VARCHAR(255) PRIMARY KEY,
    user_id     VARCHAR(255) NOT NULL,
    token_data  JSONB NOT NULL,
    expires_at  TIMESTAMPTZ NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS sessions (
    session_id  VARCHAR(255) PRIMARY KEY,
    user_id     VARCHAR(255) NOT NULL,
    data        JSONB NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    expires_at  TIMESTAMPTZ
);

CREATE TABLE IF NOT EXISTS kv_store (
    key         VARCHAR(512) PRIMARY KEY,
    value       BYTEA NOT NULL,
    expires_at  TIMESTAMPTZ
);
```

### Use Cases


- Production applications requiring data integrity
- Compliance and audit trail requirements
- Long-term data retention
- Complex queries and analytics

---

## MySQL Storage


MySQL provides an alternative relational storage backend for existing
MySQL/MariaDB infrastructure. Requires the `mysql-storage` feature.

### Setup


```toml
[dependencies]
auth-framework = { version = "0.5", features = ["mysql-storage"] }
```

```rust
use auth_framework::storage::MySqlStorage;
use sqlx::MySqlPool;

let pool = MySqlPool::connect("mysql://user:pass@localhost/auth_db").await?;
let storage = MySqlStorage::new(pool);
```

---

## UnifiedStorage (Performance Optimization)


`UnifiedStorage` is a high-performance in-process storage backend built on
`DashMap` with background cleanup, object pooling, and memory arena support.
Requires the `performance-optimization` feature.

### Setup


```toml
[dependencies]
auth-framework = { version = "0.5", features = ["performance-optimization"] }
```

```rust
use auth_framework::storage::{UnifiedStorage, UnifiedStorageConfig};
use std::time::Duration;

// Default configuration
let storage = UnifiedStorage::new();

// Custom configuration
let config = UnifiedStorageConfig {
    initial_capacity: 10_000,
    default_ttl: Duration::from_secs(3600),
    max_memory: 512 * 1024 * 1024, // 512 MB
    ..Default::default()
};
let storage = UnifiedStorage::with_config(config);
```

### Performance Metrics


`UnifiedStorage` tracks hit/miss ratios and memory usage internally:

```rust
let stats = storage.get_stats();
println!("Hits: {}, Misses: {}", stats.hits, stats.misses);
```

### Use Cases


- Single-process, high-throughput workloads
- Benchmarking and performance testing
- Embedded applications without external dependencies
- When sub-millisecond latency is critical

---

## Encrypted Storage


`EncryptedStorage` wraps any other storage backend and transparently encrypts
data at rest. Always available — no feature flag required.

```rust
use auth_framework::storage::{EncryptedStorage, MemoryStorage};

let inner = MemoryStorage::new();
let storage = EncryptedStorage::new(inner, encryption_key);
```

---

## Storage Backend Comparison


| Feature              | In-Memory      | Redis           | PostgreSQL    | UnifiedStorage  |
| -------------------- | -------------- | --------------- | ------------- | --------------- |
| **Performance**      | Excellent      | Very Good       | Good          | Excellent       |
| **Scalability**      | Single process | Highly scalable | Very scalable | Single process  |
| **Persistence**      | None           | Optional        | Full          | None            |
| **ACID compliance**  | N/A            | Limited         | Full          | N/A             |
| **Setup complexity** | Minimal        | Low             | Moderate      | Minimal         |
| **Best for**         | Dev/Testing    | Distributed     | Production    | High-throughput |

## Choosing the Right Backend


### Use In-Memory When


- Developing or testing applications
- Building single-instance applications
- Performance is critical and persistence isn't needed
- You want zero external dependencies

### Use Redis When


- Building distributed applications
- You need high performance with some persistence
- Implementing caching strategies
- Scaling horizontally across multiple instances

### Use PostgreSQL When


- Building production applications
- Data integrity is critical
- Compliance requires audit trails
- Long-term data retention is important

### Use UnifiedStorage When


- Running a single-process server
- Sub-millisecond latency is required
- External dependencies are not an option
- Persistence is not needed

## Testing with Different Backends


```rust
#[cfg(test)]

mod tests {
    use auth_framework::{AuthFramework, config::AuthConfig};
    use auth_framework::storage::MemoryStorage;
    use std::sync::Arc;

    #[tokio::test]
    async fn test_with_memory_storage() {
        let config = AuthConfig::new();
        let mut auth = AuthFramework::new(config);
        auth.initialize().await.unwrap();

        let user_id = auth
            .register_user("alice", "alice@test.com", "P@ssw0rd!")
            .await
            .unwrap();
        assert!(!user_id.is_empty());
    }
}
```