softauth 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.
Files changed (55) hide show
  1. softauth-0.1.0/LICENSE +21 -0
  2. softauth-0.1.0/PKG-INFO +307 -0
  3. softauth-0.1.0/README.md +252 -0
  4. softauth-0.1.0/pyproject.toml +92 -0
  5. softauth-0.1.0/setup.cfg +4 -0
  6. softauth-0.1.0/softauth/__init__.py +73 -0
  7. softauth-0.1.0/softauth/cli/__init__.py +3 -0
  8. softauth-0.1.0/softauth/cli/commands.py +233 -0
  9. softauth-0.1.0/softauth/core/__init__.py +35 -0
  10. softauth-0.1.0/softauth/core/auth.py +183 -0
  11. softauth-0.1.0/softauth/core/config.py +70 -0
  12. softauth-0.1.0/softauth/core/exceptions.py +67 -0
  13. softauth-0.1.0/softauth/database/__init__.py +5 -0
  14. softauth-0.1.0/softauth/database/models.py +58 -0
  15. softauth-0.1.0/softauth/database/repository.py +46 -0
  16. softauth-0.1.0/softauth/database/session.py +66 -0
  17. softauth-0.1.0/softauth/django/__init__.py +3 -0
  18. softauth-0.1.0/softauth/django/adapter.py +77 -0
  19. softauth-0.1.0/softauth/django/decorators.py +68 -0
  20. softauth-0.1.0/softauth/django/middleware.py +59 -0
  21. softauth-0.1.0/softauth/django/urls.py +36 -0
  22. softauth-0.1.0/softauth/django/views.py +139 -0
  23. softauth-0.1.0/softauth/fastapi/__init__.py +6 -0
  24. softauth-0.1.0/softauth/fastapi/adapter.py +55 -0
  25. softauth-0.1.0/softauth/fastapi/dependencies.py +107 -0
  26. softauth-0.1.0/softauth/fastapi/middleware.py +54 -0
  27. softauth-0.1.0/softauth/fastapi/routes.py +147 -0
  28. softauth-0.1.0/softauth/flask/__init__.py +6 -0
  29. softauth-0.1.0/softauth/flask/adapter.py +63 -0
  30. softauth-0.1.0/softauth/flask/decorators.py +73 -0
  31. softauth-0.1.0/softauth/flask/middleware.py +39 -0
  32. softauth-0.1.0/softauth/flask/routes.py +118 -0
  33. softauth-0.1.0/softauth/interfaces/__init__.py +12 -0
  34. softauth-0.1.0/softauth/interfaces/adapter.py +48 -0
  35. softauth-0.1.0/softauth/interfaces/auth_provider.py +34 -0
  36. softauth-0.1.0/softauth/interfaces/token_store.py +37 -0
  37. softauth-0.1.0/softauth/interfaces/user_store.py +39 -0
  38. softauth-0.1.0/softauth/jwt/__init__.py +4 -0
  39. softauth-0.1.0/softauth/jwt/handler.py +99 -0
  40. softauth-0.1.0/softauth/jwt/schemas.py +37 -0
  41. softauth-0.1.0/softauth/security/__init__.py +3 -0
  42. softauth-0.1.0/softauth/security/password.py +32 -0
  43. softauth-0.1.0/softauth.egg-info/PKG-INFO +307 -0
  44. softauth-0.1.0/softauth.egg-info/SOURCES.txt +53 -0
  45. softauth-0.1.0/softauth.egg-info/dependency_links.txt +1 -0
  46. softauth-0.1.0/softauth.egg-info/entry_points.txt +2 -0
  47. softauth-0.1.0/softauth.egg-info/requires.txt +32 -0
  48. softauth-0.1.0/softauth.egg-info/top_level.txt +1 -0
  49. softauth-0.1.0/tests/test_core.py +160 -0
  50. softauth-0.1.0/tests/test_database.py +84 -0
  51. softauth-0.1.0/tests/test_django.py +344 -0
  52. softauth-0.1.0/tests/test_fastapi.py +288 -0
  53. softauth-0.1.0/tests/test_flask.py +161 -0
  54. softauth-0.1.0/tests/test_jwt.py +107 -0
  55. softauth-0.1.0/tests/test_security.py +54 -0
softauth-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 softauth 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,307 @@
1
+ Metadata-Version: 2.4
2
+ Name: softauth
3
+ Version: 0.1.0
4
+ Summary: Zero-setup JWT authentication for FastAPI and Flask
5
+ Author: Soft Tech Talks
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/suhanapthn24/softauth.git
8
+ Project-URL: Repository, https://github.com/suhanapthn24/softauth.git
9
+ Project-URL: Documentation, https://softauth.readthedocs.io
10
+ Project-URL: Bug Tracker, https://github.com/suhanapthn24/softauth.git/issues
11
+ Keywords: authentication,jwt,fastapi,flask,security,rbac
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Framework :: FastAPI
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Internet :: WWW/HTTP :: Session
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: pyjwt>=2.8.0
28
+ Requires-Dist: passlib[bcrypt]>=1.7.4
29
+ Requires-Dist: pydantic>=2.0.0
30
+ Requires-Dist: sqlalchemy>=2.0.0
31
+ Requires-Dist: typer>=0.9.0
32
+ Requires-Dist: python-dotenv>=1.0.0
33
+ Provides-Extra: fastapi
34
+ Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
35
+ Requires-Dist: python-multipart>=0.0.6; extra == "fastapi"
36
+ Provides-Extra: flask
37
+ Requires-Dist: flask>=2.3.0; extra == "flask"
38
+ Provides-Extra: django
39
+ Requires-Dist: django>=4.2; extra == "django"
40
+ Provides-Extra: sqlmodel
41
+ Requires-Dist: sqlmodel>=0.0.14; extra == "sqlmodel"
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
44
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
45
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
46
+ Requires-Dist: httpx>=0.24.0; extra == "dev"
47
+ Requires-Dist: uvicorn>=0.23.0; extra == "dev"
48
+ Requires-Dist: fastapi[all]>=0.100.0; extra == "dev"
49
+ Requires-Dist: flask>=2.3.0; extra == "dev"
50
+ Requires-Dist: django>=4.2; extra == "dev"
51
+ Requires-Dist: python-multipart>=0.0.6; extra == "dev"
52
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
53
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
54
+ Dynamic: license-file
55
+
56
+ # softauth
57
+
58
+ **Zero-setup JWT authentication for FastAPI, Flask, and Django.**
59
+
60
+ [![CI](https://github.com/suhanapthn24/softauth/actions/workflows/ci.yml/badge.svg)](https://github.com/suhanapthn24/softauth/actions)
61
+ [![PyPI](https://img.shields.io/pypi/v/softauth)](https://pypi.org/project/softauth/)
62
+ [![Python](https://img.shields.io/pypi/pyversions/softauth)](https://pypi.org/project/softauth/)
63
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
64
+
65
+ ---
66
+
67
+ ## The problem
68
+
69
+ Every new project requires the same boilerplate:
70
+
71
+ - JWT helpers (create / decode / verify)
72
+ - Password hashing
73
+ - Auth routes (`/register`, `/login`, `/refresh`, `/me`)
74
+ - Middleware that parses the token on every request
75
+ - Role-based access control decorators or dependencies
76
+ - User model + database table
77
+
78
+ **softauth eliminates all of it.**
79
+
80
+ ---
81
+
82
+ ## Installation
83
+
84
+ ```bash
85
+ # FastAPI
86
+ pip install "softauth[fastapi]"
87
+
88
+ # Flask
89
+ pip install "softauth[flask]"
90
+
91
+ # Both
92
+ pip install "softauth[fastapi,flask]"
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Quick start — FastAPI
98
+
99
+ ```python
100
+ from fastapi import FastAPI, Depends
101
+ from softauth import SoftAuth
102
+
103
+ auth = SoftAuth(secret_key="your-secret", framework="fastapi")
104
+ app = FastAPI()
105
+ auth.init_app(app) # mounts /auth/* routes + JWT middleware
106
+ auth.init_db() # creates the users table
107
+
108
+ @app.get("/profile")
109
+ def profile(user=Depends(auth.current_user)):
110
+ return user.to_dict()
111
+
112
+ @app.get("/admin")
113
+ def admin(user=Depends(auth.current_admin)):
114
+ return {"msg": f"hello admin {user.email}"}
115
+
116
+ @app.get("/editor")
117
+ def editor(user=Depends(auth.require_role("editor"))):
118
+ return {"msg": f"hello editor {user.email}"}
119
+ ```
120
+
121
+ Visit `/docs` — Swagger UI shows all auth routes and lets you log in directly.
122
+
123
+ ---
124
+
125
+ ## Quick start — Flask
126
+
127
+ ```python
128
+ from flask import Flask, g, jsonify
129
+ from softauth import SoftAuth
130
+
131
+ auth = SoftAuth(secret_key="your-secret", framework="flask")
132
+ app = Flask(__name__)
133
+ auth.init_app(app) # registers /auth/* blueprint + before_request hook
134
+ auth.init_db() # creates the users table
135
+
136
+ @app.route("/profile")
137
+ @auth.login_required
138
+ def profile():
139
+ return jsonify(g.user.to_dict())
140
+
141
+ @app.route("/admin")
142
+ @auth.admin_required
143
+ def admin():
144
+ return jsonify({"msg": f"hello admin {g.user.email}"})
145
+
146
+ @app.route("/editor")
147
+ @auth.require_role("editor")
148
+ def editor():
149
+ return jsonify({"msg": f"hello editor {g.user.email}"})
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Auto-generated routes
155
+
156
+ | Method | Path | Description |
157
+ |--------|-------------------|------------------------------------------|
158
+ | POST | `/auth/register` | Create a new account |
159
+ | POST | `/auth/login` | Exchange credentials for a token pair |
160
+ | POST | `/auth/refresh` | Exchange a refresh token for access token|
161
+ | GET | `/auth/me` | Current user's profile |
162
+ | POST | `/auth/logout` | Instruct client to discard tokens |
163
+
164
+ ---
165
+
166
+ ## Configuration
167
+
168
+ ```python
169
+ auth = SoftAuth(
170
+ secret_key="your-secret", # required
171
+ framework="fastapi", # "fastapi" | "flask" | None (custom adapter)
172
+ algorithm="HS256", # JWT algorithm
173
+ access_expiry_minutes=15, # access token lifetime
174
+ refresh_expiry_days=7, # refresh token lifetime
175
+ database_url="sqlite:///auth.db", # any SQLAlchemy URL
176
+ auth_prefix="/auth", # route prefix
177
+ enable_refresh_tokens=True,
178
+ )
179
+ ```
180
+
181
+ ### Environment variables
182
+
183
+ | Variable | Config field |
184
+ |---------------------|-------------------------|
185
+ | `SOFTAUTH_SECRET` | `secret_key` |
186
+ | `SOFTAUTH_DB_URL` | `database_url` |
187
+ | `SOFTAUTH_ALGORITHM`| `algorithm` |
188
+
189
+ ---
190
+
191
+ ## CLI
192
+
193
+ ```bash
194
+ # Scaffold project
195
+ softauth init
196
+
197
+ # Generate FastAPI boilerplate
198
+ softauth setup fastapi
199
+
200
+ # Generate Flask boilerplate
201
+ softauth setup flask
202
+
203
+ # Print a secure secret key
204
+ softauth secret
205
+ ```
206
+
207
+ ---
208
+
209
+ ## RBAC
210
+
211
+ Roles are stored on each user record. Built-in roles: `user`, `manager`, `admin`.
212
+ Custom roles work out of the box — register a user with any role string.
213
+
214
+ | What | FastAPI | Flask |
215
+ |-------------------------|---------------------------------------|-------------------------------|
216
+ | Any authenticated user | `Depends(auth.current_user)` | `@auth.login_required` |
217
+ | Admin only | `Depends(auth.current_admin)` | `@auth.admin_required` |
218
+ | Specific role | `Depends(auth.require_role("mgr"))` | `@auth.require_role("mgr")` |
219
+
220
+ Admin users are **always** allowed through `require_role()` checks.
221
+
222
+ ---
223
+
224
+ ## Custom adapters (Django, Litestar, Quart, …)
225
+
226
+ The core is 100% framework-agnostic. Add support for any framework by
227
+ implementing `BaseAdapter` and calling `use_adapter()`:
228
+
229
+ ```python
230
+ from softauth import SoftAuth
231
+ from softauth.interfaces import BaseAdapter
232
+
233
+ class DjangoAdapter(BaseAdapter):
234
+ def init_app(self, app): ...
235
+ def get_current_user_dependency(self): ...
236
+ def get_current_admin_dependency(self): ...
237
+ def get_require_role_dependency(self, role): ...
238
+
239
+ auth = SoftAuth(secret_key="...", framework=None)
240
+ auth.use_adapter(DjangoAdapter(auth, auth.config), django_app)
241
+ ```
242
+
243
+ ---
244
+
245
+ ## Extension points
246
+
247
+ These interfaces are ready for future implementations without breaking the
248
+ existing API:
249
+
250
+ | Interface | Purpose |
251
+ |-----------------|------------------------------------------------|
252
+ | `BaseAdapter` | Add any framework (Django, Litestar, Quart …) |
253
+ | `AuthProvider` | OAuth2 / social login (Google, GitHub …) |
254
+ | `TokenStore` | Redis token blacklisting, audit logs |
255
+ | `UserStore` | Custom identity backends, multi-tenant |
256
+
257
+ ---
258
+
259
+ ## Architecture
260
+
261
+ ```
262
+ softauth/
263
+ ├── core/ # SoftAuth facade, SoftAuthConfig, exceptions
264
+ ├── jwt/ # JWTHandler — zero framework imports
265
+ ├── security/ # PasswordHandler — zero framework imports
266
+ ├── database/ # SQLAlchemy models, session, repository
267
+ ├── interfaces/ # BaseAdapter, AuthProvider, TokenStore, UserStore ABCs
268
+ ├── fastapi/ # FastAPIAdapter, DependencyFactory, JWTMiddleware, routes
269
+ ├── flask/ # FlaskAdapter, DecoratorFactory, middleware, routes
270
+ └── cli/ # Typer CLI commands
271
+ ```
272
+
273
+ The JWT engine (`softauth.jwt`) and password handler (`softauth.security`) import
274
+ nothing from any web framework. Adapters are loaded lazily so installing only
275
+ `fastapi` or only `flask` works without errors.
276
+
277
+ ---
278
+
279
+ ## Testing
280
+
281
+ ```bash
282
+ pip install -e ".[dev]"
283
+ pytest --cov=softauth
284
+ ```
285
+
286
+ Minimum required coverage: **90 %**
287
+
288
+ ---
289
+
290
+ ## Versioning
291
+
292
+ This project follows [Semantic Versioning](https://semver.org/).
293
+ See [CHANGELOG.md](CHANGELOG.md) for the full history.
294
+
295
+ ### Releasing
296
+
297
+ ```bash
298
+ git tag v0.2.0
299
+ git push origin v0.2.0
300
+ # GitHub Actions builds and publishes to PyPI automatically
301
+ ```
302
+
303
+ ---
304
+
305
+ ## License
306
+
307
+ [MIT](LICENSE)
@@ -0,0 +1,252 @@
1
+ # softauth
2
+
3
+ **Zero-setup JWT authentication for FastAPI, Flask, and Django.**
4
+
5
+ [![CI](https://github.com/suhanapthn24/softauth/actions/workflows/ci.yml/badge.svg)](https://github.com/suhanapthn24/softauth/actions)
6
+ [![PyPI](https://img.shields.io/pypi/v/softauth)](https://pypi.org/project/softauth/)
7
+ [![Python](https://img.shields.io/pypi/pyversions/softauth)](https://pypi.org/project/softauth/)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
9
+
10
+ ---
11
+
12
+ ## The problem
13
+
14
+ Every new project requires the same boilerplate:
15
+
16
+ - JWT helpers (create / decode / verify)
17
+ - Password hashing
18
+ - Auth routes (`/register`, `/login`, `/refresh`, `/me`)
19
+ - Middleware that parses the token on every request
20
+ - Role-based access control decorators or dependencies
21
+ - User model + database table
22
+
23
+ **softauth eliminates all of it.**
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ # FastAPI
31
+ pip install "softauth[fastapi]"
32
+
33
+ # Flask
34
+ pip install "softauth[flask]"
35
+
36
+ # Both
37
+ pip install "softauth[fastapi,flask]"
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Quick start — FastAPI
43
+
44
+ ```python
45
+ from fastapi import FastAPI, Depends
46
+ from softauth import SoftAuth
47
+
48
+ auth = SoftAuth(secret_key="your-secret", framework="fastapi")
49
+ app = FastAPI()
50
+ auth.init_app(app) # mounts /auth/* routes + JWT middleware
51
+ auth.init_db() # creates the users table
52
+
53
+ @app.get("/profile")
54
+ def profile(user=Depends(auth.current_user)):
55
+ return user.to_dict()
56
+
57
+ @app.get("/admin")
58
+ def admin(user=Depends(auth.current_admin)):
59
+ return {"msg": f"hello admin {user.email}"}
60
+
61
+ @app.get("/editor")
62
+ def editor(user=Depends(auth.require_role("editor"))):
63
+ return {"msg": f"hello editor {user.email}"}
64
+ ```
65
+
66
+ Visit `/docs` — Swagger UI shows all auth routes and lets you log in directly.
67
+
68
+ ---
69
+
70
+ ## Quick start — Flask
71
+
72
+ ```python
73
+ from flask import Flask, g, jsonify
74
+ from softauth import SoftAuth
75
+
76
+ auth = SoftAuth(secret_key="your-secret", framework="flask")
77
+ app = Flask(__name__)
78
+ auth.init_app(app) # registers /auth/* blueprint + before_request hook
79
+ auth.init_db() # creates the users table
80
+
81
+ @app.route("/profile")
82
+ @auth.login_required
83
+ def profile():
84
+ return jsonify(g.user.to_dict())
85
+
86
+ @app.route("/admin")
87
+ @auth.admin_required
88
+ def admin():
89
+ return jsonify({"msg": f"hello admin {g.user.email}"})
90
+
91
+ @app.route("/editor")
92
+ @auth.require_role("editor")
93
+ def editor():
94
+ return jsonify({"msg": f"hello editor {g.user.email}"})
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Auto-generated routes
100
+
101
+ | Method | Path | Description |
102
+ |--------|-------------------|------------------------------------------|
103
+ | POST | `/auth/register` | Create a new account |
104
+ | POST | `/auth/login` | Exchange credentials for a token pair |
105
+ | POST | `/auth/refresh` | Exchange a refresh token for access token|
106
+ | GET | `/auth/me` | Current user's profile |
107
+ | POST | `/auth/logout` | Instruct client to discard tokens |
108
+
109
+ ---
110
+
111
+ ## Configuration
112
+
113
+ ```python
114
+ auth = SoftAuth(
115
+ secret_key="your-secret", # required
116
+ framework="fastapi", # "fastapi" | "flask" | None (custom adapter)
117
+ algorithm="HS256", # JWT algorithm
118
+ access_expiry_minutes=15, # access token lifetime
119
+ refresh_expiry_days=7, # refresh token lifetime
120
+ database_url="sqlite:///auth.db", # any SQLAlchemy URL
121
+ auth_prefix="/auth", # route prefix
122
+ enable_refresh_tokens=True,
123
+ )
124
+ ```
125
+
126
+ ### Environment variables
127
+
128
+ | Variable | Config field |
129
+ |---------------------|-------------------------|
130
+ | `SOFTAUTH_SECRET` | `secret_key` |
131
+ | `SOFTAUTH_DB_URL` | `database_url` |
132
+ | `SOFTAUTH_ALGORITHM`| `algorithm` |
133
+
134
+ ---
135
+
136
+ ## CLI
137
+
138
+ ```bash
139
+ # Scaffold project
140
+ softauth init
141
+
142
+ # Generate FastAPI boilerplate
143
+ softauth setup fastapi
144
+
145
+ # Generate Flask boilerplate
146
+ softauth setup flask
147
+
148
+ # Print a secure secret key
149
+ softauth secret
150
+ ```
151
+
152
+ ---
153
+
154
+ ## RBAC
155
+
156
+ Roles are stored on each user record. Built-in roles: `user`, `manager`, `admin`.
157
+ Custom roles work out of the box — register a user with any role string.
158
+
159
+ | What | FastAPI | Flask |
160
+ |-------------------------|---------------------------------------|-------------------------------|
161
+ | Any authenticated user | `Depends(auth.current_user)` | `@auth.login_required` |
162
+ | Admin only | `Depends(auth.current_admin)` | `@auth.admin_required` |
163
+ | Specific role | `Depends(auth.require_role("mgr"))` | `@auth.require_role("mgr")` |
164
+
165
+ Admin users are **always** allowed through `require_role()` checks.
166
+
167
+ ---
168
+
169
+ ## Custom adapters (Django, Litestar, Quart, …)
170
+
171
+ The core is 100% framework-agnostic. Add support for any framework by
172
+ implementing `BaseAdapter` and calling `use_adapter()`:
173
+
174
+ ```python
175
+ from softauth import SoftAuth
176
+ from softauth.interfaces import BaseAdapter
177
+
178
+ class DjangoAdapter(BaseAdapter):
179
+ def init_app(self, app): ...
180
+ def get_current_user_dependency(self): ...
181
+ def get_current_admin_dependency(self): ...
182
+ def get_require_role_dependency(self, role): ...
183
+
184
+ auth = SoftAuth(secret_key="...", framework=None)
185
+ auth.use_adapter(DjangoAdapter(auth, auth.config), django_app)
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Extension points
191
+
192
+ These interfaces are ready for future implementations without breaking the
193
+ existing API:
194
+
195
+ | Interface | Purpose |
196
+ |-----------------|------------------------------------------------|
197
+ | `BaseAdapter` | Add any framework (Django, Litestar, Quart …) |
198
+ | `AuthProvider` | OAuth2 / social login (Google, GitHub …) |
199
+ | `TokenStore` | Redis token blacklisting, audit logs |
200
+ | `UserStore` | Custom identity backends, multi-tenant |
201
+
202
+ ---
203
+
204
+ ## Architecture
205
+
206
+ ```
207
+ softauth/
208
+ ├── core/ # SoftAuth facade, SoftAuthConfig, exceptions
209
+ ├── jwt/ # JWTHandler — zero framework imports
210
+ ├── security/ # PasswordHandler — zero framework imports
211
+ ├── database/ # SQLAlchemy models, session, repository
212
+ ├── interfaces/ # BaseAdapter, AuthProvider, TokenStore, UserStore ABCs
213
+ ├── fastapi/ # FastAPIAdapter, DependencyFactory, JWTMiddleware, routes
214
+ ├── flask/ # FlaskAdapter, DecoratorFactory, middleware, routes
215
+ └── cli/ # Typer CLI commands
216
+ ```
217
+
218
+ The JWT engine (`softauth.jwt`) and password handler (`softauth.security`) import
219
+ nothing from any web framework. Adapters are loaded lazily so installing only
220
+ `fastapi` or only `flask` works without errors.
221
+
222
+ ---
223
+
224
+ ## Testing
225
+
226
+ ```bash
227
+ pip install -e ".[dev]"
228
+ pytest --cov=softauth
229
+ ```
230
+
231
+ Minimum required coverage: **90 %**
232
+
233
+ ---
234
+
235
+ ## Versioning
236
+
237
+ This project follows [Semantic Versioning](https://semver.org/).
238
+ See [CHANGELOG.md](CHANGELOG.md) for the full history.
239
+
240
+ ### Releasing
241
+
242
+ ```bash
243
+ git tag v0.2.0
244
+ git push origin v0.2.0
245
+ # GitHub Actions builds and publishes to PyPI automatically
246
+ ```
247
+
248
+ ---
249
+
250
+ ## License
251
+
252
+ [MIT](LICENSE)
@@ -0,0 +1,92 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "softauth"
7
+ version = "0.1.0"
8
+ description = "Zero-setup JWT authentication for FastAPI and Flask"
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.9"
12
+ authors = [{ name = "Soft Tech Talks" }]
13
+ keywords = ["authentication", "jwt", "fastapi", "flask", "security", "rbac"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Framework :: FastAPI",
24
+ "Topic :: Security",
25
+ "Topic :: Internet :: WWW/HTTP :: Session",
26
+ "Typing :: Typed",
27
+ ]
28
+ dependencies = [
29
+ "pyjwt>=2.8.0",
30
+ "passlib[bcrypt]>=1.7.4",
31
+ "pydantic>=2.0.0",
32
+ "sqlalchemy>=2.0.0",
33
+ "typer>=0.9.0",
34
+ "python-dotenv>=1.0.0",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ fastapi = [
39
+ "fastapi>=0.100.0",
40
+ "python-multipart>=0.0.6",
41
+ ]
42
+ flask = [
43
+ "flask>=2.3.0",
44
+ ]
45
+ django = [
46
+ "django>=4.2",
47
+ ]
48
+ sqlmodel = [
49
+ "sqlmodel>=0.0.14",
50
+ ]
51
+ dev = [
52
+ "pytest>=7.4.0",
53
+ "pytest-asyncio>=0.21.0",
54
+ "pytest-cov>=4.1.0",
55
+ "httpx>=0.24.0",
56
+ "uvicorn>=0.23.0",
57
+ "fastapi[all]>=0.100.0",
58
+ "flask>=2.3.0",
59
+ "django>=4.2",
60
+ "python-multipart>=0.0.6",
61
+ "ruff>=0.1.0",
62
+ "mypy>=1.5.0",
63
+ ]
64
+
65
+ [project.scripts]
66
+ softauth = "softauth.cli.commands:app"
67
+
68
+ [project.urls]
69
+ Homepage = "https://github.com/suhanapthn24/softauth.git"
70
+ Repository = "https://github.com/suhanapthn24/softauth.git"
71
+ Documentation = "https://softauth.readthedocs.io"
72
+ "Bug Tracker" = "https://github.com/suhanapthn24/softauth.git/issues"
73
+
74
+ [tool.setuptools.packages.find]
75
+ where = ["."]
76
+ include = ["softauth*"]
77
+
78
+ [tool.pytest.ini_options]
79
+ testpaths = ["tests"]
80
+ asyncio_mode = "auto"
81
+ addopts = "--cov=softauth --cov-report=term-missing --cov-fail-under=90"
82
+
83
+ [tool.ruff]
84
+ line-length = 100
85
+ target-version = "py39"
86
+ select = ["E", "F", "I", "UP", "ANN"]
87
+ ignore = ["ANN101", "ANN102"]
88
+
89
+ [tool.mypy]
90
+ python_version = "3.9"
91
+ strict = true
92
+ ignore_missing_imports = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+