the37lab-authlib 0.1.1750952155__tar.gz → 0.1.1751357568__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.1750952155 → the37lab_authlib-0.1.1751357568}/PKG-INFO +8 -1
  2. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/README.md +196 -189
  3. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/pyproject.toml +15 -15
  4. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/__init__.py +4 -4
  5. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/auth.py +541 -527
  6. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/db.py +73 -73
  7. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/decorators.py +32 -32
  8. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/exceptions.py +10 -10
  9. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib/models.py +94 -94
  10. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib.egg-info/PKG-INFO +8 -1
  11. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/setup.cfg +0 -0
  12. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib.egg-info/SOURCES.txt +0 -0
  13. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib.egg-info/dependency_links.txt +0 -0
  14. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/src/the37lab_authlib.egg-info/requires.txt +0 -0
  15. {the37lab_authlib-0.1.1750952155 → the37lab_authlib-0.1.1751357568}/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.1750952155
3
+ Version: 0.1.1751357568
4
4
  Summary: Python SDK for the Authlib
5
5
  Author-email: the37lab <info@the37lab.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -54,6 +54,7 @@ from authlib import AuthManager
54
54
 
55
55
  app = Flask(__name__)
56
56
 
57
+ # Option 1: Explicit configuration
57
58
  auth = AuthManager(
58
59
  app=app,
59
60
  db_dsn="postgresql://user:pass@localhost/dbname",
@@ -66,6 +67,11 @@ auth = AuthManager(
66
67
  }
67
68
  )
68
69
 
70
+ # Option 2: Use environment variables with a prefix (e.g., AMPA_)
71
+ # This will load:
72
+ # AMPA_DATABASE_URL, AMPA_JWT_SECRET, AMPA_GOOGLE_CLIENT_ID, AMPA_GOOGLE_CLIENT_SECRET
73
+ # auth = AuthManager(app=app, environment_prefix="AMPA")
74
+
69
75
  @app.route("/protected")
70
76
  @auth.require_auth(roles=["admin"])
71
77
  def protected_route():
@@ -96,6 +102,7 @@ public using the `@auth.public_endpoint` decorator or
96
102
  - `oauth_config`: Dictionary of OAuth provider configurations (see below)
97
103
  - `token_expiry`: JWT token expiry time in seconds (default: 3600)
98
104
  - `refresh_token_expiry`: Refresh token expiry time in seconds (default: 2592000)
105
+ - `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.
99
106
 
100
107
  #### Example `oauth_config`:
101
108
  ```python
@@ -1,189 +1,196 @@
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
-
26
- ## Installation
27
-
28
- ```bash
29
- pip install -e .
30
- ```
31
-
32
- ## Quick Start
33
-
34
- ```python
35
- from flask import Flask
36
- from authlib import AuthManager
37
-
38
- app = Flask(__name__)
39
-
40
- auth = AuthManager(
41
- app=app,
42
- db_dsn="postgresql://user:pass@localhost/dbname",
43
- jwt_secret="your-secret-key",
44
- oauth_config={
45
- "google": {
46
- "client_id": "your-client-id",
47
- "client_secret": "your-client-secret"
48
- }
49
- }
50
- )
51
-
52
- @app.route("/protected")
53
- @auth.require_auth(roles=["admin"])
54
- def protected_route():
55
- return "Protected content"
56
-
57
- @app.route("/public")
58
- @auth.public_endpoint
59
- def custom_public_route():
60
- return "Public content"
61
- ```
62
-
63
- `AuthManager`'s blueprint now registers a global error handler for
64
- `AuthError` and authenticates requests for all of its routes by default.
65
- Authenticated users are made available as `flask.g.requesting_user`.
66
- Only the login, OAuth, token refresh, registration and role listing
67
- endpoints are exempt from this check. Additional routes can be marked as
68
- public using the `@auth.public_endpoint` decorator or
69
- `auth.add_public_endpoint("auth.some_endpoint")`.
70
-
71
- ## Configuration
72
-
73
- ### Required Parameters
74
- - `app`: Flask application instance
75
- - `db_dsn`: PostgreSQL connection string
76
- - `jwt_secret`: Secret key for JWT signing
77
-
78
- ### Optional Parameters
79
- - `oauth_config`: Dictionary of OAuth provider configurations (see below)
80
- - `token_expiry`: JWT token expiry time in seconds (default: 3600)
81
- - `refresh_token_expiry`: Refresh token expiry time in seconds (default: 2592000)
82
-
83
- #### Example `oauth_config`:
84
- ```python
85
- {
86
- "google": {
87
- "client_id": "...",
88
- "client_secret": "..."
89
- },
90
- "github": {
91
- "client_id": "...",
92
- "client_secret": "..."
93
- }
94
- }
95
- ```
96
-
97
- ## API Endpoints
98
-
99
- ### Authentication
100
- - `POST /api/v1/users/login` - Login with username/password
101
- - **Request:** `{ "username": "string", "password": "string" }`
102
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
103
- - `POST /api/v1/users/login/oauth` - Get OAuth redirect URL
104
- - **Request:** `{ "provider": "google|github|..." }`
105
- - **Response:** `{ "redirect_url": "string" }`
106
- - `GET /api/v1/users/login/oauth2callback` - OAuth callback
107
- - **Query Params:** `code`, `state`, `provider`
108
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
109
- - `POST /api/v1/users/token-refresh` - Refresh JWT token
110
- - **Request:** `{ "refresh_token": "jwt" }`
111
- - **Response:** `{ "token": "jwt", "refresh_token": "jwt" }`
112
-
113
- ### User Management
114
- - `POST /api/v1/users/register` - Register new user
115
- - **Request:** `{ "username": "string", "password": "string", "email": "string", ... }`
116
- - **Response:** `{ "user": { ... }, "token": "jwt", "refresh_token": "jwt" }`
117
- - `GET /api/v1/users/login/profile` - Get user profile
118
- - **Auth:** Bearer JWT
119
- - **Response:** `{ "user": { ... } }`
120
- - `GET /api/v1/users/roles` - Get available roles
121
- - **Response:** `[ "admin", "user", ... ]`
122
-
123
- ### API Tokens
124
- - `POST /api/v1/users/{user}/api-tokens` - Create API token
125
- - **Request:** `{ "name": "string", "scopes": [ ... ] }`
126
- - **Response:** `{ "token": "string", "id": "uuid", ... }`
127
- - `GET /api/v1/users/{user}/api-tokens` - List API tokens
128
- - **Response:** `[ { "id": "uuid", "name": "string", ... } ]`
129
- - `DELETE /api/v1/users/{user}/api-tokens/{token_id}` - Delete API token
130
- - **Response:** `{ "success": true }`
131
-
132
- ## Authentication Flow
133
-
134
- 1. **Login:**
135
- - User submits credentials to `/api/v1/users/login`.
136
- - Receives JWT and refresh token.
137
- 2. **Token Refresh:**
138
- - Use `/api/v1/users/token-refresh` with refresh token to get new JWT.
139
- 3. **OAuth:**
140
- - Get redirect URL from `/api/v1/users/login/oauth`.
141
- - Complete OAuth flow via `/api/v1/users/login/oauth2callback`.
142
- 4. **Protected Routes:**
143
- - All routes inside the provided blueprint are authenticated by default.
144
- The authenticated user can be accessed via `g.requesting_user`.
145
- Use `@auth.require_auth()` to protect custom routes in your application.
146
-
147
- ## User Object
148
-
149
- The user object returned by the API typically includes:
150
- ```json
151
- {
152
- "id": "uuid",
153
- "username": "string",
154
- "email": "string",
155
- "roles": ["user", "admin"],
156
- "created_at": "timestamp",
157
- "last_login": "timestamp"
158
- }
159
- ```
160
-
161
- ## Token Management
162
- - **JWT:** Used for authenticating API requests. Include in `Authorization: Bearer <token>` header.
163
- - **Refresh Token:** Used to obtain new JWTs without re-authenticating.
164
- - **API Tokens:** Long-lived tokens for programmatic access, managed per user.
165
-
166
- ## Development
167
-
168
- ### Setup
169
- 1. Clone the repository
170
- 2. Create virtual environment:
171
- ```bash
172
- python -m venv venv
173
- venv\Scripts\activate
174
- ```
175
- 3. Install dependencies:
176
- ```bash
177
- pip install -e ".[dev]"
178
- ```
179
-
180
- ### Database Setup
181
- ```bash
182
- createdb authlib
183
- python -m authlib.cli db init
184
- ```
185
-
186
- ### Running Tests
187
- ```bash
188
- pytest
189
- ```
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
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ pip install -e .
30
+ ```
31
+
32
+ ## Quick Start
33
+
34
+ ```python
35
+ from flask import Flask
36
+ from authlib import AuthManager
37
+
38
+ app = Flask(__name__)
39
+
40
+ # Option 1: Explicit configuration
41
+ auth = AuthManager(
42
+ app=app,
43
+ db_dsn="postgresql://user:pass@localhost/dbname",
44
+ jwt_secret="your-secret-key",
45
+ oauth_config={
46
+ "google": {
47
+ "client_id": "your-client-id",
48
+ "client_secret": "your-client-secret"
49
+ }
50
+ }
51
+ )
52
+
53
+ # Option 2: Use environment variables with a prefix (e.g., AMPA_)
54
+ # This will load:
55
+ # AMPA_DATABASE_URL, AMPA_JWT_SECRET, AMPA_GOOGLE_CLIENT_ID, AMPA_GOOGLE_CLIENT_SECRET
56
+ # auth = AuthManager(app=app, environment_prefix="AMPA")
57
+
58
+ @app.route("/protected")
59
+ @auth.require_auth(roles=["admin"])
60
+ def protected_route():
61
+ return "Protected content"
62
+
63
+ @app.route("/public")
64
+ @auth.public_endpoint
65
+ def custom_public_route():
66
+ return "Public content"
67
+ ```
68
+
69
+ `AuthManager`'s blueprint now registers a global error handler for
70
+ `AuthError` and authenticates requests for all of its routes by default.
71
+ Authenticated users are made available as `flask.g.requesting_user`.
72
+ Only the login, OAuth, token refresh, registration and role listing
73
+ endpoints are exempt from this check. Additional routes can be marked as
74
+ public using the `@auth.public_endpoint` decorator or
75
+ `auth.add_public_endpoint("auth.some_endpoint")`.
76
+
77
+ ## Configuration
78
+
79
+ ### Required Parameters
80
+ - `app`: Flask application instance
81
+ - `db_dsn`: PostgreSQL connection string
82
+ - `jwt_secret`: Secret key for JWT signing
83
+
84
+ ### Optional Parameters
85
+ - `oauth_config`: Dictionary of OAuth provider configurations (see below)
86
+ - `token_expiry`: JWT token expiry time in seconds (default: 3600)
87
+ - `refresh_token_expiry`: Refresh token expiry time in seconds (default: 2592000)
88
+ - `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.
89
+
90
+ #### Example `oauth_config`:
91
+ ```python
92
+ {
93
+ "google": {
94
+ "client_id": "...",
95
+ "client_secret": "..."
96
+ },
97
+ "github": {
98
+ "client_id": "...",
99
+ "client_secret": "..."
100
+ }
101
+ }
102
+ ```
103
+
104
+ ## API Endpoints
105
+
106
+ ### Authentication
107
+ - `POST /api/v1/users/login` - Login with username/password
108
+ - **Request:** `{ "username": "string", "password": "string" }`
109
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
110
+ - `POST /api/v1/users/login/oauth` - Get OAuth redirect URL
111
+ - **Request:** `{ "provider": "google|github|..." }`
112
+ - **Response:** `{ "redirect_url": "string" }`
113
+ - `GET /api/v1/users/login/oauth2callback` - OAuth callback
114
+ - **Query Params:** `code`, `state`, `provider`
115
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt", "user": { ... } }`
116
+ - `POST /api/v1/users/token-refresh` - Refresh JWT token
117
+ - **Request:** `{ "refresh_token": "jwt" }`
118
+ - **Response:** `{ "token": "jwt", "refresh_token": "jwt" }`
119
+
120
+ ### User Management
121
+ - `POST /api/v1/users/register` - Register new user
122
+ - **Request:** `{ "username": "string", "password": "string", "email": "string", ... }`
123
+ - **Response:** `{ "user": { ... }, "token": "jwt", "refresh_token": "jwt" }`
124
+ - `GET /api/v1/users/login/profile` - Get user profile
125
+ - **Auth:** Bearer JWT
126
+ - **Response:** `{ "user": { ... } }`
127
+ - `GET /api/v1/users/roles` - Get available roles
128
+ - **Response:** `[ "admin", "user", ... ]`
129
+
130
+ ### API Tokens
131
+ - `POST /api/v1/users/{user}/api-tokens` - Create API token
132
+ - **Request:** `{ "name": "string", "scopes": [ ... ] }`
133
+ - **Response:** `{ "token": "string", "id": "uuid", ... }`
134
+ - `GET /api/v1/users/{user}/api-tokens` - List API tokens
135
+ - **Response:** `[ { "id": "uuid", "name": "string", ... } ]`
136
+ - `DELETE /api/v1/users/{user}/api-tokens/{token_id}` - Delete API token
137
+ - **Response:** `{ "success": true }`
138
+
139
+ ## Authentication Flow
140
+
141
+ 1. **Login:**
142
+ - User submits credentials to `/api/v1/users/login`.
143
+ - Receives JWT and refresh token.
144
+ 2. **Token Refresh:**
145
+ - Use `/api/v1/users/token-refresh` with refresh token to get new JWT.
146
+ 3. **OAuth:**
147
+ - Get redirect URL from `/api/v1/users/login/oauth`.
148
+ - Complete OAuth flow via `/api/v1/users/login/oauth2callback`.
149
+ 4. **Protected Routes:**
150
+ - All routes inside the provided blueprint are authenticated by default.
151
+ The authenticated user can be accessed via `g.requesting_user`.
152
+ Use `@auth.require_auth()` to protect custom routes in your application.
153
+
154
+ ## User Object
155
+
156
+ The user object returned by the API typically includes:
157
+ ```json
158
+ {
159
+ "id": "uuid",
160
+ "username": "string",
161
+ "email": "string",
162
+ "roles": ["user", "admin"],
163
+ "created_at": "timestamp",
164
+ "last_login": "timestamp"
165
+ }
166
+ ```
167
+
168
+ ## Token Management
169
+ - **JWT:** Used for authenticating API requests. Include in `Authorization: Bearer <token>` header.
170
+ - **Refresh Token:** Used to obtain new JWTs without re-authenticating.
171
+ - **API Tokens:** Long-lived tokens for programmatic access, managed per user.
172
+
173
+ ## Development
174
+
175
+ ### Setup
176
+ 1. Clone the repository
177
+ 2. Create virtual environment:
178
+ ```bash
179
+ python -m venv venv
180
+ venv\Scripts\activate
181
+ ```
182
+ 3. Install dependencies:
183
+ ```bash
184
+ pip install -e ".[dev]"
185
+ ```
186
+
187
+ ### Database Setup
188
+ ```bash
189
+ createdb authlib
190
+ python -m authlib.cli db init
191
+ ```
192
+
193
+ ### Running Tests
194
+ ```bash
195
+ pytest
196
+ ```
@@ -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.1750952155"
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"]
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.1751357568"
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"]
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"]