agios-auth-verify 1.0.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.
- agios_auth_verify-1.0.0/PKG-INFO +61 -0
- agios_auth_verify-1.0.0/README.md +49 -0
- agios_auth_verify-1.0.0/pyproject.toml +22 -0
- agios_auth_verify-1.0.0/setup.cfg +4 -0
- agios_auth_verify-1.0.0/src/agios_auth_verify.egg-info/PKG-INFO +61 -0
- agios_auth_verify-1.0.0/src/agios_auth_verify.egg-info/SOURCES.txt +9 -0
- agios_auth_verify-1.0.0/src/agios_auth_verify.egg-info/dependency_links.txt +1 -0
- agios_auth_verify-1.0.0/src/agios_auth_verify.egg-info/requires.txt +2 -0
- agios_auth_verify-1.0.0/src/agios_auth_verify.egg-info/top_level.txt +1 -0
- agios_auth_verify-1.0.0/src/auth_verify/__init__.py +4 -0
- agios_auth_verify-1.0.0/src/auth_verify/authorize.py +48 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agios-auth-verify
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: FastAPI dependency that verifies a user's RBAC permission against the auth-service
|
|
5
|
+
License-Expression: ISC
|
|
6
|
+
Project-URL: Repository, https://github.com/AGIOS-AI-RT/auth-verify-python
|
|
7
|
+
Keywords: fastapi,rbac,authorization,permissions,auth,middleware
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: fastapi>=0.100
|
|
11
|
+
Requires-Dist: httpx>=0.24
|
|
12
|
+
|
|
13
|
+
# agios-auth-verify
|
|
14
|
+
|
|
15
|
+
FastAPI dependency that verifies a user's RBAC permission by calling
|
|
16
|
+
`POST {AUTH_SERVICE_URL}/api/auth/check-permission`.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install agios-auth-verify
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires `fastapi` and `httpx`. Set `AUTH_SERVICE_URL` in the environment
|
|
25
|
+
(e.g. `http://127.0.0.1:8000`).
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from fastapi import Depends, FastAPI
|
|
31
|
+
from auth_verify import authorize
|
|
32
|
+
|
|
33
|
+
app = FastAPI()
|
|
34
|
+
|
|
35
|
+
# An upstream middleware must set `request.state.user`
|
|
36
|
+
# (a dict or object with `userId`, optionally `tenantId`).
|
|
37
|
+
|
|
38
|
+
@app.delete("/users/{user_id}", dependencies=[Depends(authorize("users:delete"))])
|
|
39
|
+
async def delete_user(user_id: str):
|
|
40
|
+
return {"ok": True}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The request forwards the incoming `Authorization` header and a `tenant-id`
|
|
44
|
+
header (`user["tenantId"]`, falling back to the request's `tenant-id` header)
|
|
45
|
+
to the auth-service, and sends `{"userId": ..., "permissionKey": ...}` as the body.
|
|
46
|
+
|
|
47
|
+
## Responses
|
|
48
|
+
|
|
49
|
+
Raises `fastapi.HTTPException` with body `{"success": false, "message": ...}`:
|
|
50
|
+
|
|
51
|
+
| Status | When |
|
|
52
|
+
| ------ | ----------------------------------------------------------- |
|
|
53
|
+
| `401` | No authenticated user, or the auth-service returns 401 |
|
|
54
|
+
| `403` | The auth-service responds with `allowed: false` |
|
|
55
|
+
| `503` | The auth-service is unreachable or errors |
|
|
56
|
+
|
|
57
|
+
## Build
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m build
|
|
61
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# agios-auth-verify
|
|
2
|
+
|
|
3
|
+
FastAPI dependency that verifies a user's RBAC permission by calling
|
|
4
|
+
`POST {AUTH_SERVICE_URL}/api/auth/check-permission`.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install agios-auth-verify
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Requires `fastapi` and `httpx`. Set `AUTH_SERVICE_URL` in the environment
|
|
13
|
+
(e.g. `http://127.0.0.1:8000`).
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from fastapi import Depends, FastAPI
|
|
19
|
+
from auth_verify import authorize
|
|
20
|
+
|
|
21
|
+
app = FastAPI()
|
|
22
|
+
|
|
23
|
+
# An upstream middleware must set `request.state.user`
|
|
24
|
+
# (a dict or object with `userId`, optionally `tenantId`).
|
|
25
|
+
|
|
26
|
+
@app.delete("/users/{user_id}", dependencies=[Depends(authorize("users:delete"))])
|
|
27
|
+
async def delete_user(user_id: str):
|
|
28
|
+
return {"ok": True}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The request forwards the incoming `Authorization` header and a `tenant-id`
|
|
32
|
+
header (`user["tenantId"]`, falling back to the request's `tenant-id` header)
|
|
33
|
+
to the auth-service, and sends `{"userId": ..., "permissionKey": ...}` as the body.
|
|
34
|
+
|
|
35
|
+
## Responses
|
|
36
|
+
|
|
37
|
+
Raises `fastapi.HTTPException` with body `{"success": false, "message": ...}`:
|
|
38
|
+
|
|
39
|
+
| Status | When |
|
|
40
|
+
| ------ | ----------------------------------------------------------- |
|
|
41
|
+
| `401` | No authenticated user, or the auth-service returns 401 |
|
|
42
|
+
| `403` | The auth-service responds with `allowed: false` |
|
|
43
|
+
| `503` | The auth-service is unreachable or errors |
|
|
44
|
+
|
|
45
|
+
## Build
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m build
|
|
49
|
+
```
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agios-auth-verify"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "FastAPI dependency that verifies a user's RBAC permission against the auth-service"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "ISC"
|
|
12
|
+
keywords = ["fastapi", "rbac", "authorization", "permissions", "auth", "middleware"]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"fastapi>=0.100",
|
|
15
|
+
"httpx>=0.24",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Repository = "https://github.com/AGIOS-AI-RT/auth-verify-python"
|
|
20
|
+
|
|
21
|
+
[tool.setuptools.packages.find]
|
|
22
|
+
where = ["src"]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agios-auth-verify
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: FastAPI dependency that verifies a user's RBAC permission against the auth-service
|
|
5
|
+
License-Expression: ISC
|
|
6
|
+
Project-URL: Repository, https://github.com/AGIOS-AI-RT/auth-verify-python
|
|
7
|
+
Keywords: fastapi,rbac,authorization,permissions,auth,middleware
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: fastapi>=0.100
|
|
11
|
+
Requires-Dist: httpx>=0.24
|
|
12
|
+
|
|
13
|
+
# agios-auth-verify
|
|
14
|
+
|
|
15
|
+
FastAPI dependency that verifies a user's RBAC permission by calling
|
|
16
|
+
`POST {AUTH_SERVICE_URL}/api/auth/check-permission`.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install agios-auth-verify
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires `fastapi` and `httpx`. Set `AUTH_SERVICE_URL` in the environment
|
|
25
|
+
(e.g. `http://127.0.0.1:8000`).
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from fastapi import Depends, FastAPI
|
|
31
|
+
from auth_verify import authorize
|
|
32
|
+
|
|
33
|
+
app = FastAPI()
|
|
34
|
+
|
|
35
|
+
# An upstream middleware must set `request.state.user`
|
|
36
|
+
# (a dict or object with `userId`, optionally `tenantId`).
|
|
37
|
+
|
|
38
|
+
@app.delete("/users/{user_id}", dependencies=[Depends(authorize("users:delete"))])
|
|
39
|
+
async def delete_user(user_id: str):
|
|
40
|
+
return {"ok": True}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The request forwards the incoming `Authorization` header and a `tenant-id`
|
|
44
|
+
header (`user["tenantId"]`, falling back to the request's `tenant-id` header)
|
|
45
|
+
to the auth-service, and sends `{"userId": ..., "permissionKey": ...}` as the body.
|
|
46
|
+
|
|
47
|
+
## Responses
|
|
48
|
+
|
|
49
|
+
Raises `fastapi.HTTPException` with body `{"success": false, "message": ...}`:
|
|
50
|
+
|
|
51
|
+
| Status | When |
|
|
52
|
+
| ------ | ----------------------------------------------------------- |
|
|
53
|
+
| `401` | No authenticated user, or the auth-service returns 401 |
|
|
54
|
+
| `403` | The auth-service responds with `allowed: false` |
|
|
55
|
+
| `503` | The auth-service is unreachable or errors |
|
|
56
|
+
|
|
57
|
+
## Build
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m build
|
|
61
|
+
```
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/agios_auth_verify.egg-info/PKG-INFO
|
|
4
|
+
src/agios_auth_verify.egg-info/SOURCES.txt
|
|
5
|
+
src/agios_auth_verify.egg-info/dependency_links.txt
|
|
6
|
+
src/agios_auth_verify.egg-info/requires.txt
|
|
7
|
+
src/agios_auth_verify.egg-info/top_level.txt
|
|
8
|
+
src/auth_verify/__init__.py
|
|
9
|
+
src/auth_verify/authorize.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
auth_verify
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
from fastapi import HTTPException, Request
|
|
5
|
+
|
|
6
|
+
AUTH_SERVICE_URL = os.environ.get("AUTH_SERVICE_URL", "")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def authorize(required_permission: str):
|
|
10
|
+
async def middleware(request: Request) -> None:
|
|
11
|
+
user = getattr(request.state, "user", None)
|
|
12
|
+
user_id = (user or {}).get("userId") if isinstance(user, dict) else getattr(user, "userId", None)
|
|
13
|
+
if not user_id:
|
|
14
|
+
raise HTTPException(status_code=401, detail={"success": False, "message": "Authentication required"})
|
|
15
|
+
|
|
16
|
+
tenant_id = None
|
|
17
|
+
if isinstance(user, dict):
|
|
18
|
+
tenant_id = user.get("tenantId")
|
|
19
|
+
elif user is not None:
|
|
20
|
+
tenant_id = getattr(user, "tenantId", None)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
async with httpx.AsyncClient() as client:
|
|
24
|
+
response = await client.post(
|
|
25
|
+
f"{AUTH_SERVICE_URL}/api/auth/check-permission",
|
|
26
|
+
json={"userId": user_id, "permissionKey": required_permission},
|
|
27
|
+
headers={
|
|
28
|
+
"Authorization": request.headers.get("authorization", ""),
|
|
29
|
+
"tenant-id": tenant_id or request.headers.get("tenant-id", ""),
|
|
30
|
+
},
|
|
31
|
+
)
|
|
32
|
+
response.raise_for_status()
|
|
33
|
+
|
|
34
|
+
if not response.json().get("allowed"):
|
|
35
|
+
raise HTTPException(
|
|
36
|
+
status_code=403,
|
|
37
|
+
detail={"success": False, "message": "You do not have permission to perform this action"},
|
|
38
|
+
)
|
|
39
|
+
except HTTPException:
|
|
40
|
+
raise
|
|
41
|
+
except httpx.HTTPStatusError as error:
|
|
42
|
+
if error.response.status_code == 401:
|
|
43
|
+
raise HTTPException(status_code=401, detail={"success": False, "message": "Authentication required"})
|
|
44
|
+
raise HTTPException(status_code=503, detail={"success": False, "message": "Authorization service unavailable"})
|
|
45
|
+
except httpx.RequestError:
|
|
46
|
+
raise HTTPException(status_code=503, detail={"success": False, "message": "Authorization service unavailable"})
|
|
47
|
+
|
|
48
|
+
return middleware
|