sreekarnv-fastauth 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sreekarnv_fastauth-0.2.0/LICENSE +21 -0
- sreekarnv_fastauth-0.2.0/PKG-INFO +696 -0
- sreekarnv_fastauth-0.2.0/README.md +662 -0
- sreekarnv_fastauth-0.2.0/fastauth/__init__.py +147 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/__init__.py +0 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/__init__.py +19 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/email_change.py +52 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/email_verification.py +20 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/oauth_accounts.py +103 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/oauth_states.py +72 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/password_reset.py +20 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/refresh_tokens.py +20 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/roles.py +139 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/sessions.py +34 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/base/users.py +113 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/__init__.py +45 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/email_change.py +47 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/email_verification.py +46 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/models.py +262 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/oauth_accounts.py +81 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/oauth_states.py +59 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/password_reset.py +46 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/refresh_tokens.py +48 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/roles.py +109 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/sessions.py +78 -0
- sreekarnv_fastauth-0.2.0/fastauth/adapters/sqlalchemy/users.py +73 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/__init__.py +0 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/account.py +189 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/auth.py +354 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/dependencies.py +139 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/oauth.py +286 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/schemas.py +78 -0
- sreekarnv_fastauth-0.2.0/fastauth/api/sessions.py +112 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/__init__.py +0 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/account.py +192 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/email_verification.py +60 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/hashing.py +21 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/oauth.py +321 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/password_reset.py +65 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/refresh_tokens.py +74 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/roles.py +244 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/sessions.py +136 -0
- sreekarnv_fastauth-0.2.0/fastauth/core/users.py +86 -0
- sreekarnv_fastauth-0.2.0/fastauth/email/__init__.py +0 -0
- sreekarnv_fastauth-0.2.0/fastauth/email/base.py +9 -0
- sreekarnv_fastauth-0.2.0/fastauth/email/console.py +9 -0
- sreekarnv_fastauth-0.2.0/fastauth/email/factory.py +14 -0
- sreekarnv_fastauth-0.2.0/fastauth/email/smtp.py +38 -0
- sreekarnv_fastauth-0.2.0/fastauth/providers/__init__.py +68 -0
- sreekarnv_fastauth-0.2.0/fastauth/providers/base.py +108 -0
- sreekarnv_fastauth-0.2.0/fastauth/providers/google.py +152 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/__init__.py +0 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/email_verification.py +10 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/jwt.py +60 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/limits.py +16 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/oauth.py +118 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/password_reset.py +10 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/rate_limit.py +42 -0
- sreekarnv_fastauth-0.2.0/fastauth/security/refresh.py +16 -0
- sreekarnv_fastauth-0.2.0/fastauth/settings.py +32 -0
- sreekarnv_fastauth-0.2.0/pyproject.toml +124 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sreekar V Nutulapati
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: sreekarnv-fastauth
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Production-ready authentication for FastAPI applications
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: fastapi,authentication,auth,jwt,oauth,rbac,session
|
|
7
|
+
Author: Sreekar Nutulapati
|
|
8
|
+
Author-email: sreekarnv1@gmail.com
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Framework :: FastAPI
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Requires-Dist: argon2-cffi (>=25.1.0,<26.0.0)
|
|
22
|
+
Requires-Dist: fastapi[all] (>=0.125.0,<0.126.0)
|
|
23
|
+
Requires-Dist: httpx (>=0.27.0,<0.28.0)
|
|
24
|
+
Requires-Dist: pydantic-settings (>=2.12.0,<3.0.0)
|
|
25
|
+
Requires-Dist: python-jose (>=3.5.0,<4.0.0)
|
|
26
|
+
Requires-Dist: sqlmodel (>=0.0.27,<0.0.28)
|
|
27
|
+
Project-URL: Bug Tracker, https://github.com/sreekarnv/fastauth/issues
|
|
28
|
+
Project-URL: Changelog, https://github.com/sreekarnv/fastauth/blob/main/CHANGELOG.md
|
|
29
|
+
Project-URL: Documentation, https://sreekarnv.github.io/fastauth/
|
|
30
|
+
Project-URL: Homepage, https://github.com/sreekarnv/fastauth
|
|
31
|
+
Project-URL: Repository, https://github.com/sreekarnv/fastauth
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# FastAuth
|
|
35
|
+
|
|
36
|
+
> Production-ready authentication for FastAPI applications
|
|
37
|
+
|
|
38
|
+
FastAuth is a flexible, database-agnostic authentication library for FastAPI that provides secure user authentication, session management, and authorization out of the box.
|
|
39
|
+
|
|
40
|
+
[](https://github.com/sreekarnv/fastauth/actions/workflows/ci.yml)
|
|
41
|
+
[](https://www.python.org/downloads/)
|
|
42
|
+
[](https://opensource.org/licenses/MIT)
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
- **Complete Authentication Flow** - Registration, login, logout, and token refresh
|
|
47
|
+
- **Session Management** - Track and manage active user sessions across devices
|
|
48
|
+
- **Role-Based Access Control (RBAC)** - Fine-grained authorization with roles and permissions
|
|
49
|
+
- **Email Verification** - Secure email verification with expiring tokens
|
|
50
|
+
- **Password Reset** - Self-service password reset via email
|
|
51
|
+
- **Refresh Tokens** - Long-lived refresh tokens with rotation support
|
|
52
|
+
- **Rate Limiting** - Built-in rate limiting for authentication endpoints
|
|
53
|
+
- **Database Agnostic** - Adapter pattern supports any database (SQLAlchemy included)
|
|
54
|
+
- **Type Safe** - Full type hints and Pydantic validation
|
|
55
|
+
- **Production Ready** - Secure defaults, comprehensive tests, and CI/CD pipeline
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
### From PyPI (Coming Soon)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install fastauth
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### From Source
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/sreekarnv/fastauth.git
|
|
69
|
+
cd fastauth
|
|
70
|
+
pip install .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### With Poetry
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
poetry add fastauth
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
Here's a complete authentication system in under 5 minutes:
|
|
82
|
+
|
|
83
|
+
### 1. Install FastAuth
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install fastauth
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 2. Create Your Application
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from fastapi import FastAPI, Depends
|
|
93
|
+
from sqlmodel import Session, SQLModel, create_engine
|
|
94
|
+
from fastauth import auth_router, sessions_router
|
|
95
|
+
from fastauth.api import dependencies
|
|
96
|
+
from fastauth.adapters.sqlalchemy.models import User
|
|
97
|
+
|
|
98
|
+
# Database setup
|
|
99
|
+
DATABASE_URL = "sqlite:///./app.db"
|
|
100
|
+
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
|
|
101
|
+
|
|
102
|
+
def init_db():
|
|
103
|
+
SQLModel.metadata.create_all(engine)
|
|
104
|
+
|
|
105
|
+
def get_session():
|
|
106
|
+
with Session(engine) as session:
|
|
107
|
+
yield session
|
|
108
|
+
|
|
109
|
+
# Create FastAPI app
|
|
110
|
+
app = FastAPI(title="My App")
|
|
111
|
+
|
|
112
|
+
# Initialize database
|
|
113
|
+
init_db()
|
|
114
|
+
|
|
115
|
+
# Include FastAuth routers
|
|
116
|
+
app.include_router(auth_router)
|
|
117
|
+
app.include_router(sessions_router)
|
|
118
|
+
|
|
119
|
+
# Override session dependency
|
|
120
|
+
app.dependency_overrides[dependencies.get_session] = get_session
|
|
121
|
+
|
|
122
|
+
# Protected route example
|
|
123
|
+
from fastauth.api.dependencies import get_current_user
|
|
124
|
+
|
|
125
|
+
@app.get("/protected")
|
|
126
|
+
def protected_route(current_user: User = Depends(get_current_user)):
|
|
127
|
+
return {"message": f"Hello {current_user.email}!"}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### 3. Configure Environment Variables
|
|
131
|
+
|
|
132
|
+
Create a `.env` file:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# JWT Settings
|
|
136
|
+
JWT_SECRET_KEY=your-secret-key-here-change-in-production
|
|
137
|
+
JWT_ALGORITHM=HS256
|
|
138
|
+
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
|
139
|
+
REFRESH_TOKEN_EXPIRE_DAYS=7
|
|
140
|
+
|
|
141
|
+
# Email Settings (optional - uses console by default)
|
|
142
|
+
EMAIL_PROVIDER=console # or smtp, sendgrid, resend, ses
|
|
143
|
+
REQUIRE_EMAIL_VERIFICATION=false # Set to true in production
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 4. Run Your Application
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
uvicorn main:app --reload
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### 5. Try It Out
|
|
153
|
+
|
|
154
|
+
Visit `http://localhost:8000/docs` to see the auto-generated API documentation and try:
|
|
155
|
+
|
|
156
|
+
**Register a user:**
|
|
157
|
+
```bash
|
|
158
|
+
curl -X POST "http://localhost:8000/auth/register" \
|
|
159
|
+
-H "Content-Type: application/json" \
|
|
160
|
+
-d '{"email": "user@example.com", "password": "securepassword123"}'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Login:**
|
|
164
|
+
```bash
|
|
165
|
+
curl -X POST "http://localhost:8000/auth/login" \
|
|
166
|
+
-H "Content-Type: application/json" \
|
|
167
|
+
-d '{"email": "user@example.com", "password": "securepassword123"}'
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Access protected route:**
|
|
171
|
+
```bash
|
|
172
|
+
curl -X GET "http://localhost:8000/protected" \
|
|
173
|
+
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
That's it! You now have a working authentication system.
|
|
177
|
+
|
|
178
|
+
## API Endpoints
|
|
179
|
+
|
|
180
|
+
FastAuth automatically adds these endpoints to your application:
|
|
181
|
+
|
|
182
|
+
### Authentication
|
|
183
|
+
|
|
184
|
+
| Method | Endpoint | Description |
|
|
185
|
+
|--------|----------|-------------|
|
|
186
|
+
| `POST` | `/auth/register` | Register a new user |
|
|
187
|
+
| `POST` | `/auth/login` | Login with email and password |
|
|
188
|
+
| `POST` | `/auth/logout` | Logout and revoke refresh token |
|
|
189
|
+
| `POST` | `/auth/refresh` | Get new access token using refresh token |
|
|
190
|
+
| `POST` | `/auth/password-reset/request` | Request password reset email |
|
|
191
|
+
| `POST` | `/auth/password-reset/confirm` | Reset password with token |
|
|
192
|
+
| `POST` | `/auth/email-verification/request` | Request email verification |
|
|
193
|
+
| `POST` | `/auth/email-verification/confirm` | Verify email with token |
|
|
194
|
+
| `POST` | `/auth/email-verification/resend` | Resend verification email |
|
|
195
|
+
|
|
196
|
+
### Session Management
|
|
197
|
+
|
|
198
|
+
| Method | Endpoint | Description |
|
|
199
|
+
|--------|----------|-------------|
|
|
200
|
+
| `GET` | `/sessions` | List all active sessions for authenticated user |
|
|
201
|
+
| `DELETE` | `/sessions/all` | Delete all user sessions (logout from all devices) |
|
|
202
|
+
| `DELETE` | `/sessions/{session_id}` | Delete a specific session |
|
|
203
|
+
|
|
204
|
+
## Architecture
|
|
205
|
+
|
|
206
|
+
FastAuth uses a clean, layered architecture:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
┌─────────────────────────────────────┐
|
|
210
|
+
│ FastAPI Routes │ ← Your application
|
|
211
|
+
├─────────────────────────────────────┤
|
|
212
|
+
│ FastAuth API Layer │ ← HTTP handlers
|
|
213
|
+
├─────────────────────────────────────┤
|
|
214
|
+
│ Core Business Logic │ ← Database-agnostic
|
|
215
|
+
├─────────────────────────────────────┤
|
|
216
|
+
│ Adapter Interface │ ← Abstract base classes
|
|
217
|
+
├─────────────────────────────────────┤
|
|
218
|
+
│ Adapter Implementation │ ← SQLAlchemy, MongoDB, etc.
|
|
219
|
+
│ (SQLAlchemy, MongoDB, etc.) │
|
|
220
|
+
└─────────────────────────────────────┘
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Key Principles:**
|
|
224
|
+
|
|
225
|
+
- **Database Agnostic Core** - Business logic has no database dependencies
|
|
226
|
+
- **Adapter Pattern** - Swap databases by implementing the adapter interface
|
|
227
|
+
- **Dependency Injection** - Easy to customize and test
|
|
228
|
+
- **Type Safety** - Full type hints throughout
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
FastAuth can be configured via environment variables or the `Settings` class:
|
|
233
|
+
|
|
234
|
+
### Environment Variables
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# JWT Configuration
|
|
238
|
+
JWT_SECRET_KEY=your-secret-key-min-32-chars
|
|
239
|
+
JWT_ALGORITHM=HS256
|
|
240
|
+
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
|
241
|
+
REFRESH_TOKEN_EXPIRE_DAYS=7
|
|
242
|
+
|
|
243
|
+
# Email Configuration
|
|
244
|
+
EMAIL_PROVIDER=console # console, smtp, sendgrid, resend, ses
|
|
245
|
+
REQUIRE_EMAIL_VERIFICATION=false
|
|
246
|
+
SMTP_HOST=smtp.gmail.com
|
|
247
|
+
SMTP_PORT=587
|
|
248
|
+
SMTP_USERNAME=your-email@gmail.com
|
|
249
|
+
SMTP_PASSWORD=your-app-password
|
|
250
|
+
SMTP_FROM_EMAIL=noreply@yourapp.com
|
|
251
|
+
|
|
252
|
+
# Rate Limiting
|
|
253
|
+
RATE_LIMIT_ENABLED=true
|
|
254
|
+
LOGIN_RATE_LIMIT=5 # attempts per window
|
|
255
|
+
LOGIN_RATE_WINDOW=300 # seconds (5 minutes)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Programmatic Configuration
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
from fastauth import Settings
|
|
262
|
+
|
|
263
|
+
settings = Settings(
|
|
264
|
+
jwt_secret_key="your-secret-key",
|
|
265
|
+
access_token_expire_minutes=60,
|
|
266
|
+
require_email_verification=True
|
|
267
|
+
)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Usage Examples
|
|
271
|
+
|
|
272
|
+
### Protecting Routes
|
|
273
|
+
|
|
274
|
+
```python
|
|
275
|
+
from fastapi import Depends
|
|
276
|
+
from fastauth.api.dependencies import get_current_user
|
|
277
|
+
from fastauth.adapters.sqlalchemy.models import User
|
|
278
|
+
|
|
279
|
+
@app.get("/profile")
|
|
280
|
+
def get_profile(current_user: User = Depends(get_current_user)):
|
|
281
|
+
return {
|
|
282
|
+
"email": current_user.email,
|
|
283
|
+
"verified": current_user.is_verified,
|
|
284
|
+
"created_at": current_user.created_at
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Custom User Model
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from sqlmodel import Field
|
|
292
|
+
from fastauth.adapters.sqlalchemy.models import User as BaseUser
|
|
293
|
+
|
|
294
|
+
class User(BaseUser, table=True):
|
|
295
|
+
__tablename__ = "users"
|
|
296
|
+
|
|
297
|
+
# Add custom fields
|
|
298
|
+
first_name: str | None = None
|
|
299
|
+
last_name: str | None = None
|
|
300
|
+
company: str | None = None
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Role-Based Access Control (RBAC)
|
|
304
|
+
|
|
305
|
+
Protect routes with roles and permissions for fine-grained authorization:
|
|
306
|
+
|
|
307
|
+
#### Creating Roles and Permissions
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
from fastauth import create_role, create_permission, assign_permission_to_role, assign_role
|
|
311
|
+
from fastauth.adapters.sqlalchemy.roles import SQLAlchemyRoleAdapter
|
|
312
|
+
|
|
313
|
+
# Create roles
|
|
314
|
+
admin_role = create_role(roles=role_adapter, name="admin", description="Administrator")
|
|
315
|
+
moderator_role = create_role(roles=role_adapter, name="moderator", description="Moderator")
|
|
316
|
+
user_role = create_role(roles=role_adapter, name="user", description="Regular user")
|
|
317
|
+
|
|
318
|
+
# Create permissions
|
|
319
|
+
read_users = create_permission(roles=role_adapter, name="read:users")
|
|
320
|
+
write_users = create_permission(roles=role_adapter, name="write:users")
|
|
321
|
+
delete_users = create_permission(roles=role_adapter, name="delete:users")
|
|
322
|
+
|
|
323
|
+
# Assign permissions to roles
|
|
324
|
+
assign_permission_to_role(roles=role_adapter, role_name="admin", permission_name="read:users")
|
|
325
|
+
assign_permission_to_role(roles=role_adapter, role_name="admin", permission_name="write:users")
|
|
326
|
+
assign_permission_to_role(roles=role_adapter, role_name="admin", permission_name="delete:users")
|
|
327
|
+
|
|
328
|
+
# Assign role to user
|
|
329
|
+
assign_role(roles=role_adapter, user_id=user.id, role_name="admin")
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### Protecting Routes by Role
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
from fastapi import Depends
|
|
336
|
+
from fastauth.api.dependencies import require_role
|
|
337
|
+
|
|
338
|
+
@app.get("/admin/dashboard", dependencies=[Depends(require_role("admin"))])
|
|
339
|
+
def admin_dashboard():
|
|
340
|
+
return {"message": "Admin access granted"}
|
|
341
|
+
|
|
342
|
+
@app.get("/moderator/panel", dependencies=[Depends(require_role("moderator"))])
|
|
343
|
+
def moderator_panel():
|
|
344
|
+
return {"message": "Moderator access granted"}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### Protecting Routes by Permission
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
from fastapi import Depends
|
|
351
|
+
from fastauth.api.dependencies import require_permission
|
|
352
|
+
|
|
353
|
+
@app.get("/users", dependencies=[Depends(require_permission("read:users"))])
|
|
354
|
+
def list_users():
|
|
355
|
+
return {"users": [...]}
|
|
356
|
+
|
|
357
|
+
@app.delete("/users/{id}", dependencies=[Depends(require_permission("delete:users"))])
|
|
358
|
+
def delete_user(id: str):
|
|
359
|
+
return {"message": "User deleted"}
|
|
360
|
+
|
|
361
|
+
@app.post("/users", dependencies=[Depends(require_permission("write:users"))])
|
|
362
|
+
def create_user(user_data: dict):
|
|
363
|
+
return {"message": "User created"}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Checking Permissions Programmatically
|
|
367
|
+
|
|
368
|
+
```python
|
|
369
|
+
from fastauth import check_permission
|
|
370
|
+
|
|
371
|
+
# Check if user has specific permission
|
|
372
|
+
has_access = check_permission(
|
|
373
|
+
roles=role_adapter,
|
|
374
|
+
user_id=user.id,
|
|
375
|
+
permission_name="delete:users"
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
if has_access:
|
|
379
|
+
# Perform action
|
|
380
|
+
pass
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Session Management
|
|
384
|
+
|
|
385
|
+
Track and manage user sessions across multiple devices for enhanced security:
|
|
386
|
+
|
|
387
|
+
#### Viewing Active Sessions
|
|
388
|
+
|
|
389
|
+
Sessions are automatically created when users log in or register. Users can view all their active sessions:
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
from fastapi import Depends
|
|
393
|
+
from fastauth.api.dependencies import get_current_user
|
|
394
|
+
from fastauth.adapters.sqlalchemy.models import User
|
|
395
|
+
|
|
396
|
+
@app.get("/my-sessions")
|
|
397
|
+
def get_my_sessions(current_user: User = Depends(get_current_user)):
|
|
398
|
+
return {"user_id": current_user.id}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### Session Information
|
|
402
|
+
|
|
403
|
+
Each session contains:
|
|
404
|
+
- **Device** - Device name or identifier
|
|
405
|
+
- **IP Address** - Client IP address
|
|
406
|
+
- **User Agent** - Browser/client information
|
|
407
|
+
- **Last Active** - Last activity timestamp
|
|
408
|
+
- **Created At** - Session creation time
|
|
409
|
+
|
|
410
|
+
#### Revoking Sessions
|
|
411
|
+
|
|
412
|
+
Users can revoke individual sessions (e.g., logout from a specific device):
|
|
413
|
+
|
|
414
|
+
```bash
|
|
415
|
+
curl -X DELETE "http://localhost:8000/sessions/{session_id}" \
|
|
416
|
+
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Or logout from all devices at once:
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
curl -X DELETE "http://localhost:8000/sessions/all" \
|
|
423
|
+
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
#### Programmatic Session Management
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
from fastauth import create_session, get_user_sessions, delete_session
|
|
430
|
+
from fastauth.adapters.sqlalchemy.sessions import SQLAlchemySessionAdapter
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
session = create_session(
|
|
434
|
+
sessions=session_adapter,
|
|
435
|
+
users=user_adapter,
|
|
436
|
+
user_id=user.id,
|
|
437
|
+
device="iPhone 13",
|
|
438
|
+
ip_address="192.168.1.1",
|
|
439
|
+
user_agent="Mozilla/5.0"
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
user_sessions = get_user_sessions(
|
|
443
|
+
sessions=session_adapter,
|
|
444
|
+
user_id=user.id
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
delete_session(
|
|
448
|
+
sessions=session_adapter,
|
|
449
|
+
session_id=session.id,
|
|
450
|
+
user_id=user.id
|
|
451
|
+
)
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### Session Cleanup
|
|
455
|
+
|
|
456
|
+
Automatically cleanup inactive sessions:
|
|
457
|
+
|
|
458
|
+
```python
|
|
459
|
+
from fastauth import cleanup_inactive_sessions
|
|
460
|
+
|
|
461
|
+
cleanup_inactive_sessions(
|
|
462
|
+
sessions=session_adapter,
|
|
463
|
+
inactive_days=30
|
|
464
|
+
)
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
This can be scheduled as a background task:
|
|
468
|
+
|
|
469
|
+
```python
|
|
470
|
+
from fastapi import FastAPI
|
|
471
|
+
from apscheduler.schedulers.background import BackgroundScheduler
|
|
472
|
+
|
|
473
|
+
app = FastAPI()
|
|
474
|
+
|
|
475
|
+
def cleanup_old_sessions():
|
|
476
|
+
cleanup_inactive_sessions(sessions=session_adapter, inactive_days=30)
|
|
477
|
+
|
|
478
|
+
scheduler = BackgroundScheduler()
|
|
479
|
+
scheduler.add_job(cleanup_old_sessions, 'interval', days=1)
|
|
480
|
+
scheduler.start()
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Using Different Databases
|
|
484
|
+
|
|
485
|
+
FastAuth works with any database through adapters:
|
|
486
|
+
|
|
487
|
+
**SQLAlchemy (built-in):**
|
|
488
|
+
```python
|
|
489
|
+
from fastauth.adapters.sqlalchemy import SQLAlchemyUserAdapter
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**MongoDB (install fastauth[mongodb]):**
|
|
493
|
+
```python
|
|
494
|
+
from fastauth.adapters.mongodb import MongoDBUserAdapter
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Custom adapter:**
|
|
498
|
+
```python
|
|
499
|
+
from fastauth.adapters.base import UserAdapter
|
|
500
|
+
|
|
501
|
+
class MyCustomAdapter(UserAdapter):
|
|
502
|
+
def create_user(self, email: str, hashed_password: str):
|
|
503
|
+
# Your implementation
|
|
504
|
+
pass
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
## Advanced Features
|
|
508
|
+
|
|
509
|
+
### Email Verification
|
|
510
|
+
|
|
511
|
+
Enable email verification for new signups:
|
|
512
|
+
|
|
513
|
+
```python
|
|
514
|
+
# .env
|
|
515
|
+
REQUIRE_EMAIL_VERIFICATION=true
|
|
516
|
+
EMAIL_PROVIDER=smtp # or sendgrid, resend, ses
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Users must verify their email before logging in.
|
|
520
|
+
|
|
521
|
+
### Password Reset
|
|
522
|
+
|
|
523
|
+
Users can reset their password via email:
|
|
524
|
+
|
|
525
|
+
1. Request reset: `POST /auth/password-reset/request`
|
|
526
|
+
2. Receive email with reset link
|
|
527
|
+
3. Submit new password: `POST /auth/password-reset/confirm`
|
|
528
|
+
|
|
529
|
+
### Rate Limiting
|
|
530
|
+
|
|
531
|
+
Built-in rate limiting protects against brute force attacks:
|
|
532
|
+
|
|
533
|
+
- Login attempts: 5 per 5 minutes (configurable)
|
|
534
|
+
- Registration: 3 per 10 minutes
|
|
535
|
+
- Email verification: 3 per 10 minutes
|
|
536
|
+
|
|
537
|
+
### Refresh Token Rotation
|
|
538
|
+
|
|
539
|
+
Refresh tokens are automatically rotated on use for enhanced security:
|
|
540
|
+
|
|
541
|
+
```python
|
|
542
|
+
# Old refresh token is invalidated
|
|
543
|
+
# New refresh token is issued
|
|
544
|
+
response = await refresh_tokens(refresh_token)
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
## Examples
|
|
548
|
+
|
|
549
|
+
Check out the [examples](./examples) directory for complete applications:
|
|
550
|
+
|
|
551
|
+
- **[Basic Example](./examples/basic)** - Simple FastAPI app with FastAuth
|
|
552
|
+
|
|
553
|
+
## Development
|
|
554
|
+
|
|
555
|
+
### Setup Development Environment
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
# Clone repository
|
|
559
|
+
git clone https://github.com/sreekarnv/fastauth.git
|
|
560
|
+
cd fastauth
|
|
561
|
+
|
|
562
|
+
# Install dependencies
|
|
563
|
+
poetry install
|
|
564
|
+
|
|
565
|
+
# Install pre-commit hooks
|
|
566
|
+
poetry run pre-commit install
|
|
567
|
+
|
|
568
|
+
# Run tests
|
|
569
|
+
poetry run pytest
|
|
570
|
+
|
|
571
|
+
# Run linting
|
|
572
|
+
poetry run black .
|
|
573
|
+
poetry run ruff check .
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
### Running Tests
|
|
577
|
+
|
|
578
|
+
```bash
|
|
579
|
+
# All tests
|
|
580
|
+
poetry run pytest
|
|
581
|
+
|
|
582
|
+
# With coverage
|
|
583
|
+
poetry run pytest --cov=fastauth --cov-report=html
|
|
584
|
+
|
|
585
|
+
# Specific test file
|
|
586
|
+
poetry run pytest tests/core/test_users.py
|
|
587
|
+
|
|
588
|
+
# Verbose output
|
|
589
|
+
poetry run pytest -v
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Project Structure
|
|
593
|
+
|
|
594
|
+
```
|
|
595
|
+
fastauth/
|
|
596
|
+
├── fastauth/ # Main package
|
|
597
|
+
│ ├── core/ # Business logic (database-agnostic)
|
|
598
|
+
│ ├── adapters/ # Database adapters
|
|
599
|
+
│ │ ├── base/ # Abstract interfaces
|
|
600
|
+
│ │ └── sqlalchemy/ # SQLAlchemy implementation
|
|
601
|
+
│ ├── api/ # FastAPI routes and dependencies
|
|
602
|
+
│ ├── security/ # JWT, hashing, rate limiting
|
|
603
|
+
│ ├── email/ # Email providers
|
|
604
|
+
│ └── settings.py # Configuration
|
|
605
|
+
├── tests/ # Test suite
|
|
606
|
+
├── examples/ # Example applications
|
|
607
|
+
└── docs/ # Documentation
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
## Security
|
|
611
|
+
|
|
612
|
+
FastAuth follows security best practices:
|
|
613
|
+
|
|
614
|
+
- **Password Hashing** - Argon2 (OWASP recommended)
|
|
615
|
+
- **JWT Tokens** - Secure token generation and validation
|
|
616
|
+
- **Rate Limiting** - Protection against brute force
|
|
617
|
+
- **Token Expiration** - Configurable token lifetimes
|
|
618
|
+
- **Refresh Token Rotation** - Enhanced security
|
|
619
|
+
- **SQL Injection Protection** - Parameterized queries
|
|
620
|
+
- **XSS Protection** - Proper input validation
|
|
621
|
+
|
|
622
|
+
### Security Recommendations
|
|
623
|
+
|
|
624
|
+
For production deployments:
|
|
625
|
+
|
|
626
|
+
1. Use strong `JWT_SECRET_KEY` (min 32 characters)
|
|
627
|
+
2. Enable HTTPS/TLS
|
|
628
|
+
3. Enable email verification (`REQUIRE_EMAIL_VERIFICATION=true`)
|
|
629
|
+
4. Use secure email provider (not console)
|
|
630
|
+
5. Set appropriate token expiration times
|
|
631
|
+
6. Enable rate limiting
|
|
632
|
+
7. Monitor authentication logs
|
|
633
|
+
8. Keep dependencies updated
|
|
634
|
+
|
|
635
|
+
## Troubleshooting
|
|
636
|
+
|
|
637
|
+
### Common Issues
|
|
638
|
+
|
|
639
|
+
**Issue: "Invalid JWT secret key"**
|
|
640
|
+
```bash
|
|
641
|
+
# Solution: Set a strong secret key
|
|
642
|
+
JWT_SECRET_KEY=your-very-long-secret-key-min-32-characters
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
**Issue: "Email not being sent"**
|
|
646
|
+
```bash
|
|
647
|
+
# Solution: Check email provider configuration
|
|
648
|
+
EMAIL_PROVIDER=console # For development
|
|
649
|
+
# Or configure SMTP settings for production
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Issue: "Database connection failed"**
|
|
653
|
+
```bash
|
|
654
|
+
# Solution: Verify database URL format
|
|
655
|
+
# SQLite: sqlite:///./app.db
|
|
656
|
+
# PostgreSQL: postgresql://user:pass@localhost/dbname
|
|
657
|
+
# MySQL: mysql://user:pass@localhost/dbname
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Issue: "Rate limit exceeded"**
|
|
661
|
+
```bash
|
|
662
|
+
# Solution: Adjust rate limit settings or wait for window to expire
|
|
663
|
+
LOGIN_RATE_LIMIT=10 # Increase limit
|
|
664
|
+
LOGIN_RATE_WINDOW=300 # 5 minutes
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Getting Help
|
|
668
|
+
|
|
669
|
+
- **Documentation**: [docs/](./docs)
|
|
670
|
+
- **Issues**: [GitHub Issues](https://github.com/sreekarnv/fastauth/issues)
|
|
671
|
+
- **Discussions**: [GitHub Discussions](https://github.com/sreekarnv/fastauth/discussions)
|
|
672
|
+
|
|
673
|
+
## License
|
|
674
|
+
|
|
675
|
+
This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
|
|
676
|
+
|
|
677
|
+
## Acknowledgments
|
|
678
|
+
|
|
679
|
+
- Built with [FastAPI](https://fastapi.tiangolo.com/)
|
|
680
|
+
- Database ORM: [SQLModel](https://sqlmodel.tiangolo.com/)
|
|
681
|
+
- Password hashing: [Argon2](https://github.com/hynek/argon2-cffi)
|
|
682
|
+
- JWT tokens: [python-jose](https://github.com/mpdavis/python-jose)
|
|
683
|
+
|
|
684
|
+
## Support
|
|
685
|
+
|
|
686
|
+
If you find FastAuth useful, please consider:
|
|
687
|
+
|
|
688
|
+
- Starring the repository ⭐
|
|
689
|
+
- Reporting bugs and suggesting features
|
|
690
|
+
- Contributing code or documentation
|
|
691
|
+
- Sharing with others
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
695
|
+
Made with ❤️ by [Sreekar Nutulapati](https://github.com/sreekarnv)
|
|
696
|
+
|