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:
- Auth not enabled — raises
AuthenticationError(auth configuration is required) - No token — raises
AuthenticationError - Matches a static token — returns a static-token user (O(1) set lookup)
- 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)
| File | Size | Uploaded | |
|---|---|---|---|
| remem_auth-0.3.2.tar.gz | 8.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|