Metadata-Version: 2.4
Name: herfy-auth
Version: 1.0.0
Summary: Authentication SDK for integrating with Herfy Control Center
Author: Herfy Development Team
License: MIT
Project-URL: Homepage, https://github.com/herfy/helpdesk
Project-URL: Documentation, https://github.com/herfy/helpdesk/tree/main/packages/auth-sdk
Keywords: auth,oauth2,sso,jwt,fastapi
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Framework :: FastAPI
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.24.0
Requires-Dist: python-jose[cryptography]>=3.3.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: fastapi
Requires-Dist: fastapi>=0.100.0; extra == "fastapi"
Requires-Dist: starlette>=0.27.0; extra == "fastapi"
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"

# Herfy Auth SDK

Authentication SDK for integrating applications with the Herfy Control Center.

## Features

- **Local JWT Validation**: Validate tokens locally using a shared secret (fast, no network calls)
- **Remote Token Validation**: Validate tokens via Control Center API (always up-to-date)
- **OAuth2 Authorization Code Flow**: Redirect users to Control Center for authentication
- **Client Credentials Flow**: App-to-app authentication
- **FastAPI Integration**: Ready-to-use dependencies and middleware
- **Token Caching**: Built-in caching to reduce validation overhead

## Installation

```bash
# From PyPI (recommended for app repos)
pip install herfy-auth==1.0.0

# With FastAPI support
pip install "herfy-auth[fastapi]==1.0.0"

# Local editable install (monorepo development)
pip install -e packages/auth-sdk
```

### Publishing

Create a PyPI API token and add it as a GitHub repository secret:

- `PYPI_API_TOKEN`

## Quick Start

### 1. Environment Configuration

Set these environment variables:

```bash
# Required
CONTROL_CENTER_URL=https://control.herfy.com
SECRET_KEY=your-shared-jwt-secret  # Same as Control Center

# For OAuth flows (optional)
AUTH_CLIENT_ID=your-app-id
AUTH_CLIENT_SECRET=your-app-secret

# Optional settings
TOKEN_VALIDATION_MODE=local  # "local" or "remote"
TOKEN_CACHE_TTL=300  # seconds
```

### 2. FastAPI Integration

```python
from fastapi import FastAPI, Depends
from herfy_auth import init_auth, get_current_user, require_auth, UserInfo

app = FastAPI()

# Initialize auth (call once at startup)
init_auth(
    public_routes=["/health", "/api/public"],
    public_prefixes=["/static/"],
)

# Protect routes with authentication
@app.get("/api/profile")
async def get_profile(user: UserInfo = Depends(get_current_user)):
    return {
        "id": user.id,
        "email": user.email,
        "roles": user.roles,
    }

# Require specific roles
@app.get("/api/admin")
async def admin_only(user: UserInfo = Depends(require_auth(roles=["admin"]))):
    return {"admin": True}

# Require any of multiple roles
@app.get("/api/staff")
async def staff_route(
    user: UserInfo = Depends(require_auth(roles=["admin", "agent"], any_role=True))
):
    return {"staff": True}
```

### 3. OAuth2 Login Flow

```python
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
from herfy_auth import HerfyAuthClient, AuthConfig

app = FastAPI()
auth_client = HerfyAuthClient(
    control_center_url="https://control.herfy.com",
    client_id="your-app-id",
    client_secret="your-app-secret",
)

@app.get("/login")
async def login():
    # Redirect user to Control Center login
    login_url = auth_client.get_login_url(
        redirect_uri="https://your-app.com/callback",
        state="random-csrf-token",
    )
    return RedirectResponse(login_url)

@app.get("/callback")
async def callback(code: str, state: str):
    # Exchange authorization code for tokens
    tokens = await auth_client.exchange_code(
        code=code,
        redirect_uri="https://your-app.com/callback",
    )
    
    # Get user info
    user = await auth_client.validate_token(tokens.access_token)
    
    return {
        "access_token": tokens.access_token,
        "user": {
            "id": user.id,
            "email": user.email,
        }
    }
```

### 4. App-to-App Authentication

```python
from herfy_auth import HerfyAuthClient

# For backend services that need to call the helpdesk API
auth_client = HerfyAuthClient(
    control_center_url="https://control.herfy.com",
    client_id="your-service-app-id",
    client_secret="your-service-app-secret",
)

# Get a token for API calls
async def call_helpdesk_api():
    tokens = await auth_client.get_client_credentials_token()
    
    # Use the token to call other APIs
    async with httpx.AsyncClient() as client:
        response = await client.get(
            "https://helpdesk-api.herfy.com/api/tickets",
            headers={"Authorization": f"Bearer {tokens.access_token}"}
        )
        return response.json()
```

## API Reference

### HerfyAuthClient

Main client class for authentication operations.

```python
client = HerfyAuthClient(
    control_center_url="https://control.herfy.com",
    client_id="app-id",           # Optional: for OAuth flows
    client_secret="app-secret",   # Optional: for OAuth flows  
    jwt_secret="shared-secret",   # Optional: for local validation
)

# Validate a token
user = await client.validate_token(token)

# Get OAuth login URL
url = client.get_login_url(redirect_uri, state)

# Exchange authorization code
tokens = await client.exchange_code(code, redirect_uri)

# Get client credentials token
tokens = await client.get_client_credentials_token()

# Refresh a token
tokens = await client.refresh_token(refresh_token)
```

### UserInfo

User information model returned from token validation.

```python
user = await client.validate_token(token)

user.id           # User ID
user.email        # Email address
user.roles        # List of roles
user.org_roles    # Organization roles
user.permissions  # List of permissions
user.is_admin()   # Check if admin
user.has_role("agent")  # Check specific role
user.has_permission("tickets:read")  # Check permission
```

### FastAPI Dependencies

```python
from herfy_auth import get_current_user, get_optional_user, require_auth, require_admin

# Basic auth required
user = Depends(get_current_user)

# Optional auth (returns None if not authenticated)
user = Depends(get_optional_user)

# Require specific roles
user = Depends(require_auth(roles=["admin"]))

# Require any of multiple roles
user = Depends(require_auth(roles=["admin", "manager"], any_role=True))

# Require specific permissions
user = Depends(require_auth(permissions=["tickets:write"]))

# Convenience admin check
user = Depends(require_admin())
```

## Configuration

### AuthConfig

```python
from herfy_auth import AuthConfig

config = AuthConfig(
    control_center_url="https://control.herfy.com",
    client_id="app-id",
    client_secret="app-secret",
    jwt_secret="shared-secret",
    jwt_algorithm="HS256",
    token_validation_mode="local",  # "local" or "remote"
    cache_ttl_seconds=300,
)

# Or load from environment
config = AuthConfig.from_env()
```

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `CONTROL_CENTER_URL` | Control Center API URL | `http://localhost:8001` |
| `AUTH_CLIENT_ID` | OAuth client ID | - |
| `AUTH_CLIENT_SECRET` | OAuth client secret | - |
| `SECRET_KEY` / `JWT_SECRET` | JWT signing secret | - |
| `JWT_ALGORITHM` | JWT algorithm | `HS256` |
| `TOKEN_VALIDATION_MODE` | `local` or `remote` | `local` |
| `TOKEN_CACHE_TTL` | Cache TTL in seconds | `300` |

## Token Validation Modes

### Local Validation (Recommended)

Validates JWT tokens locally using a shared secret. Fast and doesn't require network calls.

```bash
TOKEN_VALIDATION_MODE=local
SECRET_KEY=same-key-as-control-center
```

### Remote Validation

Validates tokens by calling the Control Center's `/oauth/userinfo` endpoint. Always up-to-date but requires network calls.

```bash
TOKEN_VALIDATION_MODE=remote
CONTROL_CENTER_URL=https://control.herfy.com
```

## License

MIT
