fastapi-startkit-auth 0.6.3__tar.gz → 0.7.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_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/CHANGELOG.md +9 -1
- fastapi_startkit_auth-0.7.0/PKG-INFO +67 -0
- fastapi_startkit_auth-0.7.0/README.md +23 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/pyproject.toml +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/__init__.py +39 -7
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/manager.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/commands/oauth2_client.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/config/__init__.py +4 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/config/auth.py +36 -19
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/dependencies.py +6 -6
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/exceptions.py +41 -16
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/facade.py +4 -4
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/authorization_code.py +7 -7
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/client_credentials.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/password.py +5 -5
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/refresh.py +4 -4
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/guards/guard.py +5 -5
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/guards/session.py +9 -9
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/guards/token.py +9 -9
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/manager.py +21 -21
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/middleware/csrf.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/passwords/broker.py +11 -11
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/policy.py +12 -12
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/provider.py +4 -4
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/routes.py +38 -38
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/routes_password.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/security/jwt.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/facade.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/tokens/service.py +11 -11
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/conftest.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_api_tokens.py +12 -12
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_async_auth.py +6 -6
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_async_refresh_race.py +7 -7
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_async_safety.py +3 -3
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_class_config.py +3 -3
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_client_scopes.py +6 -6
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_facade_api.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_grants.py +8 -8
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_integration.py +24 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_jwt.py +7 -7
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_manager.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_multi_provider.py +1 -1
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_oauth21.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_oauth2_client_command.py +3 -3
- fastapi_startkit_auth-0.7.0/tests/test_oauth_config_aliases.py +29 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_oauth_hardening.py +19 -19
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_password_reset.py +5 -5
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_resource_binding.py +25 -25
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_security_fixes.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_session_auth.py +6 -6
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_spa_csrf.py +2 -2
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_startkit_provider.py +3 -3
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_store_names.py +9 -9
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_sync_regression.py +7 -7
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_token_service.py +8 -8
- fastapi_startkit_auth-0.6.3/PKG-INFO +0 -398
- fastapi_startkit_auth-0.6.3/README.md +0 -354
- /fastapi_startkit_auth-0.6.3/LICENSE → /fastapi_startkit_auth-0.7.0/LICENSE.md +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/facade.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/models.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/orm.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/apitokens/repository.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/clients/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/clients/credentials.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/clients/models.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/clients/orm.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/clients/repository.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/commands/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/concurrency.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/grants/pkce.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/guards/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/middleware/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/middleware/context.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/middleware/session.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/orm.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/passwords/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/passwords/repository.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/providers/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/providers/base.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/providers/fields.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/providers/memory.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/providers/model.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/cors.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_09_30_000001_create_sessions_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_09_30_000002_create_personal_api_tokens_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_09_30_000003_create_oauth_access_tokens_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_09_30_000004_create_oauth_refresh_tokens_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_09_30_000005_create_oauth_auth_codes_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_10_02_000001_add_resource_to_oauth_tables.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_10_04_000001_create_oauth_clients_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_10_04_000002_add_family_id_to_oauth_refresh_tokens_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/publishable/migrations/2026_10_05_000001_add_scopes_to_oauth_clients_table.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/py.typed +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/request_context.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/routes_spa.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/scoped_method.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/security/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/security/hashing.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/models.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/orm.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/state.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/sessions/store.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/tokens/__init__.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/tokens/models.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/tokens/orm.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/tokens/repository.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_async_stores.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_clients.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_guard_registry.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_hashing.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_model_provider.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_model_provider_postgres.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_reset_throttle_enumeration.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_session_store.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_token_repository.py +0 -0
- {fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/tests/test_user_provider.py +0 -0
|
@@ -66,7 +66,7 @@ Each item lists what changed and what to do.
|
|
|
66
66
|
in `SessionConfig.csrf_exempt_paths`.
|
|
67
67
|
- **OAuth client store defaults to `"database"`** (the ORM `oauth_clients`
|
|
68
68
|
table). *Migrate:* publish and run the migrations, or set
|
|
69
|
-
`OAuth2Config(clients=
|
|
69
|
+
`OAuth2Config(clients=OAuthClientConfig(store="memory"))`.
|
|
70
70
|
- **The in-memory OAuth client store is async.** `InMemoryClientRepository`
|
|
71
71
|
methods (`register`, `add`, `find`, `all`, `authenticate`, `revoke`,
|
|
72
72
|
`delete`) are coroutines, like `OrmClientRepository`, and `store="memory"` now
|
|
@@ -74,6 +74,14 @@ Each item lists what changed and what to do.
|
|
|
74
74
|
synchronous custom store passed with `store="instance"` keeps the sync grants.
|
|
75
75
|
*Migrate:*
|
|
76
76
|
`await` client-store calls and the `handle` / `issue_code` of those grants.
|
|
77
|
+
- **Exception classes take an `Exception` suffix.** `AuthError` is now
|
|
78
|
+
`AuthException`, and every subclass gets the suffix (`InvalidToken` →
|
|
79
|
+
`InvalidTokenException`, `InsufficientScope` → `MissingScopeException`, and so
|
|
80
|
+
on). Wire error codes and HTTP statuses are unchanged. The old names remain as
|
|
81
|
+
deprecated aliases. *Migrate:* import the `*Exception` names.
|
|
82
|
+
- **Bad password on the password grant raises `InvalidCredentialsException`**, a
|
|
83
|
+
subclass of `InvalidGrantException`. The response is unchanged (`invalid_grant`,
|
|
84
|
+
400), so existing `except InvalidGrantException` blocks still catch it.
|
|
77
85
|
- **Persistent stores are named `"database"`.** `store="orm"` still works for
|
|
78
86
|
sessions, API tokens, OAuth tokens and OAuth clients, but emits a
|
|
79
87
|
`DeprecationWarning` and will be removed in a future release. *Migrate:*
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-startkit-auth
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Laravel-style authentication for FastAPI: OAuth2/JWT authorization server, cookie/session guard, SPA + CSRF protection, and Sanctum-style API tokens.
|
|
5
|
+
Keywords: fastapi,oauth2,jwt,auth,passport,sanctum,authentication,authorization,security,tokens,session,cookie,csrf,spa,starter-kit
|
|
6
|
+
Author: Bedram Tamang
|
|
7
|
+
Author-email: Bedram Tamang <tmgbedu@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE.md
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Session
|
|
20
|
+
Classifier: Topic :: Security
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Dist: fastapi>=0.110
|
|
24
|
+
Requires-Dist: pyjwt>=2.10.1
|
|
25
|
+
Requires-Dist: bcrypt>=4.1
|
|
26
|
+
Requires-Dist: pydantic>=2
|
|
27
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
28
|
+
Requires-Dist: masonite-orm>=2.18 ; extra == 'masoniteorm'
|
|
29
|
+
Requires-Dist: fastapi-startkit[database]>=0.60,<1.0 ; python_full_version >= '3.12' and extra == 'startkit'
|
|
30
|
+
Requires-Dist: pytest>=8 ; extra == 'test'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.23 ; extra == 'test'
|
|
32
|
+
Requires-Dist: httpx>=0.27 ; extra == 'test'
|
|
33
|
+
Requires-Dist: aiosqlite>=0.20 ; extra == 'test'
|
|
34
|
+
Requires-Dist: asyncpg>=0.29 ; extra == 'test'
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Project-URL: Homepage, https://github.com/fastapi-startkit/fastapi-startkit-auth
|
|
37
|
+
Project-URL: Repository, https://github.com/fastapi-startkit/fastapi-startkit-auth
|
|
38
|
+
Project-URL: Issues, https://github.com/fastapi-startkit/fastapi-startkit-auth/issues
|
|
39
|
+
Project-URL: Changelog, https://github.com/fastapi-startkit/fastapi-startkit-auth/blob/main/CHANGELOG.md
|
|
40
|
+
Provides-Extra: masoniteorm
|
|
41
|
+
Provides-Extra: startkit
|
|
42
|
+
Provides-Extra: test
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
|
|
45
|
+
# FastAPI Startkit Auth
|
|
46
|
+
|
|
47
|
+
FastAPI Startkit Auth provides authentication for FastAPI: an OAuth2/JWT authorization server, cookie/session guards, SPA + CSRF protection, and API tokens.
|
|
48
|
+
|
|
49
|
+
## Official Documentation
|
|
50
|
+
|
|
51
|
+
Documentation for FastAPI Startkit Auth can be found on the [FastAPI Startkit website](https://fastapi-startkit.github.io/docs/authentication).
|
|
52
|
+
|
|
53
|
+
## Contributing
|
|
54
|
+
|
|
55
|
+
Thank you for considering contributing to FastAPI Startkit Auth! The contribution guide can be found in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
56
|
+
|
|
57
|
+
## Code of Conduct
|
|
58
|
+
|
|
59
|
+
In order to ensure that the FastAPI Startkit community is welcoming to all, please review and abide by the code of conduct in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
60
|
+
|
|
61
|
+
## Security Vulnerabilities
|
|
62
|
+
|
|
63
|
+
If you discover a security vulnerability within FastAPI Startkit Auth, please report it privately to the maintainers rather than opening a public issue. Details can be found in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
64
|
+
|
|
65
|
+
## License
|
|
66
|
+
|
|
67
|
+
FastAPI Startkit Auth is open-sourced software licensed under the [MIT license](LICENSE.md).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# FastAPI Startkit Auth
|
|
2
|
+
|
|
3
|
+
FastAPI Startkit Auth provides authentication for FastAPI: an OAuth2/JWT authorization server, cookie/session guards, SPA + CSRF protection, and API tokens.
|
|
4
|
+
|
|
5
|
+
## Official Documentation
|
|
6
|
+
|
|
7
|
+
Documentation for FastAPI Startkit Auth can be found on the [FastAPI Startkit website](https://fastapi-startkit.github.io/docs/authentication).
|
|
8
|
+
|
|
9
|
+
## Contributing
|
|
10
|
+
|
|
11
|
+
Thank you for considering contributing to FastAPI Startkit Auth! The contribution guide can be found in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
12
|
+
|
|
13
|
+
## Code of Conduct
|
|
14
|
+
|
|
15
|
+
In order to ensure that the FastAPI Startkit community is welcoming to all, please review and abide by the code of conduct in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
16
|
+
|
|
17
|
+
## Security Vulnerabilities
|
|
18
|
+
|
|
19
|
+
If you discover a security vulnerability within FastAPI Startkit Auth, please report it privately to the maintainers rather than opening a public issue. Details can be found in the [FastAPI Startkit documentation](https://fastapi-startkit.github.io/docs/authentication).
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
FastAPI Startkit Auth is open-sourced software licensed under the [MIT license](LICENSE.md).
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fastapi-startkit-auth"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Laravel-style authentication for FastAPI: OAuth2/JWT authorization server, cookie/session guard, SPA + CSRF protection, and Sanctum-style API tokens."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
7
|
-
license-files = ["LICENSE"]
|
|
7
|
+
license-files = ["LICENSE.md"]
|
|
8
8
|
keywords = [
|
|
9
9
|
"fastapi",
|
|
10
10
|
"oauth2",
|
{fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/__init__.py
RENAMED
|
@@ -18,7 +18,9 @@ from .config import (
|
|
|
18
18
|
ApiTokenConfig,
|
|
19
19
|
AuthConfig,
|
|
20
20
|
OAuth2Config,
|
|
21
|
+
OAuthClientConfig,
|
|
21
22
|
OAuthClientsConfig,
|
|
23
|
+
OAuthTokenConfig,
|
|
22
24
|
OAuthTokensConfig,
|
|
23
25
|
SessionConfig,
|
|
24
26
|
)
|
|
@@ -31,18 +33,32 @@ from .dependencies import (
|
|
|
31
33
|
)
|
|
32
34
|
from .exceptions import (
|
|
33
35
|
AccessDenied,
|
|
36
|
+
AccessDeniedException,
|
|
37
|
+
AuthenticationException,
|
|
34
38
|
AuthError,
|
|
39
|
+
AuthException,
|
|
35
40
|
CsrfTokenMismatch,
|
|
41
|
+
CsrfTokenMismatchException,
|
|
36
42
|
InsufficientScope,
|
|
37
43
|
InvalidClient,
|
|
44
|
+
InvalidClientException,
|
|
45
|
+
InvalidCredentialsException,
|
|
38
46
|
InvalidGrant,
|
|
47
|
+
InvalidGrantException,
|
|
39
48
|
InvalidScope,
|
|
49
|
+
InvalidScopeException,
|
|
40
50
|
InvalidSession,
|
|
41
51
|
InvalidTarget,
|
|
52
|
+
InvalidTargetException,
|
|
42
53
|
InvalidToken,
|
|
54
|
+
InvalidTokenException,
|
|
55
|
+
MissingScopeException,
|
|
43
56
|
UnauthorizedClient,
|
|
57
|
+
UnauthorizedClientException,
|
|
44
58
|
UnsupportedGrantType,
|
|
59
|
+
UnsupportedGrantTypeException,
|
|
45
60
|
UnsupportedResponseType,
|
|
61
|
+
UnsupportedResponseTypeException,
|
|
46
62
|
)
|
|
47
63
|
from .policy import GrantPolicy
|
|
48
64
|
from .facade import AsyncAuth, Auth
|
|
@@ -62,13 +78,15 @@ from .sessions.models import SessionRecord
|
|
|
62
78
|
from .sessions.store import InMemorySessionStore, SessionStore
|
|
63
79
|
from .tokens.service import AsyncTokenService, TokenService
|
|
64
80
|
|
|
65
|
-
__version__ = "0.
|
|
81
|
+
__version__ = "0.7.0"
|
|
66
82
|
|
|
67
83
|
__all__ = (
|
|
68
84
|
"AuthConfig",
|
|
69
85
|
"SessionConfig",
|
|
70
86
|
"OAuth2Config",
|
|
87
|
+
"OAuthClientConfig",
|
|
71
88
|
"OAuthClientsConfig",
|
|
89
|
+
"OAuthTokenConfig",
|
|
72
90
|
"OAuthTokensConfig",
|
|
73
91
|
"ApiTokenConfig",
|
|
74
92
|
"AuthProvider",
|
|
@@ -85,23 +103,37 @@ __all__ = (
|
|
|
85
103
|
"InMemoryClientRepository",
|
|
86
104
|
"OrmClientRepository",
|
|
87
105
|
"OrmSessionStore",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
106
|
+
"AccessDeniedException",
|
|
107
|
+
"UnauthorizedClientException",
|
|
108
|
+
"UnsupportedGrantTypeException",
|
|
109
|
+
"UnsupportedResponseTypeException",
|
|
92
110
|
"current_user",
|
|
93
111
|
"optional_user",
|
|
94
112
|
"require_scopes",
|
|
95
113
|
"require_abilities",
|
|
96
|
-
"
|
|
114
|
+
"AuthException",
|
|
97
115
|
"AsyncMisconfiguration",
|
|
116
|
+
"InvalidGrantException",
|
|
117
|
+
"InvalidClientException",
|
|
118
|
+
"InvalidCredentialsException",
|
|
119
|
+
"InvalidTokenException",
|
|
120
|
+
"MissingScopeException",
|
|
121
|
+
"InvalidScopeException",
|
|
122
|
+
"InvalidTargetException",
|
|
123
|
+
"GrantPolicy",
|
|
124
|
+
"AuthenticationException",
|
|
125
|
+
"CsrfTokenMismatchException",
|
|
126
|
+
"AccessDenied",
|
|
127
|
+
"UnauthorizedClient",
|
|
128
|
+
"UnsupportedGrantType",
|
|
129
|
+
"UnsupportedResponseType",
|
|
130
|
+
"AuthError",
|
|
98
131
|
"InvalidGrant",
|
|
99
132
|
"InvalidClient",
|
|
100
133
|
"InvalidToken",
|
|
101
134
|
"InsufficientScope",
|
|
102
135
|
"InvalidScope",
|
|
103
136
|
"InvalidTarget",
|
|
104
|
-
"GrantPolicy",
|
|
105
137
|
"InvalidSession",
|
|
106
138
|
"CsrfTokenMismatch",
|
|
107
139
|
"Auth",
|
|
@@ -7,7 +7,7 @@ from dataclasses import dataclass
|
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
9
|
from ..concurrency import call
|
|
10
|
-
from ..exceptions import
|
|
10
|
+
from ..exceptions import InvalidTokenException
|
|
11
11
|
from .models import ApiTokenRecord
|
|
12
12
|
from .repository import ApiTokenRepository, generate_token_secret, hash_token_secret
|
|
13
13
|
|
|
@@ -29,7 +29,7 @@ def _check_secret(record: ApiTokenRecord | None, secret: str) -> None:
|
|
|
29
29
|
expected = record.token_hash if record is not None else _DUMMY_HASH
|
|
30
30
|
matched = secrets.compare_digest(hash_token_secret(secret), expected)
|
|
31
31
|
if record is None or not matched or record.expired:
|
|
32
|
-
raise
|
|
32
|
+
raise InvalidTokenException(_GENERIC_FAILURE)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def _creation_fields(
|
|
@@ -5,7 +5,7 @@ from cleo.helpers import option
|
|
|
5
5
|
from fastapi_startkit.console import Command
|
|
6
6
|
|
|
7
7
|
from ..concurrency import call
|
|
8
|
-
from ..exceptions import
|
|
8
|
+
from ..exceptions import InvalidScopeException
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def _valid_redirect(uri: str | None) -> bool:
|
|
@@ -45,7 +45,7 @@ class OAuth2ClientCommand(Command):
|
|
|
45
45
|
return 1
|
|
46
46
|
try:
|
|
47
47
|
manager.grant_policy.check_scopes(scopes)
|
|
48
|
-
except
|
|
48
|
+
except InvalidScopeException as error:
|
|
49
49
|
self.line_error(str(error))
|
|
50
50
|
return 1
|
|
51
51
|
client, secret = asyncio.run(
|
|
@@ -6,7 +6,9 @@ from .auth import (
|
|
|
6
6
|
AuthConfig,
|
|
7
7
|
OAuth2Config,
|
|
8
8
|
OAuth2Guard,
|
|
9
|
+
OAuthClientConfig,
|
|
9
10
|
OAuthClientsConfig,
|
|
11
|
+
OAuthTokenConfig,
|
|
10
12
|
OAuthTokensConfig,
|
|
11
13
|
SessionConfig,
|
|
12
14
|
SessionGuard,
|
|
@@ -19,7 +21,9 @@ __all__ = (
|
|
|
19
21
|
"AuthConfig",
|
|
20
22
|
"SessionConfig",
|
|
21
23
|
"OAuth2Config",
|
|
24
|
+
"OAuthClientConfig",
|
|
22
25
|
"OAuthClientsConfig",
|
|
26
|
+
"OAuthTokenConfig",
|
|
23
27
|
"OAuthTokensConfig",
|
|
24
28
|
"ApiTokenConfig",
|
|
25
29
|
"SessionGuard",
|
{fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/config/auth.py
RENAMED
|
@@ -8,14 +8,14 @@ from typing import Any, Literal, TypeVar
|
|
|
8
8
|
ConfigT = TypeVar("ConfigT")
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def
|
|
12
|
-
if
|
|
11
|
+
def _canonical_driver(driver: str, section: str) -> str:
|
|
12
|
+
if driver == "orm":
|
|
13
13
|
# stacklevel 4: this helper, __post_init__, the dataclass __init__, then the caller.
|
|
14
14
|
warnings.warn(
|
|
15
|
-
f'{section}(
|
|
15
|
+
f'{section}(driver="orm") is deprecated; use driver="database".', DeprecationWarning, stacklevel=4
|
|
16
16
|
)
|
|
17
17
|
return "database"
|
|
18
|
-
return
|
|
18
|
+
return driver
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@dataclass
|
|
@@ -41,11 +41,11 @@ class ApiTokenGuard:
|
|
|
41
41
|
class SessionConfig:
|
|
42
42
|
"""Cookie sessions, enabled by ``AuthSessionProvider``.
|
|
43
43
|
|
|
44
|
-
``
|
|
44
|
+
``driver`` is "memory", "database" (the ORM ``sessions`` table; "orm" is a
|
|
45
45
|
deprecated alias) or "instance" (a ready-made store under ``instance``).
|
|
46
46
|
"""
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
driver: str = "memory"
|
|
49
49
|
connection: str | None = None
|
|
50
50
|
instance: Any = None
|
|
51
51
|
cookie: str = "startkit_session"
|
|
@@ -63,7 +63,7 @@ class SessionConfig:
|
|
|
63
63
|
csrf_exempt_paths: list[str] = field(default_factory=list)
|
|
64
64
|
|
|
65
65
|
def __post_init__(self) -> None:
|
|
66
|
-
self.
|
|
66
|
+
self.driver = _canonical_driver(self.driver, "SessionConfig")
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
@dataclass
|
|
@@ -74,7 +74,7 @@ class ApiTokenConfig:
|
|
|
74
74
|
accept the ``session_guard`` cookie session from those origins.
|
|
75
75
|
"""
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
driver: str = "memory"
|
|
78
78
|
connection: str | None = None
|
|
79
79
|
instance: Any = None
|
|
80
80
|
header: str = "Authorization"
|
|
@@ -84,7 +84,7 @@ class ApiTokenConfig:
|
|
|
84
84
|
session_guard: str = "web"
|
|
85
85
|
|
|
86
86
|
def __post_init__(self) -> None:
|
|
87
|
-
self.
|
|
87
|
+
self.driver = _canonical_driver(self.driver, "ApiTokenConfig")
|
|
88
88
|
|
|
89
89
|
@property
|
|
90
90
|
def stateful(self) -> bool:
|
|
@@ -92,25 +92,42 @@ class ApiTokenConfig:
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
@dataclass
|
|
95
|
-
class
|
|
95
|
+
class OAuthClientConfig:
|
|
96
96
|
"""Where OAuth clients live: "database" (the ORM ``oauth_clients`` table), "memory" or "instance"."""
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
driver: str = "database"
|
|
99
99
|
connection: str | None = None
|
|
100
100
|
instance: Any = None
|
|
101
101
|
|
|
102
102
|
def __post_init__(self) -> None:
|
|
103
|
-
self.
|
|
103
|
+
self.driver = _canonical_driver(self.driver, "OAuthClientConfig")
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
@dataclass
|
|
107
|
-
class
|
|
108
|
-
|
|
107
|
+
class OAuthTokenConfig:
|
|
108
|
+
driver: str = "memory"
|
|
109
109
|
connection: str | None = None
|
|
110
110
|
instance: Any = None
|
|
111
111
|
|
|
112
112
|
def __post_init__(self) -> None:
|
|
113
|
-
self.
|
|
113
|
+
self.driver = _canonical_driver(self.driver, "OAuthTokenConfig")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _deprecated_alias(config_type: type[ConfigT], old_name: str) -> type[ConfigT]:
|
|
117
|
+
class Alias(config_type):
|
|
118
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
119
|
+
warnings.warn(
|
|
120
|
+
f"{old_name} is deprecated; use {config_type.__name__}.", DeprecationWarning, stacklevel=2
|
|
121
|
+
)
|
|
122
|
+
super().__init__(*args, **kwargs)
|
|
123
|
+
|
|
124
|
+
Alias.__name__ = old_name
|
|
125
|
+
Alias.__qualname__ = old_name
|
|
126
|
+
return Alias
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
OAuthClientsConfig = _deprecated_alias(OAuthClientConfig, "OAuthClientsConfig")
|
|
130
|
+
OAuthTokensConfig = _deprecated_alias(OAuthTokenConfig, "OAuthTokensConfig")
|
|
114
131
|
|
|
115
132
|
|
|
116
133
|
DEFAULT_GRANT_TYPES = ("authorization_code", "client_credentials", "refresh_token")
|
|
@@ -145,12 +162,12 @@ class OAuth2Config:
|
|
|
145
162
|
require_redirect_uri: bool = True
|
|
146
163
|
grant_types: list[str] = field(default_factory=lambda: list(DEFAULT_GRANT_TYPES))
|
|
147
164
|
authorization_guard: str | None = None
|
|
148
|
-
tokens:
|
|
149
|
-
clients:
|
|
165
|
+
tokens: OAuthTokenConfig = field(default_factory=OAuthTokenConfig)
|
|
166
|
+
clients: OAuthClientConfig = field(default_factory=OAuthClientConfig)
|
|
150
167
|
|
|
151
168
|
def __post_init__(self) -> None:
|
|
152
|
-
self.tokens = resolve_config(self.tokens,
|
|
153
|
-
self.clients = resolve_config(self.clients,
|
|
169
|
+
self.tokens = resolve_config(self.tokens, OAuthTokenConfig)
|
|
170
|
+
self.clients = resolve_config(self.clients, OAuthClientConfig)
|
|
154
171
|
|
|
155
172
|
|
|
156
173
|
# v0.6 AuthConfig attributes that moved to OAuth2Config; still read, with a warning.
|
|
@@ -6,7 +6,7 @@ from fastapi import Depends, Request
|
|
|
6
6
|
from fastapi.security import OAuth2PasswordBearer
|
|
7
7
|
|
|
8
8
|
from .concurrency import call
|
|
9
|
-
from .exceptions import
|
|
9
|
+
from .exceptions import AuthenticationException, AuthException, InvalidTokenException, MissingScopeException
|
|
10
10
|
from .guards.guard import AuthContext
|
|
11
11
|
from .manager import AuthManager
|
|
12
12
|
from .request_context import _auth_request
|
|
@@ -46,7 +46,7 @@ async def resolve_context(request: Request, manager: AuthManager, guard: str | N
|
|
|
46
46
|
return await call(authenticate, request)
|
|
47
47
|
token = _bearer_token(request)
|
|
48
48
|
if not token:
|
|
49
|
-
raise
|
|
49
|
+
raise AuthenticationException("Not authenticated.")
|
|
50
50
|
return await call(resolved.user_from_token, token)
|
|
51
51
|
|
|
52
52
|
|
|
@@ -62,14 +62,14 @@ async def current_context(
|
|
|
62
62
|
async def auth(context: AuthContext = Depends(current_context)) -> AuthContext:
|
|
63
63
|
"""Like ``current_context`` but also rejects user-less (client_credentials) tokens."""
|
|
64
64
|
if context.user is None:
|
|
65
|
-
raise
|
|
65
|
+
raise InvalidTokenException("This token is not associated with a user.")
|
|
66
66
|
return context
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
def current_user(context: AuthContext = Depends(current_context)) -> Any:
|
|
70
70
|
"""Return the authenticated user model (401 if the token carries no user)."""
|
|
71
71
|
if context.user is None:
|
|
72
|
-
raise
|
|
72
|
+
raise InvalidTokenException("This token is not associated with a user.")
|
|
73
73
|
return context.user
|
|
74
74
|
|
|
75
75
|
|
|
@@ -81,7 +81,7 @@ async def optional_user(
|
|
|
81
81
|
"""Return the authenticated user, or ``None`` if unauthenticated/invalid."""
|
|
82
82
|
try:
|
|
83
83
|
return (await resolve_context(request, manager)).user
|
|
84
|
-
except
|
|
84
|
+
except AuthException:
|
|
85
85
|
return None
|
|
86
86
|
|
|
87
87
|
|
|
@@ -96,7 +96,7 @@ def require_scopes(*scopes: str, mode: str = "all") -> Callable[..., AuthContext
|
|
|
96
96
|
def dependency(context: AuthContext = Depends(current_context)) -> AuthContext:
|
|
97
97
|
ok = context.can_any(required) if mode == "any" else context.can_all(required)
|
|
98
98
|
if not ok:
|
|
99
|
-
raise
|
|
99
|
+
raise MissingScopeException(
|
|
100
100
|
f"Requires scope(s): {' '.join(required)} (mode={mode})."
|
|
101
101
|
)
|
|
102
102
|
return context
|
{fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/exceptions.py
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Auth
|
|
1
|
+
"""Auth exception hierarchy.
|
|
2
2
|
|
|
3
3
|
Error codes follow the OAuth2 error registry (RFC 6749 §5.2) so they can be
|
|
4
4
|
surfaced verbatim in token-endpoint responses.
|
|
@@ -6,7 +6,7 @@ surfaced verbatim in token-endpoint responses.
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class AuthException(Exception):
|
|
10
10
|
"""Base class for all authentication/authorization failures."""
|
|
11
11
|
|
|
12
12
|
error = "invalid_request"
|
|
@@ -20,99 +20,124 @@ class AuthError(Exception):
|
|
|
20
20
|
return {"error": self.error, "error_description": self.description}
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class
|
|
23
|
+
class InvalidRequestException(AuthException):
|
|
24
24
|
"""The request is missing a required parameter or is otherwise malformed."""
|
|
25
25
|
|
|
26
26
|
error = "invalid_request"
|
|
27
27
|
status_code = 400
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
class
|
|
30
|
+
class InvalidClientException(AuthException):
|
|
31
31
|
"""Client authentication failed (unknown client or bad secret)."""
|
|
32
32
|
|
|
33
33
|
error = "invalid_client"
|
|
34
34
|
status_code = 401
|
|
35
35
|
|
|
36
36
|
|
|
37
|
-
class
|
|
37
|
+
class InvalidGrantException(AuthException):
|
|
38
38
|
"""The provided credentials, code, or refresh token are invalid or expired."""
|
|
39
39
|
|
|
40
40
|
error = "invalid_grant"
|
|
41
41
|
status_code = 400
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
class
|
|
44
|
+
class InvalidCredentialsException(InvalidGrantException):
|
|
45
|
+
"""The username or password is incorrect (password grant)."""
|
|
46
|
+
|
|
47
|
+
error = "invalid_grant"
|
|
48
|
+
status_code = 400
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class UnsupportedGrantTypeException(AuthException):
|
|
45
52
|
"""The authorization server does not support this grant type."""
|
|
46
53
|
|
|
47
54
|
error = "unsupported_grant_type"
|
|
48
55
|
status_code = 400
|
|
49
56
|
|
|
50
57
|
|
|
51
|
-
class
|
|
58
|
+
class UnauthorizedClientException(AuthException):
|
|
52
59
|
"""The client is not permitted to use this grant type."""
|
|
53
60
|
|
|
54
61
|
error = "unauthorized_client"
|
|
55
62
|
status_code = 400
|
|
56
63
|
|
|
57
64
|
|
|
58
|
-
class
|
|
65
|
+
class InvalidTokenException(AuthException):
|
|
59
66
|
"""The access token is expired, malformed, revoked, or otherwise invalid."""
|
|
60
67
|
|
|
61
68
|
error = "invalid_token"
|
|
62
69
|
status_code = 401
|
|
63
70
|
|
|
64
71
|
|
|
65
|
-
class
|
|
72
|
+
class AuthenticationException(AuthException):
|
|
66
73
|
"""The session cookie is missing, expired, or no longer valid."""
|
|
67
74
|
|
|
68
75
|
error = "invalid_session"
|
|
69
76
|
status_code = 401
|
|
70
77
|
|
|
71
78
|
|
|
72
|
-
class
|
|
79
|
+
class CsrfTokenMismatchException(AuthException):
|
|
73
80
|
"""The request is missing a valid CSRF token for this session."""
|
|
74
81
|
|
|
75
82
|
error = "csrf_token_mismatch"
|
|
76
83
|
status_code = 403
|
|
77
84
|
|
|
78
85
|
|
|
79
|
-
class
|
|
86
|
+
class MissingScopeException(AuthException):
|
|
80
87
|
"""The token does not carry the scopes required for this resource."""
|
|
81
88
|
|
|
82
89
|
error = "insufficient_scope"
|
|
83
90
|
status_code = 403
|
|
84
91
|
|
|
85
92
|
|
|
86
|
-
class ThrottleException(
|
|
93
|
+
class ThrottleException(AuthException):
|
|
87
94
|
"""Too many requests for this action; retry later."""
|
|
88
95
|
|
|
89
96
|
error = "throttled"
|
|
90
97
|
status_code = 429
|
|
91
98
|
|
|
92
99
|
|
|
93
|
-
class
|
|
100
|
+
class InvalidScopeException(AuthException):
|
|
94
101
|
"""The requested scope is unknown or not allowed."""
|
|
95
102
|
|
|
96
103
|
error = "invalid_scope"
|
|
97
104
|
status_code = 400
|
|
98
105
|
|
|
99
106
|
|
|
100
|
-
class
|
|
107
|
+
class InvalidTargetException(AuthException):
|
|
101
108
|
"""The requested resource is unknown or does not match the grant (RFC 8707)."""
|
|
102
109
|
|
|
103
110
|
error = "invalid_target"
|
|
104
111
|
status_code = 400
|
|
105
112
|
|
|
106
113
|
|
|
107
|
-
class
|
|
114
|
+
class UnsupportedResponseTypeException(AuthException):
|
|
108
115
|
"""The authorization endpoint only issues authorization codes."""
|
|
109
116
|
|
|
110
117
|
error = "unsupported_response_type"
|
|
111
118
|
status_code = 400
|
|
112
119
|
|
|
113
120
|
|
|
114
|
-
class
|
|
121
|
+
class AccessDeniedException(AuthException):
|
|
115
122
|
"""The resource owner did not approve the authorization request."""
|
|
116
123
|
|
|
117
124
|
error = "access_denied"
|
|
118
125
|
status_code = 400
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
# Deprecated aliases for the names used before the Exception-suffix rename.
|
|
129
|
+
# Remove them in the next major release.
|
|
130
|
+
AuthError = AuthException
|
|
131
|
+
InvalidRequest = InvalidRequestException
|
|
132
|
+
InvalidClient = InvalidClientException
|
|
133
|
+
InvalidGrant = InvalidGrantException
|
|
134
|
+
UnsupportedGrantType = UnsupportedGrantTypeException
|
|
135
|
+
UnauthorizedClient = UnauthorizedClientException
|
|
136
|
+
InvalidToken = InvalidTokenException
|
|
137
|
+
InvalidSession = AuthenticationException
|
|
138
|
+
CsrfTokenMismatch = CsrfTokenMismatchException
|
|
139
|
+
InsufficientScope = MissingScopeException
|
|
140
|
+
InvalidScope = InvalidScopeException
|
|
141
|
+
InvalidTarget = InvalidTargetException
|
|
142
|
+
UnsupportedResponseType = UnsupportedResponseTypeException
|
|
143
|
+
AccessDenied = AccessDeniedException
|
{fastapi_startkit_auth-0.6.3 → fastapi_startkit_auth-0.7.0}/src/fastapi_startkit_auth/facade.py
RENAMED
|
@@ -6,7 +6,7 @@ from fastapi import Depends, Request
|
|
|
6
6
|
|
|
7
7
|
from .dependencies import _bearer_token, get_auth_manager, resolve_context
|
|
8
8
|
from .concurrency import call, ensure_sync
|
|
9
|
-
from .exceptions import
|
|
9
|
+
from .exceptions import AuthException
|
|
10
10
|
from .guards.session import AsyncSessionGuard, SessionGuard
|
|
11
11
|
from .manager import AuthManager
|
|
12
12
|
from .providers.base import user_is_active, user_is_active_async
|
|
@@ -26,7 +26,7 @@ class Auth:
|
|
|
26
26
|
@api.post("/login")
|
|
27
27
|
def login(payload: Credentials, auth: Auth = Depends(Auth.scoped)):
|
|
28
28
|
if not auth.attempt(payload.model_dump()):
|
|
29
|
-
raise
|
|
29
|
+
raise AuthenticationException("Invalid credentials.")
|
|
30
30
|
return {"ok": True}
|
|
31
31
|
|
|
32
32
|
@api.post("/logout")
|
|
@@ -97,7 +97,7 @@ class Auth:
|
|
|
97
97
|
if token is None:
|
|
98
98
|
return None
|
|
99
99
|
return ensure_sync(resolved.user_from_token(token), "The guard's user_from_token").user
|
|
100
|
-
except
|
|
100
|
+
except AuthException:
|
|
101
101
|
return None
|
|
102
102
|
|
|
103
103
|
@ScopedMethod
|
|
@@ -174,7 +174,7 @@ class AsyncAuth:
|
|
|
174
174
|
async def user(self, guard: str | None = None) -> Any | None:
|
|
175
175
|
try:
|
|
176
176
|
return (await resolve_context(self._request, self._manager, guard)).user
|
|
177
|
-
except
|
|
177
|
+
except AuthException:
|
|
178
178
|
return None
|
|
179
179
|
|
|
180
180
|
@ScopedMethod
|