# pico-client-auth

> JWT authentication client for pico-fastapi with SecurityContext, role-based access control, and JWKS key rotation

Install: `pip install pico-client-auth`. Import surface: `from pico_client_auth import ...`.

## Usage

```python
from pico_fastapi import controller, get
from pico_client_auth import SecurityContext, allow_anonymous, requires_role, requires_group

@controller(prefix="/api")
class ApiController:

    @get("/me")
    async def get_me(self):
        claims = SecurityContext.require()
        return {"sub": claims.sub, "email": claims.email}

    @get("/health")
    @allow_anonymous
    async def health(self):
        return {"status": "ok"}

    @get("/admin")
    @requires_role("admin")
    async def admin_panel(self):
        return {"admin": True}
```

## Public API

- `class AgentClaims` — Immutable representation of the agentic claims carried in the
- `class AgentContext` — Singleton-style accessor for the per-request agent identity.
- `class SecurityContext` — Singleton-style accessor for the current request's authentication state.
- `class TokenClaims` — Immutable representation of the essential JWT claims.
- `allow_anonymous(fn: F)` — Mark an endpoint as accessible without authentication.
- `any_scope_matches(granted_scopes, required_scopes)` — Return True if ANY granted scope matches ANY required scope.
- `requires_group(*group_ids: str)` — Require the authenticated user to belong to at least one of the specified groups.
- `requires_role(*roles: str)` — Require the authenticated user to have at least one of the specified roles.
- `requires_scope(*scopes: str)` — Mark an endpoint as requiring at least one of the given scopes
- `scope_matches(granted: str, required: str)` — Return True if `granted` satisfies `required`.
- `class RoleResolver(Protocol)` — Protocol for resolving user roles from JWT claims.
- `class AuthClientSettings` — Type-safe settings for the auth client, loaded from configuration sources.
- `class AuthClientError(Exception)` — Base error for all pico-client-auth exceptions.
- `class MissingTokenError(AuthClientError)` — No Bearer token found in the Authorization header.
- `class TokenExpiredError(AuthClientError)` — The JWT token has expired.
- `class TokenInvalidError(AuthClientError)` — The JWT token is malformed or has an invalid signature.
- `class InsufficientPermissionsError(AuthClientError)` — The authenticated user lacks the required role(s).
- `class AuthConfigurationError(AuthClientError)` — Authentication configuration is missing or invalid.

## Docs

- docs/CHANGELOG.md
- docs/architecture.md
- docs/faq.md
- docs/getting-started.md
- docs/how-to/ (5 pages)
- docs/reference/ (3 pages)
- docs/skills.md
- docs/troubleshooting.md
- docs/tutorial.md
- docs/user-guide/ (3 pages)
