Metadata-Version: 2.4
Name: pyrx-auth-sdk
Version: 0.1.1
Summary: SDK for PYRX ecosystem services to verify JWTs, consume user events, and call pyrx.auth internal API
Requires-Python: >=3.11
Requires-Dist: httpx>=0.28.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pyjwt[crypto]>=2.9.0
Requires-Dist: redis>=5.2.0
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.115.0; extra == 'fastapi'
Description-Content-Type: text/markdown

# pyrx-auth-sdk

SDK for PYRX ecosystem services to integrate with [pyrx.auth](https://github.com/tautobot/pyrx.auth) centralized authentication.

## Installation

```bash
pip install pyrx-auth-sdk

# With FastAPI dependency support
pip install pyrx-auth-sdk[fastapi]
```

## Features

- **JWT Verification**: ES256 JWT verification with JWKS caching (no network per request)
- **FastAPI Dependency**: `get_current_user()` extracts `AuthenticatedUser` from Bearer JWT
- **Event Consumer**: Redis Stream consumer for user lifecycle events
- **Internal API Client**: Service-to-service user lookup API

## Quick Start

### FastAPI Integration

```python
from pyrx_auth_sdk.config import AuthSDKConfig
from pyrx_auth_sdk.dependencies import init_auth, get_current_user
from pyrx_auth_sdk.schemas import AuthenticatedUser

# At app startup
config = AuthSDKConfig(
    jwks_url="http://pyrx-auth:8001/api/v1/.well-known/jwks.json",
    issuer="pyrx.auth",
    audience="pyrx-mentor",
)
init_auth(config)

# In route handlers
@app.get("/protected")
async def protected(user: AuthenticatedUser = Depends(get_current_user)):
    print(f"User {user.id} from tenant {user.tenant_id}")
```

### Event Consumer

```python
from pyrx_auth_sdk.events import UserEventConsumer

consumer = UserEventConsumer(
    redis=redis_client,
    group_name="my-service-group",
    consumer_name="worker-1",
)

async def on_user_registered(payload):
    print(f"New user: {payload['user_id']}")

consumer.on("user.registered", on_user_registered)
await consumer.run()
```

### Internal API Client

```python
from pyrx_auth_sdk import AuthInternalClient
from pyrx_auth_sdk.config import AuthSDKConfig

client = AuthInternalClient(AuthSDKConfig(
    internal_api_url="http://pyrx-auth:8001",
    internal_api_key="your-service-key",
))

user = await client.get_user(user_id)
users, not_found = await client.get_users_batch(["uuid-1", "uuid-2"])
```

## Environment Variables

| Variable | Description |
|----------|-------------|
| `PYRX_AUTH_JWKS_URL` | JWKS endpoint URL |
| `PYRX_AUTH_ISSUER` | JWT issuer (default: `pyrx.auth`) |
| `PYRX_AUTH_AUDIENCE` | JWT audience (your service slug) |
| `PYRX_AUTH_INTERNAL_API_URL` | pyrx.auth base URL |
| `PYRX_AUTH_INTERNAL_API_KEY` | Service-to-service API key |
