the37lab-authlib 0.1.1756740066__tar.gz → 0.1.1758263039__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.

Potentially problematic release.


This version of the37lab-authlib might be problematic. Click here for more details.

Files changed (15) hide show
  1. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/PKG-INFO +1 -1
  2. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/README.md +233 -233
  3. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/pyproject.toml +15 -15
  4. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/__init__.py +4 -4
  5. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/auth.py +1148 -854
  6. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/db.py +90 -90
  7. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/decorators.py +32 -32
  8. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/exceptions.py +10 -10
  9. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib/models.py +94 -94
  10. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib.egg-info/PKG-INFO +1 -1
  11. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/setup.cfg +0 -0
  12. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib.egg-info/SOURCES.txt +0 -0
  13. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib.egg-info/dependency_links.txt +0 -0
  14. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib.egg-info/requires.txt +0 -0
  15. {the37lab_authlib-0.1.1756740066 → the37lab_authlib-0.1.1758263039}/src/the37lab_authlib.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: the37lab_authlib
3
- Version: 0.1.1756740066
3
+ Version: 0.1.1758263039
4
4
  Summary: Python SDK for the Authlib
5
5
  Author-email: the37lab <info@the37lab.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,233 +1,233 @@
1
- # AuthLib
2
-
3
- A Python authentication library that provides JWT, OAuth2, and API token authentication with PostgreSQL backend. This library is designed for seamless integration with Flask applications and provides a robust set of endpoints and utilities for user management, authentication, and API token handling.
4
-
5
- ## Table of Contents
6
- - [AuthLib](#authlib)
7
- - [Table of Contents](#table-of-contents)
8
- - [Installation](#installation)
9
- - [Quick Start](#quick-start)
10
- - [Configuration](#configuration)
11
- - [Required Parameters](#required-parameters)
12
- - [Optional Parameters](#optional-parameters)
13
- - [Example `oauth_config`:](#example-oauth_config)
14
- - [API Endpoints](#api-endpoints)
15
- - [Authentication](#authentication)
16
- - [User Management](#user-management)
17
- - [API Tokens](#api-tokens)
18
- - [Authentication Flow](#authentication-flow)
19
- - [User Object](#user-object)
20
- - [Token Management](#token-management)
21
- - [Development](#development)
22
- - [Setup](#setup)
23
- - [Database Setup](#database-setup)
24
- - [Running Tests](#running-tests)
25
- - [API Token Override for Testing](#api-token-override-for-testing)
26
- - [Usage](#usage)
27
- - [Warning](#warning)
28
- - [User Override for Testing](#user-override-for-testing)
29
- - [Usage](#usage-1)
30
- - [Warning](#warning-1)
31
-
32
- ## Installation
33
-
34
- ```bash
35
- pip install -e .
36
- ```
37
-
38
- ## Quick Start
39
-
40
- ```python
41
- from flask import Flask
42
- from authlib import AuthManager
43
-
44
- app = Flask(__name__)
45
-
46
- # Option 1: Explicit configuration
47
- auth = AuthManager(
48
- app=app,
49
- db_dsn="postgresql://user:pass@localhost/dbname",
50
- jwt_secret="your-secret-key",
51
- oauth_config={
52
- "google": {
53
- "client_id": "your-client-id",
54
- "client_secret": "your-client-secret"
55
- }
56
- }
57
- )
58
-
59
- # Option 2: Use environment variables with a prefix (e.g., AMPA_)
60
- # This will load:
61
- # AMPA_DATABASE_URL, AMPA_JWT_SECRET, AMPA_GOOGLE_CLIENT_ID, AMPA_GOOGLE_CLIENT_SECRET
62
- # auth = AuthManager(app=app, environment_prefix="AMPA")
63
-
64
- @app.route("/protected")
65
- @auth.require_auth(roles=["admin"])
66
- def protected_route():
67
- return "Protected content"
68
-
69
- @app.route("/public")
70
- @auth.public_endpoint
71
- def custom_public_route():
72
- return "Public content"
73
- ```
74
-
75
- `AuthManager`'s blueprint now registers a global error handler for
76
- `AuthError` and authenticates requests for all of its routes by default.
77
- Authenticated users are made available as `flask.g.requesting_user`.
78
- Only the login, OAuth, token refresh, registration and role listing
79
- endpoints are exempt from this check. Additional routes can be marked as
80
- public using the `@auth.public_endpoint` decorator or
81
- `auth.add_public_endpoint("auth.some_endpoint")`.
82
-
83
- ## Configuration
84
-
85
- ### Required Parameters
86
- - `app`: Flask application instance
87
- - `db_dsn`: PostgreSQL connection string
88
- - `jwt_secret`: Secret key for JWT signing
89
-
90
- ### Optional Parameters
91
- - `oauth_config`: Dictionary of OAuth provider configurations (see below)
92
- - `token_expiry`: JWT token expiry time in seconds (default: 3600)
93
- - `refresh_token_expiry`: Refresh token expiry time in seconds (default: 2592000)
94
- - `environment_prefix`: If set, loads all configuration from environment variables with this prefix (e.g., `AMPA_DATABASE_URL`, `AMPA_JWT_SECRET`, `AMPA_GOOGLE_CLIENT_ID`, `AMPA_GOOGLE_CLIENT_SECRET`). Overrides other config if set.
95
-
96
- #### Example `oauth_config`:
97
- ```python
98
- {
99
- "google": {
100
- "client_id": "...",
101
- "client_secret": "..."
102
- },
103
- "github": {
104
- "client_id": "...",
105
- "client_secret": "..."
106
- }
107
- }
108
- ```
109
-
110
- ## API Endpoints
111
-
112
- ### Authentication
113
- - `POST /api/v1/users/login` - Login with username/password
114
- - **Request:** `{ "username": "string", "password": "string" }`
115
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
116
- - `POST /api/v1/users/login/oauth` - Get OAuth redirect URL
117
- - **Request:** `{ "provider": "google|github|..." }`
118
- - **Response:** `{ "redirect_url": "string" }`
119
- - `GET /api/v1/users/login/oauth2callback` - OAuth callback
120
- - **Query Params:** `code`, `state`, `provider`
121
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
122
- - `POST /api/v1/users/token-refresh` - Refresh JWT token
123
- - **Request:** `{ "refresh_token": "jwt" }`
124
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt" }`
125
-
126
- ### User Management
127
- - `POST /api/v1/users/register` - Register new user
128
- - **Request:** `{ "username": "string", "password": "string", "email": "string", ... }`
129
- - **Response:** `{ "user": { ... }, "token": "jwt", "refresh_token": "jwt" }`
130
- - `GET /api/v1/users/login/profile` - Get user profile
131
- - **Auth:** Bearer JWT
132
- - **Response:** `{ "user": { ... } }`
133
- - `GET /api/v1/users/roles` - Get available roles
134
- - **Response:** `[ "admin", "user", ... ]`
135
-
136
- ### API Tokens
137
- - `POST /api/v1/users/{user}/api-tokens` - Create API token
138
- - **Request:** `{ "name": "string", "scopes": [ ... ] }`
139
- - **Response:** `{ "token": "string", "id": "uuid", ... }`
140
- - `GET /api/v1/users/{user}/api-tokens` - List API tokens
141
- - **Response:** `[ { "id": "uuid", "name": "string", ... } ]`
142
- - `DELETE /api/v1/users/{user}/api-tokens/{token_id}` - Delete API token
143
- - **Response:** `{ "success": true }`
144
-
145
- ## Authentication Flow
146
-
147
- 1. **Login:**
148
- - User submits credentials to `/api/v1/users/login`.
149
- - Receives JWT and refresh token.
150
- 2. **Token Refresh:**
151
- - Use `/api/v1/users/token-refresh` with refresh token to get new JWT.
152
- 3. **OAuth:**
153
- - Get redirect URL from `/api/v1/users/login/oauth`.
154
- - Complete OAuth flow via `/api/v1/users/login/oauth2callback`.
155
- 4. **Protected Routes:**
156
- - All routes inside the provided blueprint are authenticated by default.
157
- The authenticated user can be accessed via `g.requesting_user`.
158
- Use `@auth.require_auth()` to protect custom routes in your application.
159
-
160
- ## User Object
161
-
162
- The user object returned by the API typically includes:
163
- ```json
164
- {
165
- "id": "uuid",
166
- "username": "string",
167
- "email": "string",
168
- "roles": ["user", "admin"],
169
- "created_at": "timestamp",
170
- "last_login": "timestamp"
171
- }
172
- ```
173
-
174
- ## Token Management
175
- - **JWT:** Used for authenticating API requests. Include in `Authorization: Bearer <token>` header.
176
- - **Refresh Token:** Used to obtain new JWTs without re-authenticating.
177
- - **API Tokens:** Long-lived tokens for programmatic access, managed per user.
178
-
179
- ## Development
180
-
181
- ### Setup
182
- 1. Clone the repository
183
- 2. Create virtual environment:
184
- ```bash
185
- python -m venv venv
186
- venv\Scripts\activate
187
- ```
188
- 3. Install dependencies:
189
- ```bash
190
- pip install -e ".[dev]"
191
- ```
192
-
193
- ### Database Setup
194
- ```bash
195
- createdb authlib
196
- python -m authlib.cli db init
197
- ```
198
-
199
- ### Running Tests
200
- ```bash
201
- pytest
202
- ```
203
-
204
- ## API Token Override for Testing
205
-
206
- For testing purposes, you can bypass the database and provide a static mapping of API tokens to usernames using the `api_tokens` argument to `AuthManager` or the `{PREFIX}API_TOKENS` environment variable.
207
-
208
- ### Usage
209
-
210
- - **Constructor argument:**
211
- ```python
212
- AuthManager(api_tokens={"token1": "user1", "token2": "user2"})
213
- ```
214
- - **Environment variable:**
215
- Set `{PREFIX}API_TOKENS` to a comma-separated list of `token:username` pairs, e.g.:
216
- ```
217
- export MYAPP_API_TOKENS="token1:user1,token2:user2"
218
- ```
219
- Replace `MYAPP` with your environment prefix.
220
-
221
- **Warning:** This method is intended only for testing and development. Do not use this approach in production environments.
222
-
223
- ## User Override for Testing
224
-
225
- For testing purposes, you can force all authentication to return a specific user by setting the `{PREFIX}USER_OVERRIDE` environment variable:
226
-
227
- ```bash
228
- export MYAPP_USER_OVERRIDE="testuser"
229
- ```
230
-
231
- If set, all requests will be authenticated as the specified user, regardless of any tokens or credentials provided. This cannot be combined with `api_tokens` or `db_dsn`.
232
-
233
- **Warning:** This method is intended only for testing and development. Do not use this approach in production environments.
1
+ # AuthLib
2
+
3
+ A Python authentication library that provides JWT, OAuth2, and API token authentication with PostgreSQL backend. This library is designed for seamless integration with Flask applications and provides a robust set of endpoints and utilities for user management, authentication, and API token handling.
4
+
5
+ ## Table of Contents
6
+ - [AuthLib](#authlib)
7
+ - [Table of Contents](#table-of-contents)
8
+ - [Installation](#installation)
9
+ - [Quick Start](#quick-start)
10
+ - [Configuration](#configuration)
11
+ - [Required Parameters](#required-parameters)
12
+ - [Optional Parameters](#optional-parameters)
13
+ - [Example `oauth_config`:](#example-oauth_config)
14
+ - [API Endpoints](#api-endpoints)
15
+ - [Authentication](#authentication)
16
+ - [User Management](#user-management)
17
+ - [API Tokens](#api-tokens)
18
+ - [Authentication Flow](#authentication-flow)
19
+ - [User Object](#user-object)
20
+ - [Token Management](#token-management)
21
+ - [Development](#development)
22
+ - [Setup](#setup)
23
+ - [Database Setup](#database-setup)
24
+ - [Running Tests](#running-tests)
25
+ - [API Token Override for Testing](#api-token-override-for-testing)
26
+ - [Usage](#usage)
27
+ - [Warning](#warning)
28
+ - [User Override for Testing](#user-override-for-testing)
29
+ - [Usage](#usage-1)
30
+ - [Warning](#warning-1)
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ pip install -e .
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ```python
41
+ from flask import Flask
42
+ from authlib import AuthManager
43
+
44
+ app = Flask(__name__)
45
+
46
+ # Option 1: Explicit configuration
47
+ auth = AuthManager(
48
+ app=app,
49
+ db_dsn="postgresql://user:pass@localhost/dbname",
50
+ jwt_secret="your-secret-key",
51
+ oauth_config={
52
+ "google": {
53
+ "client_id": "your-client-id",
54
+ "client_secret": "your-client-secret"
55
+ }
56
+ }
57
+ )
58
+
59
+ # Option 2: Use environment variables with a prefix (e.g., AMPA_)
60
+ # This will load:
61
+ # AMPA_DATABASE_URL, AMPA_JWT_SECRET, AMPA_GOOGLE_CLIENT_ID, AMPA_GOOGLE_CLIENT_SECRET
62
+ # auth = AuthManager(app=app, environment_prefix="AMPA")
63
+
64
+ @app.route("/protected")
65
+ @auth.require_auth(roles=["admin"])
66
+ def protected_route():
67
+ return "Protected content"
68
+
69
+ @app.route("/public")
70
+ @auth.public_endpoint
71
+ def custom_public_route():
72
+ return "Public content"
73
+ ```
74
+
75
+ `AuthManager`'s blueprint now registers a global error handler for
76
+ `AuthError` and authenticates requests for all of its routes by default.
77
+ Authenticated users are made available as `flask.g.requesting_user`.
78
+ Only the login, OAuth, token refresh, registration and role listing
79
+ endpoints are exempt from this check. Additional routes can be marked as
80
+ public using the `@auth.public_endpoint` decorator or
81
+ `auth.add_public_endpoint("auth.some_endpoint")`.
82
+
83
+ ## Configuration
84
+
85
+ ### Required Parameters
86
+ - `app`: Flask application instance
87
+ - `db_dsn`: PostgreSQL connection string
88
+ - `jwt_secret`: Secret key for JWT signing
89
+
90
+ ### Optional Parameters
91
+ - `oauth_config`: Dictionary of OAuth provider configurations (see below)
92
+ - `token_expiry`: JWT token expiry time in seconds (default: 3600)
93
+ - `refresh_token_expiry`: Refresh token expiry time in seconds (default: 2592000)
94
+ - `environment_prefix`: If set, loads all configuration from environment variables with this prefix (e.g., `AMPA_DATABASE_URL`, `AMPA_JWT_SECRET`, `AMPA_GOOGLE_CLIENT_ID`, `AMPA_GOOGLE_CLIENT_SECRET`). Overrides other config if set.
95
+
96
+ #### Example `oauth_config`:
97
+ ```python
98
+ {
99
+ "google": {
100
+ "client_id": "...",
101
+ "client_secret": "..."
102
+ },
103
+ "github": {
104
+ "client_id": "...",
105
+ "client_secret": "..."
106
+ }
107
+ }
108
+ ```
109
+
110
+ ## API Endpoints
111
+
112
+ ### Authentication
113
+ - `POST /api/v1/users/login` - Login with username/password
114
+ - **Request:** `{ "username": "string", "password": "string" }`
115
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
116
+ - `POST /api/v1/users/login/oauth` - Get OAuth redirect URL
117
+ - **Request:** `{ "provider": "google|github|..." }`
118
+ - **Response:** `{ "redirect_url": "string" }`
119
+ - `GET /api/v1/users/login/oauth2callback` - OAuth callback
120
+ - **Query Params:** `code`, `state`, `provider`
121
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
122
+ - `POST /api/v1/users/token-refresh` - Refresh JWT token
123
+ - **Request:** `{ "refresh_token": "jwt" }`
124
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt" }`
125
+
126
+ ### User Management
127
+ - `POST /api/v1/users/register` - Register new user
128
+ - **Request:** `{ "username": "string", "password": "string", "email": "string", ... }`
129
+ - **Response:** `{ "user": { ... }, "token": "jwt", "refresh_token": "jwt" }`
130
+ - `GET /api/v1/users/login/profile` - Get user profile
131
+ - **Auth:** Bearer JWT
132
+ - **Response:** `{ "user": { ... } }`
133
+ - `GET /api/v1/users/roles` - Get available roles
134
+ - **Response:** `[ "admin", "user", ... ]`
135
+
136
+ ### API Tokens
137
+ - `POST /api/v1/users/{user}/api-tokens` - Create API token
138
+ - **Request:** `{ "name": "string", "scopes": [ ... ] }`
139
+ - **Response:** `{ "token": "string", "id": "uuid", ... }`
140
+ - `GET /api/v1/users/{user}/api-tokens` - List API tokens
141
+ - **Response:** `[ { "id": "uuid", "name": "string", ... } ]`
142
+ - `DELETE /api/v1/users/{user}/api-tokens/{token_id}` - Delete API token
143
+ - **Response:** `{ "success": true }`
144
+
145
+ ## Authentication Flow
146
+
147
+ 1. **Login:**
148
+ - User submits credentials to `/api/v1/users/login`.
149
+ - Receives JWT and refresh token.
150
+ 2. **Token Refresh:**
151
+ - Use `/api/v1/users/token-refresh` with refresh token to get new JWT.
152
+ 3. **OAuth:**
153
+ - Get redirect URL from `/api/v1/users/login/oauth`.
154
+ - Complete OAuth flow via `/api/v1/users/login/oauth2callback`.
155
+ 4. **Protected Routes:**
156
+ - All routes inside the provided blueprint are authenticated by default.
157
+ The authenticated user can be accessed via `g.requesting_user`.
158
+ Use `@auth.require_auth()` to protect custom routes in your application.
159
+
160
+ ## User Object
161
+
162
+ The user object returned by the API typically includes:
163
+ ```json
164
+ {
165
+ "id": "uuid",
166
+ "username": "string",
167
+ "email": "string",
168
+ "roles": ["user", "admin"],
169
+ "created_at": "timestamp",
170
+ "last_login": "timestamp"
171
+ }
172
+ ```
173
+
174
+ ## Token Management
175
+ - **JWT:** Used for authenticating API requests. Include in `Authorization: Bearer <token>` header.
176
+ - **Refresh Token:** Used to obtain new JWTs without re-authenticating.
177
+ - **API Tokens:** Long-lived tokens for programmatic access, managed per user.
178
+
179
+ ## Development
180
+
181
+ ### Setup
182
+ 1. Clone the repository
183
+ 2. Create virtual environment:
184
+ ```bash
185
+ python -m venv venv
186
+ venv\Scripts\activate
187
+ ```
188
+ 3. Install dependencies:
189
+ ```bash
190
+ pip install -e ".[dev]"
191
+ ```
192
+
193
+ ### Database Setup
194
+ ```bash
195
+ createdb authlib
196
+ python -m authlib.cli db init
197
+ ```
198
+
199
+ ### Running Tests
200
+ ```bash
201
+ pytest
202
+ ```
203
+
204
+ ## API Token Override for Testing
205
+
206
+ For testing purposes, you can bypass the database and provide a static mapping of API tokens to usernames using the `api_tokens` argument to `AuthManager` or the `{PREFIX}API_TOKENS` environment variable.
207
+
208
+ ### Usage
209
+
210
+ - **Constructor argument:**
211
+ ```python
212
+ AuthManager(api_tokens={"token1": "user1", "token2": "user2"})
213
+ ```
214
+ - **Environment variable:**
215
+ Set `{PREFIX}API_TOKENS` to a comma-separated list of `token:username` pairs, e.g.:
216
+ ```
217
+ export MYAPP_API_TOKENS="token1:user1,token2:user2"
218
+ ```
219
+ Replace `MYAPP` with your environment prefix.
220
+
221
+ **Warning:** This method is intended only for testing and development. Do not use this approach in production environments.
222
+
223
+ ## User Override for Testing
224
+
225
+ For testing purposes, you can force all authentication to return a specific user by setting the `{PREFIX}USER_OVERRIDE` environment variable:
226
+
227
+ ```bash
228
+ export MYAPP_USER_OVERRIDE="testuser"
229
+ ```
230
+
231
+ If set, all requests will be authenticated as the specified user, regardless of any tokens or credentials provided. This cannot be combined with `api_tokens` or `db_dsn`.
232
+
233
+ **Warning:** This method is intended only for testing and development. Do not use this approach in production environments.
@@ -1,16 +1,16 @@
1
- [build-system]
2
- requires = ["setuptools", "wheel"]
3
- build-backend = "setuptools.build_meta"
4
-
5
- [project]
6
- name = "the37lab_authlib"
7
- version = "0.1.1756740066"
8
- description = "Python SDK for the Authlib"
9
- authors = [{name = "the37lab", email = "info@the37lab.com"}]
10
- dependencies = ["flask", "psycopg2-binary", "pyjwt", "python-dotenv", "requests", "authlib", "bcrypt", "msal"]
11
- requires-python = ">=3.9"
12
- readme = "README.md"
13
- classifiers = [
14
- "Programming Language :: Python :: 3",
15
- "Operating System :: OS Independent",
1
+ [build-system]
2
+ requires = ["setuptools", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "the37lab_authlib"
7
+ version = "0.1.1758263039"
8
+ description = "Python SDK for the Authlib"
9
+ authors = [{name = "the37lab", email = "info@the37lab.com"}]
10
+ dependencies = ["flask", "psycopg2-binary", "pyjwt", "python-dotenv", "requests", "authlib", "bcrypt", "msal"]
11
+ requires-python = ">=3.9"
12
+ readme = "README.md"
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
16
  ]
@@ -1,5 +1,5 @@
1
- from .auth import AuthManager
2
- from .decorators import require_auth
3
-
4
- __version__ = "0.1.0"
1
+ from .auth import AuthManager
2
+ from .decorators import require_auth
3
+
4
+ __version__ = "0.1.0"
5
5
  __all__ = ["AuthManager", "require_auth"]