Security & Authentication Architecture
Explore ZCore's cryptographic services (Argon2id, JWT), the BaseAuth template pipeline, fail-fast production assertions, and scope permissions.
Security in ZCore is not an afterthought; it is integrated directly into the architectural core. The framework provides modern cryptographic primitives, fail-fast production safeguards, and an automated authentication/authorization pipeline.
1. Cryptographic Services (Argon2id & JWT)
Memory-Hard Password Hashing
ZCore uses Argon2id (via argon2-cffi), the winner of the Password Hashing Competition. Unlike legacy algorithms like bcrypt or PBKDF2, Argon2id is memory-hard, providing strong resistance against GPU and ASIC cracking rigs.
ZCore exposes dynamic parameter tuning directly via the Settings class:
ARGON2_MEMORY_COST: Memory capacity allocated per hash calculation (Default:65536KB / 64 MB).ARGON2_TIME_COST: Number of hashing iterations (Default:3).ARGON2_PARALLELISM: Parallel processing threads (Default:4).
from zcore.security import Security
# Generate Argon2id hash
hashed_pwd = Security.hash_password("SuperSecretPassword123")
# Verify plain password against stored hash
is_valid = Security.verify_password("SuperSecretPassword123", hashed_pwd)JWT Management & Asymmetric Key Support
Security handles JSON Web Token creation, signature verification, and expiration assertions. It supports both symmetric (SECRET_KEY) and enterprise asymmetric key pairs (JWT_PRIVATE_KEY and JWT_PUBLIC_KEY for algorithms like RS256).
2. Fail-Fast Production Secret Assertion
A common deployment disaster in web engineering is deploying an application to production while forgetting to change the default secret key.
ZCore implements an active Fail-Fast Startup Assertion in Security._get_signing_keys():
# Internal fail-fast validation
if is_prod and is_fallback:
raise RuntimeError(
"FATAL SECURITY VIOLATION: You are running in PRODUCTION environment "
"using the insecure default fallback SECRET_KEY. Application startup aborted."
)If settings.DEBUG is False (Production) and settings.SECRET_KEY matches the default insecure fallback, the application aborts startup immediately.
3. The BaseAuth[T] Template Pipeline
ZCore does not couple your application to a rigid user table. Instead, BaseAuth[T] is a Generic template class that coordinates token extraction, cryptographic verification, caching, and context binding:
Dynamic User Cache Lifespan (AUTH_CACHE_TTL)
BaseAuth caches resolved user sessions to eliminate redundant database queries on every authenticated request. The cache expiration time is dynamically resolved from settings.AUTH_CACHE_TTL (default: 300 seconds / 5 minutes) or can be passed explicitly via cache_ttl in the constructor.
Custom Authentication Implementation
UserProtocol models user characteristics flexibly: id is typed as Any, seamlessly supporting auto-incrementing integers, UUIDs, or external strings:
# auth.py
from typing import Any
from pydantic import BaseModel
from zcore import BaseAuth
class AppUser(BaseModel):
id: Any # Supports UUID, int, or str
is_active: bool = True
is_superuser: bool = False
scopes: list[str] = []
all_restricted_fields: list[str] = []
class CustomAuth(BaseAuth[AppUser]):
# cache_ttl is optional; falls back to settings.AUTH_CACHE_TTL (300s)
def __init__(self, auto_error: bool = True):
super().__init__(user_schema=AppUser, cache_prefix="auth", auto_error=auto_error)
async def fetch_user(self, identity: str) -> AppUser | None:
# Resolve user from database repository
db_user = await user_repo.get_by_username(identity)
return AppUser.model_validate(db_user) if db_user else NoneOptional Authentication & Guest Support (auto_error=False)
For endpoints that support both authenticated users and anonymous guests (e.g., public catalogs, guest checkouts):
# main.py
from zcore.security import get_current_user_stub, get_optional_user_stub
from auth import CustomAuth
# Standard strict authentication (raises 401 on missing/invalid token)
strict_auth = CustomAuth(auto_error=True)
app.dependency_overrides[get_current_user_stub] = strict_auth
# Optional authentication (returns None if unauthenticated)
optional_auth = CustomAuth(auto_error=False)
app.dependency_overrides[get_optional_user_stub] = optional_authWhen auto_error=False, missing tokens, expired tokens, or inactive accounts return None gracefully instead of raising an AuthError (401), allowing downstream routes to serve unauthenticated requests while letting Zchema prune fields defined in __private__.
4. Scope-Based Authorization (HasScopes)
ZCore employs an OAuth2/OIDC compatible scope authorization model via the HasScopes permission class:
- Scope Resolution: Resolves user scopes dynamically from
ctx.get("scopes")or theUserProtocolinstance. - Superuser Bypass: If
allow_superuser=True(default), users withis_superuser = Truebypass scope assertions entirely, simplifying administrative workflows. - Standardized Status Codes:
- Unauthenticated or inactive user $\rightarrow$
401 Unauthorized. - Insufficient scopes $\rightarrow$
403 Forbidden.
- Unauthenticated or inactive user $\rightarrow$
from fastapi import APIRouter, Depends
from zcore.security import HasScopes
router = APIRouter()
@router.delete(
"/finance/invoices/{id}",
dependencies=[Depends(HasScopes("invoices:delete", "finance:admin"))]
)
async def delete_invoice(id: str):
return {"status": "deleted"}Zero-Boilerplate Routing: When using BaseRouter, HasScopes dependencies are automatically calculated and injected for every CRUD/Lookup endpoint based on model.actions().
Zchema & Context Shielding
Understand how ZCore intercepts Pydantic V2 to provide dynamic, role-based field pruning across validation, serialization, and OpenAPI schema generation.
Caching & Real-Time Streaming
Deep dive into ZCore's distributed Redis cache with resilient in-memory LRU fallback and the cluster-wide PubSub streaming engine.