Shared authentication library for remem Python services
Project description
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/
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file remem_auth-0.3.2.tar.gz.
File metadata
- Download URL: remem_auth-0.3.2.tar.gz
- Upload date:
- Size: 8.2 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cdcf332adb0dcbd612af3101b8a4ba2c4c5d161d967f912e7d857c12451e6f6
|
|
| MD5 |
9529b7479a53cac34c2a7e13981373b4
|
|
| BLAKE2b-256 |
66411151744b89a6ad8814f0e74636cb46e4cefdd0a993b947e7837aa9e2c2a0
|
File details
Details for the file remem_auth-0.3.2-py3-none-any.whl.
File metadata
- Download URL: remem_auth-0.3.2-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
567acd4576118a72dd6160c17aadf037a275c7678e44e6db47d9becfe15743b1
|
|
| MD5 |
1b5a48ed918cee5b5f52d0653d348192
|
|
| BLAKE2b-256 |
c9b09c787191139b03510161af0996e40d94b4481ed8e160a9c69909fbf11cc5
|