verge-auth-sdk 0.1.18__py3-none-any.whl
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 verge-auth-sdk might be problematic. Click here for more details.
- verge_auth_sdk/__init__.py +12 -0
- verge_auth_sdk/middleware.py +140 -0
- verge_auth_sdk/secret_provider.py +65 -0
- verge_auth_sdk/verge_routes.py +98 -0
- verge_auth_sdk-0.1.18.dist-info/METADATA +250 -0
- verge_auth_sdk-0.1.18.dist-info/RECORD +9 -0
- verge_auth_sdk-0.1.18.dist-info/WHEEL +5 -0
- verge_auth_sdk-0.1.18.dist-info/licenses/LICENSE +21 -0
- verge_auth_sdk-0.1.18.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# verge_auth_sdk/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
verge_auth_sdk package public API.
|
|
4
|
+
Exports:
|
|
5
|
+
- add_central_auth(app) -> middleware to attach to FastAPI app
|
|
6
|
+
- get_secret(name) -> secret retrieval helper
|
|
7
|
+
"""
|
|
8
|
+
from .middleware import add_central_auth
|
|
9
|
+
from .secret_provider import get_secret
|
|
10
|
+
from .verge_routes import verge_internal_routes
|
|
11
|
+
|
|
12
|
+
__all__ = ["add_central_auth", "get_secret", "verge_internal_routes"]
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from fastapi import FastAPI, Request
|
|
2
|
+
from fastapi.responses import RedirectResponse, JSONResponse
|
|
3
|
+
import httpx
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from .secret_provider import get_secret
|
|
7
|
+
from .verge_routes import router as verge_routes_router
|
|
8
|
+
|
|
9
|
+
REGISTERED_ROUTES = []
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def add_central_auth(app: FastAPI):
|
|
13
|
+
|
|
14
|
+
AUTH_INTROSPECT_URL = os.getenv("AUTH_INTROSPECT_URL")
|
|
15
|
+
AUTH_LOGIN_URL = os.getenv("AUTH_LOGIN_URL")
|
|
16
|
+
|
|
17
|
+
CLIENT_ID = os.getenv("VERGE_CLIENT_ID")
|
|
18
|
+
CLIENT_SECRET = os.getenv("VERGE_CLIENT_SECRET")
|
|
19
|
+
|
|
20
|
+
SERVICE_NAME = os.getenv("SERVICE_NAME")
|
|
21
|
+
SERVICE_BASE_URL = os.getenv("SERVICE_BASE_URL")
|
|
22
|
+
AUTH_REGISTER_URL = os.getenv("AUTH_REGISTER_URL")
|
|
23
|
+
|
|
24
|
+
VERGE_SECRET = get_secret("VERGE_SERVICE_SECRET")
|
|
25
|
+
|
|
26
|
+
# ---------------------------------------
|
|
27
|
+
# INTERNAL ROUTES (MUST LOAD FIRST)
|
|
28
|
+
# ---------------------------------------
|
|
29
|
+
app.include_router(verge_routes_router)
|
|
30
|
+
|
|
31
|
+
# ---------------------------------------
|
|
32
|
+
# STARTUP β ONLY COLLECT ROUTES (NO REGISTER)
|
|
33
|
+
# ---------------------------------------
|
|
34
|
+
@app.on_event("startup")
|
|
35
|
+
async def collect_routes():
|
|
36
|
+
print("π₯ Verge bootstrap started")
|
|
37
|
+
REGISTERED_ROUTES.clear()
|
|
38
|
+
|
|
39
|
+
for route in app.routes:
|
|
40
|
+
path = getattr(route, "path", None)
|
|
41
|
+
methods = getattr(route, "methods", [])
|
|
42
|
+
|
|
43
|
+
if not path:
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
if path.startswith(("/docs", "/openapi", "/__verge__")):
|
|
47
|
+
continue
|
|
48
|
+
|
|
49
|
+
for m in methods:
|
|
50
|
+
if m in ("GET", "POST", "PUT", "PATCH", "DELETE"):
|
|
51
|
+
REGISTERED_ROUTES.append({"path": path, "method": m})
|
|
52
|
+
|
|
53
|
+
print("β
Collected Routes:", REGISTERED_ROUTES)
|
|
54
|
+
|
|
55
|
+
# ---------------------------------------
|
|
56
|
+
# SUPER ADMIN TRIGGERED REGISTRATION
|
|
57
|
+
# ---------------------------------------
|
|
58
|
+
async def register_with_auth():
|
|
59
|
+
print("π§ Triggered register_with_auth()")
|
|
60
|
+
print("π AUTH_REGISTER_URL =", AUTH_REGISTER_URL)
|
|
61
|
+
print("π SERVICE_NAME =", SERVICE_NAME)
|
|
62
|
+
print("π SERVICE_BASE_URL =", SERVICE_BASE_URL)
|
|
63
|
+
print("π CLIENT_ID =", CLIENT_ID)
|
|
64
|
+
print("π ROUTES =", REGISTERED_ROUTES)
|
|
65
|
+
try:
|
|
66
|
+
async with httpx.AsyncClient(timeout=20) as client:
|
|
67
|
+
resp = await client.post(
|
|
68
|
+
AUTH_REGISTER_URL,
|
|
69
|
+
params={
|
|
70
|
+
"name": SERVICE_NAME,
|
|
71
|
+
"base_url": SERVICE_BASE_URL,
|
|
72
|
+
"client_id": CLIENT_ID,
|
|
73
|
+
"client_secret": CLIENT_SECRET
|
|
74
|
+
},
|
|
75
|
+
headers={"X-Verge-Service-Secret": VERGE_SECRET}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
print(f"π‘ Registration: {resp.status_code}")
|
|
79
|
+
print(resp.text)
|
|
80
|
+
|
|
81
|
+
except Exception as e:
|
|
82
|
+
print("β Registration failed:", e)
|
|
83
|
+
|
|
84
|
+
# ---------------------------------------
|
|
85
|
+
# MIDDLEWARE AUTH
|
|
86
|
+
# ---------------------------------------
|
|
87
|
+
@app.middleware("http")
|
|
88
|
+
async def central_auth(request: Request, call_next):
|
|
89
|
+
path = request.url.path
|
|
90
|
+
|
|
91
|
+
# Whitelisted paths
|
|
92
|
+
if path.startswith("/__verge__") or path in {"/docs", "/openapi.json", "/health"}:
|
|
93
|
+
return await call_next(request)
|
|
94
|
+
|
|
95
|
+
# Extract token
|
|
96
|
+
token = None
|
|
97
|
+
auth_header = request.headers.get("authorization")
|
|
98
|
+
|
|
99
|
+
if auth_header and auth_header.lower().startswith("bearer "):
|
|
100
|
+
token = auth_header.split(" ")[1]
|
|
101
|
+
|
|
102
|
+
if not token:
|
|
103
|
+
token = request.cookies.get("access_token")
|
|
104
|
+
|
|
105
|
+
# redirect if HTML request
|
|
106
|
+
if not token and "text/html" in request.headers.get("accept", ""):
|
|
107
|
+
return RedirectResponse(
|
|
108
|
+
f"{AUTH_LOGIN_URL}?redirect_url={request.url}"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if not token:
|
|
112
|
+
return JSONResponse({"detail": "Unauthorized"}, status_code=401)
|
|
113
|
+
|
|
114
|
+
# Validate token
|
|
115
|
+
try:
|
|
116
|
+
async with httpx.AsyncClient(timeout=4) as client:
|
|
117
|
+
res = await client.post(
|
|
118
|
+
AUTH_INTROSPECT_URL,
|
|
119
|
+
headers={
|
|
120
|
+
"Authorization": f"Bearer {token}",
|
|
121
|
+
"X-Client-Id": CLIENT_ID,
|
|
122
|
+
"X-Client-Secret": CLIENT_SECRET,
|
|
123
|
+
},
|
|
124
|
+
)
|
|
125
|
+
data = res.json()
|
|
126
|
+
|
|
127
|
+
except Exception:
|
|
128
|
+
return JSONResponse({"detail": "Auth service unreachable"}, status_code=503)
|
|
129
|
+
|
|
130
|
+
if not data.get("active"):
|
|
131
|
+
return JSONResponse({"detail": "Session expired"}, status_code=401)
|
|
132
|
+
|
|
133
|
+
user = data.get("user", {})
|
|
134
|
+
request.state.user = user
|
|
135
|
+
|
|
136
|
+
# ----------------------------------------------
|
|
137
|
+
# β ANY authenticated user triggers auto-registration
|
|
138
|
+
# ----------------------------------------------
|
|
139
|
+
print("π Authenticated user β auto-registering service")
|
|
140
|
+
await register_with_auth()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from functools import lru_cache
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# ----- Internal provider functions -----
|
|
6
|
+
def _from_env(name: str) -> str:
|
|
7
|
+
return os.getenv(name)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _from_aws(name: str) -> str:
|
|
11
|
+
raise NotImplementedError("AWS secret provider not implemented yet")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _from_azure(name: str) -> str:
|
|
15
|
+
raise NotImplementedError("Azure secret provider not implemented yet")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _from_gcp(name: str) -> str:
|
|
19
|
+
raise NotImplementedError("GCP secret provider not implemented yet")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _from_oracle(name: str) -> str:
|
|
23
|
+
raise NotImplementedError("Oracle secret provider not implemented yet")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ----- Main entry point -----
|
|
27
|
+
@lru_cache(maxsize=128)
|
|
28
|
+
def get_secret(name: str) -> str:
|
|
29
|
+
"""
|
|
30
|
+
Universal secret provider supporting:
|
|
31
|
+
- Local .env
|
|
32
|
+
- AWS Secrets Manager
|
|
33
|
+
- Azure Key Vault
|
|
34
|
+
- Google Cloud Secret Manager
|
|
35
|
+
- Oracle Cloud Vault
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
provider = os.getenv("SECRETS_PROVIDER", "env").lower()
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
if provider == "env":
|
|
42
|
+
return _from_env(name)
|
|
43
|
+
|
|
44
|
+
if provider == "aws":
|
|
45
|
+
return _from_aws(name)
|
|
46
|
+
|
|
47
|
+
if provider == "azure":
|
|
48
|
+
return _from_azure(name)
|
|
49
|
+
|
|
50
|
+
if provider == "gcp":
|
|
51
|
+
return _from_gcp(name)
|
|
52
|
+
|
|
53
|
+
if provider == "oracle":
|
|
54
|
+
return _from_oracle(name)
|
|
55
|
+
|
|
56
|
+
except Exception as e:
|
|
57
|
+
# fallback to environment variables
|
|
58
|
+
value = os.getenv(name)
|
|
59
|
+
if value:
|
|
60
|
+
return value
|
|
61
|
+
raise Exception(
|
|
62
|
+
f"Secret '{name}' not found via provider '{provider}': {e}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
raise Exception(f"Unknown SECRETS_PROVIDER '{provider}'")
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from fastapi import APIRouter, Request, HTTPException
|
|
2
|
+
from .secret_provider import get_secret
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
router = APIRouter()
|
|
6
|
+
|
|
7
|
+
SERVICE_NAME = os.getenv("SERVICE_NAME")
|
|
8
|
+
SERVICE_BASE_URL = os.getenv("SERVICE_BASE_URL")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@router.get("/__verge__/routes", include_in_schema=False)
|
|
12
|
+
async def verge_internal_routes(request: Request):
|
|
13
|
+
|
|
14
|
+
expected_secret = get_secret("VERGE_SERVICE_SECRET")
|
|
15
|
+
received_secret = request.headers.get("X-Verge-Service-Secret")
|
|
16
|
+
|
|
17
|
+
# Enforce exact secret match
|
|
18
|
+
if not expected_secret or expected_secret != received_secret:
|
|
19
|
+
raise HTTPException(status_code=403, detail="Forbidden")
|
|
20
|
+
|
|
21
|
+
collected = []
|
|
22
|
+
|
|
23
|
+
# FastAPI auto-generated system paths you DON'T want to sync
|
|
24
|
+
INTERNAL_PREFIXES = (
|
|
25
|
+
"/__verge__",
|
|
26
|
+
"/openapi",
|
|
27
|
+
"/docs",
|
|
28
|
+
"/redoc"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
for route in request.app.routes:
|
|
32
|
+
path = getattr(route, "path", None)
|
|
33
|
+
methods = getattr(route, "methods", [])
|
|
34
|
+
|
|
35
|
+
if not path:
|
|
36
|
+
continue
|
|
37
|
+
|
|
38
|
+
# Skip internal/system routes
|
|
39
|
+
if path.startswith(INTERNAL_PREFIXES):
|
|
40
|
+
continue
|
|
41
|
+
|
|
42
|
+
# Filter HTTP methods
|
|
43
|
+
for method in methods:
|
|
44
|
+
if method in ("GET", "POST", "PUT", "PATCH", "DELETE"):
|
|
45
|
+
collected.append({
|
|
46
|
+
"path": path,
|
|
47
|
+
"method": method
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
# Sort for consistency (helps prevent duplicate entries in DB)
|
|
51
|
+
collected.sort(key=lambda r: (r["path"], r["method"]))
|
|
52
|
+
|
|
53
|
+
return collected
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@router.post("/sync/service-routes", include_in_schema=False)
|
|
57
|
+
async def sync_service_routes(request: Request):
|
|
58
|
+
|
|
59
|
+
expected_secret = get_secret("VERGE_SERVICE_SECRET")
|
|
60
|
+
received_secret = request.headers.get("X-Verge-Service-Secret")
|
|
61
|
+
|
|
62
|
+
if not expected_secret or expected_secret != received_secret:
|
|
63
|
+
raise HTTPException(status_code=403, detail="Forbidden")
|
|
64
|
+
|
|
65
|
+
collected = []
|
|
66
|
+
|
|
67
|
+
INTERNAL_PREFIXES = (
|
|
68
|
+
"/__verge__",
|
|
69
|
+
"/openapi",
|
|
70
|
+
"/docs",
|
|
71
|
+
"/redoc"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Collect routes from the app
|
|
75
|
+
for route in request.app.routes:
|
|
76
|
+
path = getattr(route, "path", None)
|
|
77
|
+
methods = getattr(route, "methods", [])
|
|
78
|
+
|
|
79
|
+
if not path:
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
if path.startswith(INTERNAL_PREFIXES):
|
|
83
|
+
continue
|
|
84
|
+
|
|
85
|
+
for method in methods:
|
|
86
|
+
if method in ("GET", "POST", "PUT", "PATCH", "DELETE"):
|
|
87
|
+
collected.append({
|
|
88
|
+
"path": path,
|
|
89
|
+
"method": method
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
collected.sort(key=lambda r: (r["path"], r["method"]))
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
"service": SERVICE_NAME,
|
|
96
|
+
"base_url": SERVICE_BASE_URL,
|
|
97
|
+
"routes": collected
|
|
98
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: verge-auth-sdk
|
|
3
|
+
Version: 0.1.18
|
|
4
|
+
Summary: Secure centralized authentication SDK for FastAPI microservices
|
|
5
|
+
Author-email: Verge Infosoft <contactus@vergeinfosoft.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://www.vergeinfosoft.com
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: fastapi
|
|
12
|
+
Requires-Dist: httpx
|
|
13
|
+
Requires-Dist: python-dotenv
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
π Verge Auth SDK
|
|
17
|
+
Secure Identity & Access Management for FastAPI Microservices
|
|
18
|
+
|
|
19
|
+
Verge Auth SDK is a lightweight integration library that connects your FastAPI microservices to the Verge Auth Platform β a centralized identity, role management, and access-control system built for modern SaaS applications.
|
|
20
|
+
|
|
21
|
+
With a single line of code, your service is fully protected and becomes part of a unified authentication ecosystem:
|
|
22
|
+
|
|
23
|
+
from verge_auth_sdk import add_central_auth
|
|
24
|
+
add_central_auth(app)
|
|
25
|
+
|
|
26
|
+
π What Verge Auth Provides
|
|
27
|
+
|
|
28
|
+
β Centralized Login
|
|
29
|
+
|
|
30
|
+
Your users authenticate through the Verge Auth hosted login experience.
|
|
31
|
+
|
|
32
|
+
β Role-Based Access Control (RBAC)
|
|
33
|
+
|
|
34
|
+
Create roles inside the Verge Auth Dashboard and assign access to microservices and their granular operations.
|
|
35
|
+
|
|
36
|
+
β Route-Level Permissions
|
|
37
|
+
|
|
38
|
+
When a service integrates the SDK, its available routes automatically appear in the Verge Auth dashboard for permissions assignment.
|
|
39
|
+
|
|
40
|
+
β Group & User Management
|
|
41
|
+
|
|
42
|
+
Assign roles to users or user groups for highly flexible access control.
|
|
43
|
+
|
|
44
|
+
β Secure Communication
|
|
45
|
+
|
|
46
|
+
All microservice-to-auth communication is secured using service credentials provided during onboarding.
|
|
47
|
+
|
|
48
|
+
π§ End-to-End User Flow
|
|
49
|
+
|
|
50
|
+
1. Account Creation
|
|
51
|
+
|
|
52
|
+
Users sign up with their organization details, company domain, and email.
|
|
53
|
+
|
|
54
|
+
2. Email Verification
|
|
55
|
+
|
|
56
|
+
A verification link is sent from no-reply@vergeinfosoft.com
|
|
57
|
+
.
|
|
58
|
+
Once verified, the user is redirected to the Verge Auth platform.
|
|
59
|
+
|
|
60
|
+
3. Login
|
|
61
|
+
|
|
62
|
+
Users can sign in through the βVerge IAMβ login page using their verified email and password.
|
|
63
|
+
|
|
64
|
+
4. Auth Dashboard
|
|
65
|
+
|
|
66
|
+
Once logged in, the dashboard displays:
|
|
67
|
+
|
|
68
|
+
Total users
|
|
69
|
+
|
|
70
|
+
Active groups
|
|
71
|
+
|
|
72
|
+
Available roles
|
|
73
|
+
|
|
74
|
+
Audit logs
|
|
75
|
+
|
|
76
|
+
Permissions overview
|
|
77
|
+
|
|
78
|
+
π Role-Based Access Control (RBAC)
|
|
79
|
+
|
|
80
|
+
RBAC inside Verge Auth is designed to be extremely intuitive β while supporting enterprise-level control.
|
|
81
|
+
|
|
82
|
+
Creating a Role
|
|
83
|
+
|
|
84
|
+
Inside the Roles section:
|
|
85
|
+
|
|
86
|
+
Click New Role
|
|
87
|
+
|
|
88
|
+
Enter the role name (e.g., HR Manager, Operations Admin)
|
|
89
|
+
|
|
90
|
+
Optional: Add a description
|
|
91
|
+
|
|
92
|
+
Select the Service you want this role to access
|
|
93
|
+
|
|
94
|
+
Example: employees-service, billing-service, appointments-service
|
|
95
|
+
|
|
96
|
+
After selecting a service, the system automatically shows all available routes for that service
|
|
97
|
+
|
|
98
|
+
Example:
|
|
99
|
+
|
|
100
|
+
/employees/
|
|
101
|
+
|
|
102
|
+
/employees/{id}
|
|
103
|
+
|
|
104
|
+
/employees/create
|
|
105
|
+
|
|
106
|
+
/employees/update
|
|
107
|
+
|
|
108
|
+
/employees/delete
|
|
109
|
+
|
|
110
|
+
Each route is presented with clear CRUD permissions:
|
|
111
|
+
|
|
112
|
+
Create
|
|
113
|
+
|
|
114
|
+
Read
|
|
115
|
+
|
|
116
|
+
Update
|
|
117
|
+
|
|
118
|
+
Delete
|
|
119
|
+
|
|
120
|
+
You can either:
|
|
121
|
+
|
|
122
|
+
Grant Full Access to that service
|
|
123
|
+
|
|
124
|
+
OR choose granular permissions route-by-route
|
|
125
|
+
|
|
126
|
+
Save the role
|
|
127
|
+
|
|
128
|
+
It instantly becomes available for assignment
|
|
129
|
+
|
|
130
|
+
Role creation modal with a dropdown for service selection and an auto-generated route list for CRUD assignment.
|
|
131
|
+
|
|
132
|
+
π§βπ€βπ§ Assigning Roles to Users or Groups
|
|
133
|
+
|
|
134
|
+
After creating a role, you can:
|
|
135
|
+
|
|
136
|
+
Assign to a User
|
|
137
|
+
|
|
138
|
+
Go to Manage Users
|
|
139
|
+
|
|
140
|
+
Edit a user
|
|
141
|
+
|
|
142
|
+
Select one or more roles
|
|
143
|
+
|
|
144
|
+
Save changes
|
|
145
|
+
|
|
146
|
+
Assign to a User Group
|
|
147
|
+
|
|
148
|
+
Create a group (e.g., HR Team, Finance Department)
|
|
149
|
+
|
|
150
|
+
Assign roles to the group
|
|
151
|
+
|
|
152
|
+
Add users into the group
|
|
153
|
+
(they automatically inherit the groupβs permissions)
|
|
154
|
+
|
|
155
|
+
This makes onboarding smoother and keeps role management scalable.
|
|
156
|
+
|
|
157
|
+
π Integrating the SDK Into a Microservice
|
|
158
|
+
Install from PyPI
|
|
159
|
+
pip install verge_auth_sdk
|
|
160
|
+
|
|
161
|
+
Add the Middleware
|
|
162
|
+
from fastapi import FastAPI
|
|
163
|
+
from verge_auth_sdk import add_central_auth
|
|
164
|
+
|
|
165
|
+
app = FastAPI()
|
|
166
|
+
add_central_auth(app)
|
|
167
|
+
|
|
168
|
+
Thatβs it.
|
|
169
|
+
The service will now:
|
|
170
|
+
|
|
171
|
+
β Authenticate incoming requests
|
|
172
|
+
β Communicate securely with Verge Auth
|
|
173
|
+
β Provide user identity + roles
|
|
174
|
+
β Automatically register its routes for RBAC assignment
|
|
175
|
+
|
|
176
|
+
β Environment Configuration
|
|
177
|
+
|
|
178
|
+
Each service requires a minimal set of environment variables:
|
|
179
|
+
|
|
180
|
+
######################################################################
|
|
181
|
+
|
|
182
|
+
AUTH_INTROSPECT_URL=<auth-server-introspection-endpoint>
|
|
183
|
+
AUTH_LOGIN_URL=<auth-server-login-ui>
|
|
184
|
+
|
|
185
|
+
VERGE_CLIENT_ID=<client-id>
|
|
186
|
+
VERGE_CLIENT_SECRET=<client-secret>
|
|
187
|
+
|
|
188
|
+
VERGE_SERVICE_SECRET=<service-integration-secret>
|
|
189
|
+
|
|
190
|
+
# These are provided by Verge Infosoft during onboarding.
|
|
191
|
+
|
|
192
|
+
# Optional secret provider:
|
|
193
|
+
|
|
194
|
+
SECRETS_PROVIDER=env # azure | aws
|
|
195
|
+
|
|
196
|
+
########################################################################
|
|
197
|
+
|
|
198
|
+
π‘ Middleware Responsibilities
|
|
199
|
+
|
|
200
|
+
The SDK transparently handles:
|
|
201
|
+
|
|
202
|
+
User authentication
|
|
203
|
+
|
|
204
|
+
Role injection
|
|
205
|
+
|
|
206
|
+
Cookie vs header auth
|
|
207
|
+
|
|
208
|
+
Unauthorized access responses
|
|
209
|
+
|
|
210
|
+
Service-level authentication
|
|
211
|
+
|
|
212
|
+
Route registration
|
|
213
|
+
|
|
214
|
+
You do not need to implement any auth or RBAC logic manually.
|
|
215
|
+
|
|
216
|
+
π Security Highlights
|
|
217
|
+
|
|
218
|
+
RSA-based JWT verification
|
|
219
|
+
|
|
220
|
+
Centralized session & token lifecycle management
|
|
221
|
+
|
|
222
|
+
Strong encryption for service credentials
|
|
223
|
+
|
|
224
|
+
Multi-layer permission checks (Role β Service β Route β Operation)
|
|
225
|
+
|
|
226
|
+
HTTPS-only communication
|
|
227
|
+
|
|
228
|
+
Support for cloud key vaults
|
|
229
|
+
|
|
230
|
+
πΌ Ideal For
|
|
231
|
+
|
|
232
|
+
HRMS, ERP, CRM, Billing platforms
|
|
233
|
+
|
|
234
|
+
Multi-tenant SaaS applications
|
|
235
|
+
|
|
236
|
+
Modern microservice architectures
|
|
237
|
+
|
|
238
|
+
Secure admin dashboards
|
|
239
|
+
|
|
240
|
+
Enterprise platforms needing consistent access control
|
|
241
|
+
|
|
242
|
+
π Support & Onboarding
|
|
243
|
+
|
|
244
|
+
For enterprise onboarding, custom integrations, or troubleshooting:
|
|
245
|
+
|
|
246
|
+
π Website
|
|
247
|
+
https://www.vergeinfosoft.com
|
|
248
|
+
|
|
249
|
+
π§ Email
|
|
250
|
+
contactus@vergeinfosoft.com
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
verge_auth_sdk/__init__.py,sha256=n76KSaK3CohCP7dzrUXWlTPNPGzWesLTlYl-C7rfW60,411
|
|
2
|
+
verge_auth_sdk/middleware.py,sha256=8bwOOVELZs_yqGuG_OjQnW3P7T0zaF1_Fj_Cvyk0Y_w,5037
|
|
3
|
+
verge_auth_sdk/secret_provider.py,sha256=j89rj9LZHl4qTI2fdf0qnn-mgDD3oTbdP3imsm0S9n8,1653
|
|
4
|
+
verge_auth_sdk/verge_routes.py,sha256=hRPHe32tBEdiAOj7qbfaa4m-obOBfATLSrx6z70xvIY,2773
|
|
5
|
+
verge_auth_sdk-0.1.18.dist-info/licenses/LICENSE,sha256=OLuFd1VUvl1QKIJJ_qJ8zR4ypcDhzeRkEywc7PX2ABQ,1090
|
|
6
|
+
verge_auth_sdk-0.1.18.dist-info/METADATA,sha256=-ETqtoG-z8Rk1fThTUXhO-vv9TKb9XfePAnDGnZLbR0,5702
|
|
7
|
+
verge_auth_sdk-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
+
verge_auth_sdk-0.1.18.dist-info/top_level.txt,sha256=0ik2K2CJZrP11DvuR7USTYJkX_kv2DSJS5wyhP1yAfA,15
|
|
9
|
+
verge_auth_sdk-0.1.18.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Verge Infosoft
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
verge_auth_sdk
|