open-shield-python 0.2.4__tar.gz → 0.2.5__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.
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/PKG-INFO +22 -20
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/README.md +20 -18
- open_shield_python-0.2.5/docs/architecture.png +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/pyproject.toml +2 -2
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-packaging/SKILL.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-packaging/resources/implementation-playbook.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-pro/SKILL.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-testing-patterns/SKILL.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-testing-patterns/resources/implementation-playbook.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/SKILL.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/examples/before_after_refactor.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/examples/clean_architecture_layout.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/examples/dip_ports_adapters.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/resources/code_review_checklist.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.github/workflows/ci.yml +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/.gitignore +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/CHANGELOG.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/CODE_OF_CONDUCT.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/CONTRIBUTING.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/LICENSE +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/SECURITY.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/architecture/system-overview.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/design/overview.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/implementation/guidelines.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/README.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/backlog.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/0000-template.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/001-clean-architecture.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/002-modern-tooling.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/003-pydantic-usage.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-0-init.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-1-core.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-2-authz.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-3-integration.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-4-publish.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/roadmap.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/specs.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/tasks.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/tech-debt.md +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/main.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/config.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/key_provider.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/token_validator.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/dependencies.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/middleware.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/entities.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/exceptions.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/key_provider.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/tenant_resolver.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/token_validator.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/services/__init__.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/services/authorization_service.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/services/claim_mapping.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/services/token_service.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/integration/adapters/test_key_provider.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/integration/adapters/test_token_validator.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/integration/api/test_fastapi.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/adapters/test_config.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/domain/test_authorization_service.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/domain/test_claim_mapping.py +0 -0
- {open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/domain/test_token_service.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: open-shield-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Vendor-agnostic authentication and authorization enforcement SDK
|
|
5
5
|
Project-URL: Homepage, https://github.com/avinash-singh-io/open-shield-python
|
|
6
6
|
Project-URL: Repository, https://github.com/avinash-singh-io/open-shield-python
|
|
7
7
|
Project-URL: Bug Tracker, https://github.com/avinash-singh-io/open-shield-python/issues
|
|
8
|
-
Author-email: Avinash Singh <avinashsingh539+osp
|
|
8
|
+
Author-email: Avinash Singh <avinashsingh539+osp@gmail.com>
|
|
9
9
|
License: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Keywords: authentication,authorization,fastapi,jwt,oidc,rbac,security
|
|
@@ -264,26 +264,28 @@ ctx.user.actor_type # "user" | "service" | "agent"
|
|
|
264
264
|
|
|
265
265
|
## Architecture
|
|
266
266
|
|
|
267
|
-
|
|
268
|
-
┌─────────────────────────────────────────────────┐
|
|
269
|
-
│ API Layer (FastAPI middleware, dependencies) │
|
|
270
|
-
├─────────────────────────────────────────────────┤
|
|
271
|
-
│ Domain Layer (pure Python, zero dependencies) │
|
|
272
|
-
│ ├── Entities: User, Token, TenantContext │
|
|
273
|
-
│ ├── Services: TokenService, AuthzService │
|
|
274
|
-
│ ├── Ports: TokenValidatorPort, TenantResolver │
|
|
275
|
-
│ └── ClaimMapping: configurable extraction │
|
|
276
|
-
├─────────────────────────────────────────────────┤
|
|
277
|
-
│ Adapters Layer (PyJWT, httpx, OIDC discovery) │
|
|
278
|
-
└─────────────────────────────────────────────────┘
|
|
279
|
-
```
|
|
267
|
+
Open Shield sits as a **thin, powerful layer** between your identity provider and your Python backend — handling all the complexity of token validation, claim extraction, tenant resolution, and authorization enforcement so you don't have to.
|
|
280
268
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
- `TenantResolverPort` — M2M client → tenant lookup
|
|
269
|
+

|
|
270
|
+
|
|
271
|
+
### How It Works
|
|
285
272
|
|
|
286
|
-
|
|
273
|
+
1. **Any OIDC Identity Provider** (Logto, Auth0, Keycloak, Azure Entra ID, AWS Cognito, or your own) issues a JWT token when a user or service authenticates.
|
|
274
|
+
2. **Open Shield SDK** intercepts the incoming request in your Python application and:
|
|
275
|
+
- **Validates the token** — verifies the signature using auto-fetched JWKS keys from the provider's OIDC discovery endpoint.
|
|
276
|
+
- **Maps claims** — extracts user ID, email, tenant, scopes, and roles from the JWT using your configurable claim mapping (every provider names claims differently — Open Shield normalizes them).
|
|
277
|
+
- **Resolves the tenant** — determines tenant isolation using the 3-step cascade (M2M lookup → org claim → sub fallback).
|
|
278
|
+
- **Detects actor type** — classifies the caller as `user`, `service`, or `agent`.
|
|
279
|
+
- **Enforces authorization** — checks scopes and roles before the request reaches your handler.
|
|
280
|
+
3. **Your Python service** receives a clean, verified `UserContext` object — ready to use. No JWT parsing, no OIDC plumbing, no provider-specific code.
|
|
281
|
+
|
|
282
|
+
### Why This Matters
|
|
283
|
+
|
|
284
|
+
- **Works with any OIDC provider** — Switch from Auth0 to Keycloak? Change two environment variables. Zero code changes.
|
|
285
|
+
- **Works with any Python framework** — First-class FastAPI support today, with Django and Flask coming soon. The core logic is pure Python with no framework dependency.
|
|
286
|
+
- **Built on Clean Architecture** — The domain layer has zero external dependencies. All I/O (JWT decoding, OIDC discovery) happens through abstract ports implemented by swappable adapters.
|
|
287
|
+
- **Easy to test** — Mock the `TokenValidatorPort` for fast unit tests without any HTTP calls.
|
|
288
|
+
- **Easy to extend** — Implement `TenantResolverPort` to wire in your own database for M2M tenant lookups.
|
|
287
289
|
|
|
288
290
|
---
|
|
289
291
|
|
|
@@ -238,26 +238,28 @@ ctx.user.actor_type # "user" | "service" | "agent"
|
|
|
238
238
|
|
|
239
239
|
## Architecture
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
┌─────────────────────────────────────────────────┐
|
|
243
|
-
│ API Layer (FastAPI middleware, dependencies) │
|
|
244
|
-
├─────────────────────────────────────────────────┤
|
|
245
|
-
│ Domain Layer (pure Python, zero dependencies) │
|
|
246
|
-
│ ├── Entities: User, Token, TenantContext │
|
|
247
|
-
│ ├── Services: TokenService, AuthzService │
|
|
248
|
-
│ ├── Ports: TokenValidatorPort, TenantResolver │
|
|
249
|
-
│ └── ClaimMapping: configurable extraction │
|
|
250
|
-
├─────────────────────────────────────────────────┤
|
|
251
|
-
│ Adapters Layer (PyJWT, httpx, OIDC discovery) │
|
|
252
|
-
└─────────────────────────────────────────────────┘
|
|
253
|
-
```
|
|
241
|
+
Open Shield sits as a **thin, powerful layer** between your identity provider and your Python backend — handling all the complexity of token validation, claim extraction, tenant resolution, and authorization enforcement so you don't have to.
|
|
254
242
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
- `TenantResolverPort` — M2M client → tenant lookup
|
|
243
|
+

|
|
244
|
+
|
|
245
|
+
### How It Works
|
|
259
246
|
|
|
260
|
-
|
|
247
|
+
1. **Any OIDC Identity Provider** (Logto, Auth0, Keycloak, Azure Entra ID, AWS Cognito, or your own) issues a JWT token when a user or service authenticates.
|
|
248
|
+
2. **Open Shield SDK** intercepts the incoming request in your Python application and:
|
|
249
|
+
- **Validates the token** — verifies the signature using auto-fetched JWKS keys from the provider's OIDC discovery endpoint.
|
|
250
|
+
- **Maps claims** — extracts user ID, email, tenant, scopes, and roles from the JWT using your configurable claim mapping (every provider names claims differently — Open Shield normalizes them).
|
|
251
|
+
- **Resolves the tenant** — determines tenant isolation using the 3-step cascade (M2M lookup → org claim → sub fallback).
|
|
252
|
+
- **Detects actor type** — classifies the caller as `user`, `service`, or `agent`.
|
|
253
|
+
- **Enforces authorization** — checks scopes and roles before the request reaches your handler.
|
|
254
|
+
3. **Your Python service** receives a clean, verified `UserContext` object — ready to use. No JWT parsing, no OIDC plumbing, no provider-specific code.
|
|
255
|
+
|
|
256
|
+
### Why This Matters
|
|
257
|
+
|
|
258
|
+
- **Works with any OIDC provider** — Switch from Auth0 to Keycloak? Change two environment variables. Zero code changes.
|
|
259
|
+
- **Works with any Python framework** — First-class FastAPI support today, with Django and Flask coming soon. The core logic is pure Python with no framework dependency.
|
|
260
|
+
- **Built on Clean Architecture** — The domain layer has zero external dependencies. All I/O (JWT decoding, OIDC discovery) happens through abstract ports implemented by swappable adapters.
|
|
261
|
+
- **Easy to test** — Mock the `TokenValidatorPort` for fast unit tests without any HTTP calls.
|
|
262
|
+
- **Easy to extend** — Implement `TenantResolverPort` to wire in your own database for M2M tenant lookups.
|
|
261
263
|
|
|
262
264
|
---
|
|
263
265
|
|
|
Binary file
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "open-shield-python"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.5"
|
|
4
4
|
description = "Vendor-agnostic authentication and authorization enforcement SDK"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
license = { text = "MIT" }
|
|
8
8
|
authors = [
|
|
9
|
-
{ name = "Avinash Singh", email = "avinashsingh539+osp
|
|
9
|
+
{ name = "Avinash Singh", email = "avinashsingh539+osp@gmail.com" }
|
|
10
10
|
]
|
|
11
11
|
keywords = [
|
|
12
12
|
"authentication",
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-packaging/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/python-testing-patterns/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/.agent/skills/solid_architecture/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/0000-template.md
RENAMED
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/002-modern-tooling.md
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/decisions/003-pydantic-usage.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-3-integration.md
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/docs/planning/phases/phase-4-publish.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/key_provider.py
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/adapters/token_validator.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/__init__.py
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/dependencies.py
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/api/fastapi/middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/__init__.py
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/ports/key_provider.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/src/open_shield/domain/services/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/domain/test_claim_mapping.py
RENAMED
|
File without changes
|
{open_shield_python-0.2.4 → open_shield_python-0.2.5}/tests/unit/domain/test_token_service.py
RENAMED
|
File without changes
|