Metadata-Version: 2.4
Name: trackstack-auth-client
Version: 0.1.0
Summary: Shared JWT-then-personal-access-token auth verification for TrackStack tracker backends (Python)
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: PyJWT>=2.8.0
Requires-Dist: requests>=2.31.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
Requires-Dist: responses>=0.25.0; extra == "dev"

# trackstack-auth-client (Python)

Shared JWT-then-personal-access-token verification for TrackStack tracker backends written in Python (FastAPI, etc.).

This does **not** replace [trackstack-auth](https://github.com/RishiBappanad/trackstack-auth) — identity, JWT issuance, and PAT storage/revocation all still live there exclusively. This package is the small piece of glue every *other* tracker's backend needs: given a request's Bearer token, verify it as a JWT locally first (fast, no network call, using the shared `JWT_SECRET`), and only fall back to calling trackstack-auth's own `POST /tokens/verify` if that fails — so a personal access token still works, without making the common case (a real login JWT) pay for a network round trip on every request.

The Node/Express equivalent lives in [`trackstack-ui`](https://github.com/RishiBappanad/trackstack-ui)'s `trackstack-ui/auth-client` subpath. Both implementations are tested against the same [`CONTRACT_FIXTURE.json`](./CONTRACT_FIXTURE.json) in this repo, so they can't silently drift apart the way this exact fallback logic once did when each tracker hand-copied it — it was missing entirely in two of three trackers until that was found and fixed.

## Install

```bash
pip install trackstack-auth-client
```

## Usage

```python
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from trackstack_auth_client import verify_trackstack_token
import os

security = HTTPBearer()
JWT_SECRET = os.environ["JWT_SECRET"]
TRACKSTACK_AUTH_URL = os.environ.get("TRACKSTACK_AUTH_URL")  # required for PAT support

async def get_current_user(creds: HTTPAuthorizationCredentials = Depends(security)) -> int:
    account = await verify_trackstack_token(creds.credentials, JWT_SECRET, TRACKSTACK_AUTH_URL)
    if not account:
        raise HTTPException(status_code=401, detail="Invalid token")
    return account["accountId"]
```

A synchronous `verify_trackstack_token_sync` is also exported for callers not already inside an event loop.

## Development

```bash
pip install -e ".[dev]"
pytest
```
