Skip to main content

Shared authentication middleware for PARGO backend services

Project description

pargo-auth

Authentication and user management for PARGO. This repo serves two purposes:

  1. PyPI Package (pargo-auth) - JWT verification middleware for FastAPI
  2. User Service - API for user profile and settings management

Architecture

pargo-auth/
├── src/pargo_auth/          # Library (published to PyPI)
│   ├── middleware.py        # Supabase JWT verification
│   ├── models.py            # AuthenticatedUser dataclass
│   └── exceptions.py        # Auth errors
├── app/                     # Service (deployed to server)
│   ├── main.py              # FastAPI application
│   ├── routes/users.py      # /v1/me endpoints
│   └── services/            # Database operations
├── docker/Dockerfile        # Service container
└── pyproject.toml           # Package configuration

Part 1: PyPI Package

The pargo-auth package provides JWT verification for any PARGO backend.

Installation

pip install pargo-auth

Usage

from fastapi import Depends
from pargo_auth import get_current_user, AuthenticatedUser

@app.get("/protected")
async def protected(user: AuthenticatedUser = Depends(get_current_user)):
    return {"user_id": user.sub, "email": user.email}

Configuration

Set environment variables:

SUPABASE_URL=https://your-project.supabase.co
ENV=local  # Skip verification in local dev

AuthenticatedUser

Field Type Description
sub str Supabase user ID (stable, canonical identity)
email str | None User's email
email_verified bool Whether email is verified
supabase_uid str Alias for sub
raw_claims dict | None Full JWT payload

Optional Auth

For endpoints that work with or without authentication:

from pargo_auth import SupabaseAuth

auth = SupabaseAuth()

@app.get("/content")
async def get_content(user: AuthenticatedUser | None = Depends(auth.get_user_optional)):
    if user:
        return {"personalized": True, "user": user.sub}
    return {"personalized": False}

Part 2: User Service

The service manages user data in Hetzner Postgres (auth schema).

Endpoints

Method Path Auth Description
GET /v1/me Required Get profile + settings (creates user on first call)
PATCH /v1/me Required Update profile
PATCH /v1/me/settings Required Update settings
DELETE /v1/me Required Soft delete account
GET /health None Health check

Database Schema

Uses the auth schema in Postgres:

  • auth.users - Core user identity (synced from Supabase JWT)
  • auth.user_identities - Login methods (apple, google, email)
  • auth.user_settings - App preferences
  • auth.audit_events - Security/login event log

Running Locally

# Install dependencies
pip install -r requirements-service.txt
pip install -e .

# Set environment
export SUPABASE_URL=https://your-project.supabase.co
export DATABASE_URL=postgresql://postgres:password@localhost:5432/pargo_test
export ENV=local

# Run
uvicorn app.main:app --reload --port 8040

Docker

docker build -f docker/Dockerfile -t pargo-auth .
docker run -p 8040:8040 \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e DATABASE_URL=postgresql://... \
  pargo-auth

Response Examples

GET /v1/me

{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "supabase_uid": "846eddd7-f5ae-4d72-8082-accde7da68f2",
    "email": "user@example.com",
    "email_verified": true,
    "display_name": "John Doe",
    "preferred_lang": "da",
    "created_at": "2026-02-02T10:00:00Z",
    "last_login_at": "2026-02-02T12:00:00Z"
  },
  "settings": {
    "push_enabled": true,
    "email_enabled": true,
    "map_style": "standard",
    "settings_json": {}
  }
}

Development

Package Development

# Install in editable mode
pip install -e ".[dev]"

# Run tests
pytest

Publishing (automatic)

Push to main triggers GitHub Actions:

  1. Bumps version
  2. Publishes to PyPI

Design Decisions

Decision Rationale
supabase_uid is canonical ID JWT sub is stable even if email changes
User created on first /me call No separate signup flow needed
Soft delete GDPR compliance, account recovery possible
Separate settings table Clean separation, flexible JSONB for future

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pargo_auth-0.1.6.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pargo_auth-0.1.6-py3-none-any.whl (7.6 kB view details)

Uploaded Python 3

File details

Details for the file pargo_auth-0.1.6.tar.gz.

File metadata

  • Download URL: pargo_auth-0.1.6.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pargo_auth-0.1.6.tar.gz
Algorithm Hash digest
SHA256 b72e69c5d10914d2f421780513f52c4ec2d2e7b789d712c9807c54e365652104
MD5 37354b10e8ce52eb2777210dabf44674
BLAKE2b-256 b27c74416b20f6cabeaed5e9774b3ac69de2ef68b4c9759b9a4651c22d4b48da

See more details on using hashes here.

Provenance

The following attestation bundles were made for pargo_auth-0.1.6.tar.gz:

Publisher: publish.yml on pargoorg/pargo-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pargo_auth-0.1.6-py3-none-any.whl.

File metadata

  • Download URL: pargo_auth-0.1.6-py3-none-any.whl
  • Upload date:
  • Size: 7.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pargo_auth-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 300a637dfe432c3275a8ec2ef5fa6c79b0b91fb4a4af7bd365e614c23ccac4ac
MD5 eb83d4117942b303eed4298a2afea4c9
BLAKE2b-256 b7e50622cf0b2c48b91a6ab01d1fcea4a4e9738c1bb911b3fe9f6715bbf4ad83

See more details on using hashes here.

Provenance

The following attestation bundles were made for pargo_auth-0.1.6-py3-none-any.whl:

Publisher: publish.yml on pargoorg/pargo-auth

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page