Metadata-Version: 2.4
Name: sonnet-auth
Version: 0.1.0
Summary: JWT/JWKS authentication and Cedar authorization for sonnet-server applications
Author-email: Wolfgang Miller <wolfgang.miller@petrarca-labs.com>
License-Expression: Apache-2.0
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.14
Requires-Python: <4.0,>=3.14
Description-Content-Type: text/markdown
Requires-Dist: sonnet-server>=0.1.9
Requires-Dist: joserfc>=1.0.0
Requires-Dist: httpx>=0.28.0
Provides-Extra: cedar
Requires-Dist: cedarpy>=4.0.0; extra == "cedar"
Provides-Extra: dev
Requires-Dist: sonnet-auth[cedar]; extra == "dev"
Requires-Dist: ruff>=0.3.0; extra == "dev"
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: testcontainers[keycloak]>=4.0; extra == "dev"

# Sonnet Auth

JWT/JWKS authentication and Cedar authorization for sonnet-server
applications. No FastMCP dependency -- MCP auth wiring lives in each
domain service.

## What it provides

- **JWT/JWKS validation** -- `JwtCredentialValidator` implements
  sonnet-server's `CredentialValidator` protocol. RS256/ES256 with
  TTL-based JWKS key refresh and graceful degradation on IdP outages.
- **Claim mapping** -- configurable dot-path extraction from JWT claims
  to `AuthContext` fields and Cedar principal attributes.
  `auto_map_claims` mode passes all non-plumbing claims automatically.
- **Cedar policy evaluation** (optional `[cedar]` extra) -- `PolicyEngine`
  wraps cedarpy for in-process RBAC/ABAC. `check_authz()` and
  `filter_authz()` are one-liner authorization for REST and MCP handlers.
- **Pluggable resource resolution** -- `ResourceAttributeResolver` protocol
  for domain-specific Cedar resource attributes.
- **Settings model** -- `AuthSettings.resolve(env_prefix, seed)` with
  per-field env var overrides and optional DB seeding. No global state.

## Install

```bash
# JWT authentication only
pip install sonnet-auth

# JWT + Cedar authorization
pip install sonnet-auth[cedar]
```

## Prerequisites

- Python 3.14+
- sonnet-server >= 0.1.9

## Usage

### AuthN only (JWT/JWKS)

```python
from sonnet_auth import AuthSettings, JwtCredentialValidator
from sonnet_server.guards import set_credential_validator

auth = AuthSettings.resolve(env_prefix="MY_APP_")
if auth.enabled:
    set_credential_validator(JwtCredentialValidator(auth.config))
```

Configuration via env vars:

```
MY_APP_AUTHN_ENABLED=true
MY_APP_AUTHN_JWKS_URI=https://idp.example.com/.well-known/jwks.json
MY_APP_AUTHN_ISSUER=https://idp.example.com
MY_APP_AUTHN_AUDIENCE=my-app
```

Or with DB seeding (coco-rag pattern):

```python
seed = {
    "authn_enabled": svc.get("authn_enabled"),
    "authn_config": svc.get("authn_config"),
    "authz_enabled": svc.get("authz_enabled"),
}
auth = AuthSettings.resolve(env_prefix="COCO_RAG_", seed=seed)
```

### AuthZ (Cedar policies)

```python
from sonnet_auth import check_authz, filter_authz, set_resource_attribute_resolver

# Register domain-specific resource resolver
set_resource_attribute_resolver(MyResolver())

# In any REST handler or MCP tool
check_authz("search", "Source", source_name)  # raises AuthzDeniedError on deny

# For list operations
permitted = filter_authz("list", "Source", source_names)
```

## Package structure

```
src/sonnet_auth/
    __init__.py          # public API with lazy Cedar imports
    settings.py          # AuthSettings, AuthnConfig
    context.py           # JWT claim -> AuthContext mapping
    jwt_validator.py     # JwtCredentialValidator (JWKS)
    policy_engine.py     # Cedar PolicyEngine [cedar extra]
    authz.py             # check_authz, filter_authz [cedar extra]
```

## License

Apache License 2.0
