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.

@@ -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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -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