fastapi-jwt-authkit 0.1.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.
- fastapi_jwt_authkit-0.1.0/.gitignore +68 -0
- fastapi_jwt_authkit-0.1.0/.pypirc +13 -0
- fastapi_jwt_authkit-0.1.0/LICENSE +21 -0
- fastapi_jwt_authkit-0.1.0/PKG-INFO +366 -0
- fastapi_jwt_authkit-0.1.0/README.md +303 -0
- fastapi_jwt_authkit-0.1.0/examples/__init__.py +1 -0
- fastapi_jwt_authkit-0.1.0/examples/async_app.py +110 -0
- fastapi_jwt_authkit-0.1.0/examples/models.py +22 -0
- fastapi_jwt_authkit-0.1.0/examples/sync_app.py +104 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/LICENSE +21 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/__init__.py +5 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/authenticator.py +47 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/ext/sqlalchemy/__init__.py +6 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/ext/sqlalchemy/sa_async.py +44 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/ext/sqlalchemy/sa_sync.py +60 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/extractors.py +28 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/fastapi/__init__.py +3 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/fastapi/models.py +0 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/fastapi/routers.py +204 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/fastapi/schema.py +13 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/hashing.py +12 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/protocols.py +27 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/service.py +145 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/settings.py +26 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/src/authkit/tokens.py +45 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit/uv.lock +695 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/LICENSE +21 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/__init__.pyi +3 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/authenticator.pyi +11 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/ext/sqlalchmey/__init__.pyi +4 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/ext/sqlalchmey/sa_async.pyi +13 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/ext/sqlalchmey/sa_sync.pyi +13 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/extractors.pyi +5 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/fastapi/__init__.pyi +2 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/fastapi/routers.pyi +6 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/hashing.pyi +2 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/protocols.pyi +27 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/py.typed +0 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/service.pyi +18 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/settings.pyi +26 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/src/authkit/tokens.pyi +6 -0
- fastapi_jwt_authkit-0.1.0/packages/authkit_types/uv.lock +136 -0
- fastapi_jwt_authkit-0.1.0/pyproject.toml +75 -0
- fastapi_jwt_authkit-0.1.0/tests/__init__.py +1 -0
- fastapi_jwt_authkit-0.1.0/tests/conftest.py +21 -0
- fastapi_jwt_authkit-0.1.0/tests/test_extractors.py +68 -0
- fastapi_jwt_authkit-0.1.0/tests/test_hashing.py +32 -0
- fastapi_jwt_authkit-0.1.0/tests/test_routers_async.py +154 -0
- fastapi_jwt_authkit-0.1.0/tests/test_routers_sync.py +146 -0
- fastapi_jwt_authkit-0.1.0/tests/test_service_async.py +123 -0
- fastapi_jwt_authkit-0.1.0/tests/test_service_sync.py +140 -0
- fastapi_jwt_authkit-0.1.0/tests/test_settings.py +24 -0
- fastapi_jwt_authkit-0.1.0/tests/test_tokens.py +85 -0
- fastapi_jwt_authkit-0.1.0/uv.lock +1642 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
env/
|
|
28
|
+
|
|
29
|
+
# uv
|
|
30
|
+
.uv/
|
|
31
|
+
uv.lock.bak
|
|
32
|
+
|
|
33
|
+
# Testing / coverage
|
|
34
|
+
.pytest_cache/
|
|
35
|
+
.coverage
|
|
36
|
+
htmlcov/
|
|
37
|
+
.tox/
|
|
38
|
+
.nox/
|
|
39
|
+
coverage.xml
|
|
40
|
+
*.cover
|
|
41
|
+
.hypothesis/
|
|
42
|
+
|
|
43
|
+
# IDE
|
|
44
|
+
.idea/
|
|
45
|
+
.vscode/
|
|
46
|
+
*.swp
|
|
47
|
+
*.swo
|
|
48
|
+
*~
|
|
49
|
+
|
|
50
|
+
# OS
|
|
51
|
+
.DS_Store
|
|
52
|
+
Thumbs.db
|
|
53
|
+
|
|
54
|
+
# Project / examples runtime
|
|
55
|
+
*.db
|
|
56
|
+
*.sqlite
|
|
57
|
+
*.sqlite3
|
|
58
|
+
examples_async.db
|
|
59
|
+
examples_sync.db
|
|
60
|
+
|
|
61
|
+
# Secrets / env
|
|
62
|
+
.env
|
|
63
|
+
.env.local
|
|
64
|
+
*.pem
|
|
65
|
+
|
|
66
|
+
# Build artifacts
|
|
67
|
+
*.tar.gz
|
|
68
|
+
*.whl
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[distutils]
|
|
2
|
+
index-servers =
|
|
3
|
+
pypi
|
|
4
|
+
testpypi
|
|
5
|
+
|
|
6
|
+
[pypi]
|
|
7
|
+
username = __token__
|
|
8
|
+
password = pypi-AgEIcHlwaS5vcmcCJGNiNzBkYjE1LTU3OWQtNGVkYS1iODlmLWQwOTA1NGZkZjE5MwACKlszLCIyNGVkZWIxOS03MTBlLTQ2NTEtYjNjOC0xYTJhMGJhZTZlNjAiXQAABiBFbLNcYNuZGCB7laMVGsue9g0vFwQ-npPs0eaYVKDDPw
|
|
9
|
+
|
|
10
|
+
[testpypi]
|
|
11
|
+
repository = https://test.pypi.org/legacy/
|
|
12
|
+
username = __token__
|
|
13
|
+
password =pypi-AgEIcHlwaS5vcmcCJGNiNzBkYjE1LTU3OWQtNGVkYS1iODlmLWQwOTA1NGZkZjE5MwACKlszLCIyNGVkZWIxOS03MTBlLTQ2NTEtYjNjOC0xYTJhMGJhZTZlNjAiXQAABiBFbLNcYNuZGCB7laMVGsue9g0vFwQ-npPs0eaYVKDDPw
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fast Auth Kit contributors
|
|
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,366 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-jwt-authkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: FastAPI authentication library with JWT access/refresh tokens, sync & async SQLAlchemy support, built-in auth routes (register/login/refresh/me), secure password hashing, and cookie/header token support.
|
|
5
|
+
Project-URL: Homepage, https://github.com/azimhossaintuhin/fastapi-jwt-authkit
|
|
6
|
+
Project-URL: Repository, https://github.com/azimhossaintuhin/fastapi-jwt-authkit
|
|
7
|
+
Project-URL: Issues, https://github.com/azimhossaintuhin/fastapi-jwt-authkit/issues
|
|
8
|
+
Author: Azim Hossain Tuhin
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 Fast Auth Kit contributors
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: access-token,async,auth,authentication,bcrypt,fastapi,fastapi-auth,fastapi-jwt,json-web-token,jwt,login,password-hashing,refresh-token,register,security,sqlalchemy,sync
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Framework :: FastAPI
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python
|
|
38
|
+
Classifier: Programming Language :: Python :: 3
|
|
39
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
44
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
45
|
+
Classifier: Topic :: Security
|
|
46
|
+
Requires-Python: >=3.10
|
|
47
|
+
Requires-Dist: bcrypt<5.0.0,>=4.0.0
|
|
48
|
+
Requires-Dist: fastapi>=0.110
|
|
49
|
+
Requires-Dist: hatch>=1.16.3
|
|
50
|
+
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
51
|
+
Requires-Dist: pydantic[email]>=2.0.0
|
|
52
|
+
Requires-Dist: python-jose[cryptography]>=3.3.0
|
|
53
|
+
Requires-Dist: sqlalchemy>=2.0.0
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: aiosqlite>=0.20.0; extra == 'dev'
|
|
56
|
+
Requires-Dist: build>=1.4.0; extra == 'dev'
|
|
57
|
+
Requires-Dist: httpx>=0.28.0; extra == 'dev'
|
|
58
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
59
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
60
|
+
Requires-Dist: twine>=6.2.0; extra == 'dev'
|
|
61
|
+
Requires-Dist: uvicorn>=0.40.0; extra == 'dev'
|
|
62
|
+
Description-Content-Type: text/markdown
|
|
63
|
+
|
|
64
|
+
# FastAPI Auth Kit
|
|
65
|
+
|
|
66
|
+
**FastAPI authentication library with JWT access/refresh tokens, sync & async SQLAlchemy support, built-in auth routes (register/login/refresh/me), secure password hashing, and cookie/header token support.**
|
|
67
|
+
|
|
68
|
+
Complete authentication toolkit for FastAPI with JWT, designed for both sync and async SQLAlchemy backends. Provides batteries-included auth services, FastAPI routers, token utilities, and a clean protocol-driven repository interface.
|
|
69
|
+
|
|
70
|
+
## Highlights
|
|
71
|
+
|
|
72
|
+
- JWT access + refresh tokens with rotation
|
|
73
|
+
- Sync and async SQLAlchemy adapters
|
|
74
|
+
- Drop-in FastAPI routers for register, login, refresh, logout, and `/me`
|
|
75
|
+
- Cookie and Authorization header support
|
|
76
|
+
- Strong typing and protocol-based extensibility
|
|
77
|
+
- Works with your own User model
|
|
78
|
+
|
|
79
|
+
## Package Layout
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
packages/authkit/src/authkit/
|
|
83
|
+
fastapi/ # FastAPI router builders + schemas
|
|
84
|
+
ext/ # SQLAlchemy protocol adapters (sync/async)
|
|
85
|
+
authenticator.py
|
|
86
|
+
service.py
|
|
87
|
+
tokens.py
|
|
88
|
+
hashing.py
|
|
89
|
+
settings.py
|
|
90
|
+
extractors.py
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Installation
|
|
94
|
+
|
|
95
|
+
### From this repo
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv sync
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### In your project
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install fastapi-jwt-authkit
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
> The PyPI package name is `fastapi-jwt-authkit`, the import name is `authkit`.
|
|
108
|
+
|
|
109
|
+
### Typing support
|
|
110
|
+
|
|
111
|
+
Type information (`.pyi` + `py.typed`) is bundled with the package for IDEs and
|
|
112
|
+
static type checkers.
|
|
113
|
+
|
|
114
|
+
## Quickstart (Async)
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from fastapi import FastAPI
|
|
118
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
|
|
119
|
+
|
|
120
|
+
from authkit import AuthSettings
|
|
121
|
+
from authkit.fastapi.routers import build_auth_router_async
|
|
122
|
+
|
|
123
|
+
from your_app.models import Base, User
|
|
124
|
+
|
|
125
|
+
DATABASE_URL = "sqlite+aiosqlite:///./app.db"
|
|
126
|
+
engine = create_async_engine(DATABASE_URL, echo=False)
|
|
127
|
+
SessionLocal = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
128
|
+
|
|
129
|
+
async def get_session():
|
|
130
|
+
async with SessionLocal() as session:
|
|
131
|
+
try:
|
|
132
|
+
yield session
|
|
133
|
+
await session.commit()
|
|
134
|
+
except Exception:
|
|
135
|
+
await session.rollback()
|
|
136
|
+
raise
|
|
137
|
+
|
|
138
|
+
settings = AuthSettings(secret_key="change-me", cookie_secure=False)
|
|
139
|
+
|
|
140
|
+
app = FastAPI()
|
|
141
|
+
auth_router = build_auth_router_async(
|
|
142
|
+
settings=settings,
|
|
143
|
+
get_session=get_session,
|
|
144
|
+
user_model=User,
|
|
145
|
+
)
|
|
146
|
+
app.include_router(auth_router, prefix="/auth", tags=["auth"])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Quickstart (Sync)
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from fastapi import FastAPI
|
|
153
|
+
from sqlalchemy import create_engine
|
|
154
|
+
from sqlalchemy.orm import sessionmaker
|
|
155
|
+
|
|
156
|
+
from authkit import AuthSettings
|
|
157
|
+
from authkit.fastapi.routers import build_auth_router_sync
|
|
158
|
+
|
|
159
|
+
from your_app.models import Base, User
|
|
160
|
+
|
|
161
|
+
DATABASE_URL = "sqlite:///./app.db"
|
|
162
|
+
engine = create_engine(DATABASE_URL, echo=False)
|
|
163
|
+
SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
|
164
|
+
|
|
165
|
+
def get_session():
|
|
166
|
+
session = SessionLocal()
|
|
167
|
+
try:
|
|
168
|
+
yield session
|
|
169
|
+
session.commit()
|
|
170
|
+
except Exception:
|
|
171
|
+
session.rollback()
|
|
172
|
+
raise
|
|
173
|
+
finally:
|
|
174
|
+
session.close()
|
|
175
|
+
|
|
176
|
+
settings = AuthSettings(secret_key="change-me", cookie_secure=False)
|
|
177
|
+
|
|
178
|
+
app = FastAPI()
|
|
179
|
+
auth_router = build_auth_router_sync(
|
|
180
|
+
settings=settings,
|
|
181
|
+
get_session=get_session,
|
|
182
|
+
user_models=User,
|
|
183
|
+
)
|
|
184
|
+
app.include_router(auth_router, prefix="/auth", tags=["auth"])
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Core Concepts
|
|
188
|
+
|
|
189
|
+
### AuthSettings
|
|
190
|
+
|
|
191
|
+
All auth behavior is configured via `AuthSettings`:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
AuthSettings(
|
|
195
|
+
secret_key="your-secret",
|
|
196
|
+
algorithm="HS256",
|
|
197
|
+
access_minutes=15,
|
|
198
|
+
refresh_days=7,
|
|
199
|
+
accept_header=True,
|
|
200
|
+
accept_cookie=True,
|
|
201
|
+
set_cookie_on_login=True,
|
|
202
|
+
cookie_secure=True,
|
|
203
|
+
cookie_samesite="lax",
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### AuthService / AsyncAuthService
|
|
208
|
+
|
|
209
|
+
Business logic for creating users, authenticating, and issuing tokens. Uses a
|
|
210
|
+
repository protocol so you can plug in your own persistence layer.
|
|
211
|
+
|
|
212
|
+
### SQLAlchemy Adapters
|
|
213
|
+
|
|
214
|
+
- `SQLAlchemySyncUserProtocol`
|
|
215
|
+
- `SQLAlchemyAsyncUserProtocol`
|
|
216
|
+
|
|
217
|
+
These adapters expect a SQLAlchemy model with the following fields:
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
class User(Base):
|
|
221
|
+
id: int
|
|
222
|
+
email: str
|
|
223
|
+
username: str
|
|
224
|
+
password_hash: str
|
|
225
|
+
is_active: bool
|
|
226
|
+
is_staff: bool
|
|
227
|
+
is_superuser: bool
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## API Endpoints
|
|
231
|
+
|
|
232
|
+
When you include the auth router with prefix `/auth`, the following endpoints
|
|
233
|
+
are available:
|
|
234
|
+
|
|
235
|
+
| Method | Path | Description |
|
|
236
|
+
|--------|----------------|-----------------------------|
|
|
237
|
+
| POST | /auth/register | Create a new user |
|
|
238
|
+
| POST | /auth/login | Authenticate + issue tokens |
|
|
239
|
+
| POST | /auth/refresh | Refresh access token |
|
|
240
|
+
| POST | /auth/logout | Clear auth cookies |
|
|
241
|
+
| GET | /auth/me | Get current user |
|
|
242
|
+
|
|
243
|
+
### Request/Response Schemas
|
|
244
|
+
|
|
245
|
+
**Register**
|
|
246
|
+
```json
|
|
247
|
+
{ "email": "user@example.com", "username": "user", "password": "secret" }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Login**
|
|
251
|
+
```json
|
|
252
|
+
{ "username_or_email": "user", "password": "secret" }
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Token Response**
|
|
256
|
+
```json
|
|
257
|
+
{ "access_token": "jwt", "refresh_token": "jwt" }
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Cookies and Headers
|
|
261
|
+
|
|
262
|
+
`AuthSettings` controls where tokens are accepted and how they are stored:
|
|
263
|
+
|
|
264
|
+
- `accept_header`: allow `Authorization: Bearer <token>`
|
|
265
|
+
- `accept_cookie`: allow cookies
|
|
266
|
+
- `set_cookie_on_login`: set cookies on successful login
|
|
267
|
+
|
|
268
|
+
Cookie names and TTL are customizable with:
|
|
269
|
+
`cookie_name_access`, `cookie_name_refresh`, `cookie_max_age_access`,
|
|
270
|
+
`cookie_max_age_refresh`.
|
|
271
|
+
|
|
272
|
+
## Security Considerations
|
|
273
|
+
|
|
274
|
+
- Use a strong `secret_key` and rotate regularly.
|
|
275
|
+
- Set `cookie_secure=True` in production (HTTPS only).
|
|
276
|
+
- Consider `cookie_samesite="strict"` for web apps with tight CSRF control.
|
|
277
|
+
- Short access token TTLs with longer refresh TTLs are recommended.
|
|
278
|
+
|
|
279
|
+
## Production Checklist
|
|
280
|
+
|
|
281
|
+
- [x] `secret_key` stored in a secure secret manager
|
|
282
|
+
- [x] HTTPS enforced
|
|
283
|
+
- [x] `cookie_secure=True`, `cookie_samesite` set per app policy
|
|
284
|
+
- [x] Rotate JWT secret or use KMS-backed signing
|
|
285
|
+
- [x] Enable logging around login and refresh flows
|
|
286
|
+
- [x] Implement account lockout or rate limiting at the API gateway
|
|
287
|
+
- [x] Configure backups for the user datastore
|
|
288
|
+
|
|
289
|
+
## Compatibility
|
|
290
|
+
|
|
291
|
+
- Python: 3.10+
|
|
292
|
+
- FastAPI: 0.110+
|
|
293
|
+
- SQLAlchemy: 2.x
|
|
294
|
+
|
|
295
|
+
## Observability
|
|
296
|
+
|
|
297
|
+
This library raises standard `HTTPException` errors. For production:
|
|
298
|
+
|
|
299
|
+
- Add structured logging around auth endpoints
|
|
300
|
+
- Add tracing/metrics at the FastAPI middleware layer
|
|
301
|
+
|
|
302
|
+
## Versioning
|
|
303
|
+
|
|
304
|
+
Follows semantic versioning: `MAJOR.MINOR.PATCH`.
|
|
305
|
+
|
|
306
|
+
## Testing
|
|
307
|
+
|
|
308
|
+
Run the full test suite:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
uv run pytest tests/ -v
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
All tests are under `tests/` and cover tokens, hashing, services, and router
|
|
315
|
+
integration (sync + async).
|
|
316
|
+
|
|
317
|
+
## Examples
|
|
318
|
+
|
|
319
|
+
Working example apps are provided:
|
|
320
|
+
|
|
321
|
+
- `examples/async_app.py`
|
|
322
|
+
- `examples/sync_app.py`
|
|
323
|
+
|
|
324
|
+
Run:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
uv run python -m examples.async_app
|
|
328
|
+
uv run python -m examples.sync_app
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Extending the Repo Layer
|
|
332
|
+
|
|
333
|
+
Implement the repo protocol if you use a different persistence layer:
|
|
334
|
+
|
|
335
|
+
```python
|
|
336
|
+
class MyRepo:
|
|
337
|
+
def get_by_id(self, user_id: int): ...
|
|
338
|
+
def get_by_email_or_username(self, value: str): ...
|
|
339
|
+
def create_user(self, *, email: str, username: str, password: str,
|
|
340
|
+
is_staff: bool, is_active: bool, is_superuser: bool): ...
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Async version must expose the same methods as `async def`.
|
|
344
|
+
|
|
345
|
+
## Typing Notes
|
|
346
|
+
|
|
347
|
+
Type information is bundled with the package (`.pyi` + `py.typed`). If your IDE
|
|
348
|
+
or type checker does not pick it up, ensure:
|
|
349
|
+
|
|
350
|
+
- Your tooling supports PEP 561
|
|
351
|
+
|
|
352
|
+
## Troubleshooting
|
|
353
|
+
|
|
354
|
+
**Bcrypt errors on Windows**
|
|
355
|
+
|
|
356
|
+
If you see bcrypt backend errors during hashing, ensure you have `bcrypt<5`
|
|
357
|
+
installed. This repo pins it accordingly in `pyproject.toml`.
|
|
358
|
+
|
|
359
|
+
**SQLite in-memory tests**
|
|
360
|
+
|
|
361
|
+
In-memory SQLite needs a `StaticPool` so all sessions share the same DB
|
|
362
|
+
connection. The tests already handle this.
|
|
363
|
+
|
|
364
|
+
## License
|
|
365
|
+
|
|
366
|
+
MIT (see `LICENSE`).
|