Skip to main content

remem-auth

Shared authentication library for remem Python services. Supports JWT verification (Azure Entra ID / Google) and static bearer tokens, with out-of-the-box integrations for FastAPI and FastMCP.

Installation

# Core library (JWT verification + static tokens)
pip install remem-auth

# With FastAPI integration
pip install remem-auth[fastapi]

# With FastMCP integration
pip install remem-auth[fastmcp]

# All optional dependencies
pip install remem-auth[all]

Requires Python 3.11+.

Quick Start

1. Configure Environment Variables

All settings are read from environment variables with the REMEM_AUTH_ prefix.

As a library, remem-auth does not load .env files by default — the environment variable loading strategy is the consumer's responsibility. Common approaches:

# Option 1: Use load_dotenv() in your app's entrypoint
from dotenv import load_dotenv
load_dotenv()
config = AuthConfig()

# Option 2: Explicitly point AuthConfig to a .env file
config = AuthConfig(_env_file=".env")

# Option 3: Rely on system/container-injected env vars (no .env needed)
config = AuthConfig()

Available Variables

Variable Description Default
REMEM_AUTH_AZURE_TENANT_ID Azure Entra ID tenant ID ""
REMEM_AUTH_AZURE_CLIENT_ID Azure app registration client ID ""
REMEM_AUTH_GOOGLE_CLIENT_ID Google OAuth client ID ""
REMEM_AUTH_STATIC_TOKENS Comma-separated static bearer tokens ""
REMEM_AUTH_IDPS_JSON Advanced: full JSON array of IdP configs ""
REMEM_AUTH_VERIFY_EXP Whether to verify token expiration True
REMEM_AUTH_VERIFY_AUD Whether to verify audience True

Example — Azure Entra ID:

export REMEM_AUTH_AZURE_TENANT_ID="your-tenant-id"
export REMEM_AUTH_AZURE_CLIENT_ID="your-client-id"

Example — Static tokens (useful for dev/test):

export REMEM_AUTH_STATIC_TOKENS="dev-token-1,dev-token-2"

Example — Custom IdP via JSON:

export REMEM_AUTH_IDPS_JSON='[{"name":"my-idp","issuer":"https://idp.example.com","jwks_uri":"https://idp.example.com/.well-known/jwks.json","audience":"my-app"}]'

2. FastAPI Integration

from fastapi import Depends, FastAPI
from remem.auth import AuthConfig, AuthenticatedUser, FastAPIAuth

config = AuthConfig()  # reads from environment variables
auth = FastAPIAuth(config)
app = FastAPI()

@app.get("/protected")
def protected(user: AuthenticatedUser = Depends(auth)):
    return {"subject": user.subject, "email": user.email}

Unauthenticated requests receive a 401 Unauthorized response with a WWW-Authenticate: Bearer header.

OpenAI-compatible error format:

For services that need to return errors in the OpenAI error format, pass error_format="openai" and call install() on the app:

from fastapi import Depends, FastAPI
from remem.auth import AuthConfig, AuthenticatedUser, ErrorFormat, FastAPIAuth

config = AuthConfig()
auth = FastAPIAuth(config, error_format="openai")
app = FastAPI()
auth.install(app)  # registers the OpenAI error response handler

@app.get("/protected")
def protected(user: AuthenticatedUser = Depends(auth)):
    return {"subject": user.subject}

Authentication failures will return:

{
  "error": {
    "message": "No token provided",
    "type": "invalid_request_error",
    "param": null,
    "code": "invalid_api_key"
  }
}

If install() is not called, the error gracefully falls back to the default {"detail": "..."} format.

3. FastMCP Integration

from fastmcp import FastMCP
from remem.auth import AuthConfig, FastMCPAuthProvider

config = AuthConfig()
mcp = FastMCP("my-server", auth=FastMCPAuthProvider(config))

@mcp.tool()
def hello() -> str:
    return "world"

FastMCPAuthProvider implements FastMCP's TokenVerifier interface and uses asyncio.to_thread() internally so the synchronous verifier doesn't block the event loop.

4. Using the Core API Directly

If you're not using either framework, you can call the verification engine directly:

from remem.auth import AuthConfig, AuthVerifier, AuthenticationError

config = AuthConfig()
verifier = AuthVerifier(config)

try:
    user = verifier.verify_token("eyJhbGciOi...")
    print(user.subject, user.email, user.auth_method)
except AuthenticationError as e:
    print(f"Authentication failed: {e}")

Extracting tokens from request headers:

from remem.auth import extract_token

# Works with any object that has a .headers attribute (Mapping[str, str])
token = extract_token(request)

extract_token checks Authorization: Bearer <token> first, then falls back to the api-key header.

Core Concepts

Verification Flow

AuthVerifier.verify_token() processes tokens in this order:

  1. Auth not enabled — raises AuthenticationError (auth configuration is required)
  2. No token — raises AuthenticationError
  3. Matches a static token — returns a static-token user (O(1) set lookup)
  4. JWT — peeks the issuer from an unverified decode, then routes to the matching IdP verifier

AuthenticatedUser

The user object returned after successful authentication:

class AuthenticatedUser(BaseModel):
    subject: str                     # JWT "sub" claim
    email: str | None                # extracted from email / preferred_username / upn
    name: str | None                 # JWT "name" claim
    auth_method: AuthMethod          # "jwt" | "static" | "none"
    idp_name: str | None             # IdP name (e.g. "azure", "google")
    claims: dict[str, Any]           # full JWT payload
    token: str                       # raw token (excluded from serialization)

The token field is marked with exclude=True and repr=False, so it won't appear in .model_dump() output or print() — preventing accidental credential leaks.

Auth Required

When no IdPs or static tokens are configured, auth_enabled is False and all requests are rejected with an AuthenticationError. This ensures authentication is always explicitly configured before a service accepts requests.

API Reference

Module Exports

from remem.auth import (
    AuthConfig,                # pydantic-settings configuration
    AuthVerifier,              # core verification engine
    AuthenticationError,       # verification failure exception
    AuthenticatedUser,         # user model
    AuthMethod,                # authentication method enum
    ErrorFormat,               # error response format enum
    IdpConfig,                 # identity provider config model
    extract_token,             # extract token from request headers
    create_auth_config_from_env,  # AuthConfig factory function
    FastAPIAuth,               # FastAPI dependency (lazy import)
    FastMCPAuthProvider,       # FastMCP auth provider (lazy import)
)

FastAPIAuth and FastMCPAuthProvider are lazy-imported via __getattr__ — their framework dependencies are only loaded when actually accessed.

IdpConfig Fields

When using REMEM_AUTH_IDPS_JSON to define custom IdPs, each entry supports:

Field Type Required Default Description
name str Yes — IdP identifier
issuer str Yes — JWT issuer (used for routing)
jwks_uri str Yes — JWKS endpoint URL
audience str | None No None Expected audience
algorithms list[str] No ["RS256"] Allowed signing algorithms

Development

# Create a virtualenv and install dev dependencies
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Lint
ruff check src/ tests/

Metadata

Release files for remem-auth 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for remem-auth 0.3.2
File Size Uploaded
remem_auth-0.3.2.tar.gz 8.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for remem-auth 0.3.2
File Interpreter ABI Platform
remem_auth-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 19.3 kB

Release files / remem_auth-0.3.2.tar.gz

Download URL remem_auth-0.3.2.tar.gz
Size 8.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3cdcf332adb0dcbd612af3101b8a4ba2c4c5d161d967f912e7d857c12451e6f6
BLAKE2b-256 checksum
How to use checksums
66411151744b89a6ad8814f0e74636cb46e4cefdd0a993b947e7837aa9e2c2a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / remem_auth-0.3.2-py3-none-any.whl

Download URL remem_auth-0.3.2-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
567acd4576118a72dd6160c17aadf037a275c7678e44e6db47d9becfe15743b1
BLAKE2b-256 checksum
How to use checksums
c9b09c787191139b03510161af0996e40d94b4481ed8e160a9c69909fbf11cc5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page