AuthX — Architecture
Version: 1.0.0 Date: 2026-08-29
On this page ▾
- 1. Overview
- 2. Architectural Role
- 3. Core Architectural Principles
- 4. High-Level Architecture
- 5. AuthX Package Architecture
- 6. AuthX Internal Structure
- 7. Application Entry Point
- 8. API Architecture
- Public API
- Internal API
- 9. OIDC Architecture
- 10. Authentication Architecture
- 11. Identity Service
- 12. Identity Data Model
- UserIdentity
- RefreshToken
- 13. Database Architecture
- 14. Password Security
- 15. JWT Architecture
- 16. JWT Issuer and Audience
- 17. JWT Claims
- 18. JWKS Architecture
- 19. Access Token Architecture
- 20. Refresh Token Architecture
- 21. Userinfo Architecture
- 22. Internal Identity API Architecture
- 23. Internal Service Authentication
- 24. Soft Deletion
- 25. Consumer Architecture
- 26. Consumer-Side Integration Library
- AuthXClient
- AuthXJWT
- 27. Django Consumer Integration
- 28. Identity Ownership Boundary
- 29. Configuration Architecture
- 30. AuthX Service URL vs JWT Issuer
- APP_BASE_URL
- JWT_ISSUER
- 31. CORS Architecture
- 32. Security Boundaries
- 33. Request Processing Model
- 34. Middleware and Operational Concerns
- 35. Database Migration Architecture
- 36. Deployment Architecture
- 37. Stateless and Stateful Components
- 38. Horizontal Scaling Considerations
- 39. Key Management
- 40. API Schema Boundaries
- 41. Error and Validation Boundaries
- 42. Health Architecture
- 43. End-to-End Authentication Flow
- 44. Refresh Lifecycle
- 45. Identity Lifecycle
- 46. Architecture Responsibilities
- 47. What AuthX Does Not Own
- 48. Security Model Summary
- 49. Architectural Benefits
- 50. Reference Architecture
- 51. Final Architecture Statement
1. Overview
AuthX is a standalone identity service designed to provide centralized authentication and identity management for applications that need a dedicated identity authority.
AuthX is implemented as a FastAPI microservice with its own PostgreSQL persistence layer and exposes two principal API surfaces:
- A public OIDC-compatible API for authentication, token issuance, token refresh, identity information, discovery, and public-key distribution.
- An internal identity-management API for trusted backend services.
AuthX is the authoritative owner of:
- Identity records
- Email addresses
- Password credentials
- Password hashes
- SSO identity associations
- Identity status
- Authentication
- Access-token issuance
- Refresh-token state
- JWT signing keys
A consuming application owns its own application/domain data and references an AuthX identity by its stable identity identifier.
The consuming application does not become the identity authority.
2. Architectural Role
AuthX sits between clients and consuming applications as an independent identity authority.
flowchart TD
CLIENT["Client<br/>Browser / Mobile / CLI / API Client"]
AUTHX["AuthX<br/>Identity Service"]
CONSUMER1["Consuming Application A"]
CONSUMER2["Consuming Application B"]
CONSUMER3["Consuming Application C"]
DB["AuthX PostgreSQL"]
CLIENT -->|"Authentication / Tokens"| AUTHX
AUTHX -->|"JWT"| CLIENT
AUTHX --> DB
CLIENT -->|"Bearer JWT"| CONSUMER1
CLIENT -->|"Bearer JWT"| CONSUMER2
CLIENT -->|"Bearer JWT"| CONSUMER3
CONSUMER1 -->|"Trusted backend API"| AUTHX
CONSUMER2 -->|"Trusted backend API"| AUTHX
CONSUMER3 -->|"Trusted backend API"| AUTHX
`The architecture deliberately separates:
Identity Authority
│
▼
AuthX
│
├── Identity
├── Credentials
├── Authentication
└── Tokens
Application Authority
│
▼
Consuming Application
│
├── Profiles
├── Organizations
├── Roles
├── Permissions
└── Domain DataAuthX does not attempt to own application-specific authorization or domain data.
3. Core Architectural Principles
AuthX follows several core principles.
| Principle | Description |
|---|---|
| Dedicated Identity Authority | AuthX owns authentication identity and credentials |
| Service Separation | Identity is separated from consuming application logic |
| API First | Authentication and identity operations are exposed through APIs |
| OIDC Compatible | Public authentication endpoints follow an OIDC-oriented interface |
| JWT Based | Access tokens are signed JWTs |
| Asymmetric Signing | AuthX signs JWTs using RSA / RS256 |
| Stateless Access Tokens | Access-token validation does not require AuthX database access |
| Stateful Refresh Tokens | Refresh-token state supports rotation and revocation |
| Backend Trust Boundary | Internal identity management requires a service credential |
| Database Isolation | AuthX maintains its own identity database |
| Consumer Independence | Any suitable application can consume AuthX |
| Local Verification | Consumers can verify JWTs using the public key/JWKS |
4. High-Level Architecture
flowchart TB
subgraph CLIENTS["Clients"]
WEB["Web Browser"]
MOBILE["Mobile Client"]
CLI["CLI / Other Client"]
end
subgraph AUTHX["AuthX Identity Service"]
API["FastAPI API"]
OIDC["OIDC API"]
INTERNAL["Internal Identity API"]
IDENTITY["Identity Service"]
SECURITY["Security / JWT"]
MODELS["Identity Models"]
REFRESH["Refresh Token State"]
end
DB[("AuthX PostgreSQL")]
subgraph CONSUMERS["Consuming Applications"]
APP1["Application A"]
APP2["Application B"]
APP3["Application C"]
end
WEB --> OIDC
MOBILE --> OIDC
CLI --> OIDC
OIDC --> SECURITY
OIDC --> IDENTITY
INTERNAL --> IDENTITY
IDENTITY --> MODELS
IDENTITY --> REFRESH
MODELS --> DB
REFRESH --> DB
SECURITY -->|"Signed JWT"| WEB
SECURITY -->|"Signed JWT"| MOBILE
SECURITY -->|"Signed JWT"| CLI
WEB -->|"Bearer JWT"| APP1
MOBILE -->|"Bearer JWT"| APP2
CLI -->|"Bearer JWT"| APP3
APP1 -->|"X-Service-Token"| INTERNAL
APP2 -->|"X-Service-Token"| INTERNAL
APP3 -->|"X-Service-Token"| INTERNAL5. AuthX Package Architecture
The distribution contains two logical packages:
authx-identity
│
├── authx/
│ │
│ ├── FastAPI microservice
│ ├── API routes
│ ├── configuration
│ ├── security
│ ├── database
│ ├── models
│ ├── schemas
│ ├── services
│ └── middleware
│
└── authx_client/
│
├── AuthXClient
└── AuthXJWTThe authx package is the identity service itself.
The authx_client package is a consumer-side helper for applications that
need to communicate with an AuthX deployment. The current distribution
explicitly packages both components.
They have different responsibilities and deployment roles.
6. AuthX Internal Structure
The current package is organized into distinct technical areas:
authx/
│
├── __init__.py
├── main.py
│
├── api/
│ ├── deps.py
│ └── v1/
│ ├── endpoints/
│ │ └── oidc.py
│ │
│ └── internal/
│ └── identities.py
│
├── core/
│ ├── logging.py
│ ├── security.py
│ └── settings.py
│
├── db/
│ └── session.py
│
├── middleware/
│ └── logging.py
│
├── models/
│ ├── refresh_token.py
│ └── user_identity.py
│
├── schemas/
│ └── identity.py
│
└── services/
└── identity_service.pyThis structure separates:
- HTTP/API concerns
- Security concerns
- Configuration
- Persistence
- Domain models
- Request/response schemas
- Identity business operations
- Middleware
The package layout is confirmed by the built AuthX distribution.
7. Application Entry Point
The FastAPI service is exposed through:
authx.main:appThe application is normally run using Uvicorn.
Example:
uvicorn authx.main:app --host 0.0.0.0 --port 8100In containerized deployments, migrations are applied before the service starts.
The default development service endpoint is:
http://localhost:81008. API Architecture
AuthX exposes two API boundaries.
flowchart TD
REQUEST["Incoming Request"]
REQUEST --> PUBLIC{"Public API?"}
PUBLIC -->|"Yes"| OIDC["OIDC / Public Endpoints"]
PUBLIC -->|"No"| INTERNAL["Internal API"]
OIDC --> AUTH["Credential / JWT Authentication"]
INTERNAL --> SERVICE["X-Service-Token Validation"]
AUTH --> SERVICE_LAYER["AuthX Services"]
SERVICE --> SERVICE_LAYER
SERVICE_LAYER --> DB[("PostgreSQL")]Public API
Public endpoints are designed for clients and consuming systems.
GET /.well-known/openid-configuration
GET /jwks
POST /token
POST /token/refresh
GET /userinfo
GET /healthInternal API
Internal endpoints manage identity records.
POST /internal/identities
GET /internal/identities/{id}
GET /internal/identities/by-email/{email}
GET /internal/identities/by-sso/lookup
PATCH /internal/identities/{id}
DELETE /internal/identities/{id}Internal endpoints require:
X-Service-Token: <AUTHX_SERVICE_TOKEN>The public and internal APIs therefore represent different trust boundaries.
9. OIDC Architecture
AuthX provides an OIDC-compatible public surface.
flowchart LR
CLIENT["Client"]
DISCOVERY["/.well-known/<br/>openid-configuration"]
TOKEN["/token"]
REFRESH["/token/refresh"]
USERINFO["/userinfo"]
JWKS["/jwks"]
AUTHX["AuthX"]
CLIENT --> DISCOVERY
CLIENT --> TOKEN
CLIENT --> REFRESH
CLIENT --> USERINFO
CLIENT --> JWKS
DISCOVERY --> AUTHX
TOKEN --> AUTHX
REFRESH --> AUTHX
USERINFO --> AUTHX
JWKS --> AUTHXThe discovery endpoint publishes the service metadata required by consumers.
The current implementation advertises:
response_types_supported:
["token"]
subject_types_supported:
["public"]
scopes_supported:
["openid", "email", "profile"]
grant_types_supported:
["password", "refresh_token"]10. Authentication Architecture
The authentication flow is centered around the identity stored in AuthX.
For password authentication:
sequenceDiagram
participant C as Client
participant A as AuthX
participant DB as PostgreSQL
C->>A: POST /token<br/>email + password
A->>DB: Find identity
DB-->>A: Identity + password hash
A->>A: Verify password
A->>A: Validate identity status
A->>A: Create access JWT
A->>A: Create refresh JWT
A->>DB: Persist refresh-token state
A-->>C: Access + Refresh tokensAuthX therefore owns the complete credential verification operation.
A consuming application does not need to know the password hash or implement the password verification algorithm itself.
11. Identity Service
The identity service is the main business boundary inside AuthX.
Its responsibilities include:
- Creating identities
- Looking up identities
- Updating identities
- Looking up SSO identities
- Handling identity status
- Soft deletion
- Credential handling
- Identity-related validation
The API layer delegates identity operations to the service layer rather than embedding persistence logic directly into route handlers.
HTTP Request
│
▼
API Endpoint
│
▼
Identity Service
│
├── Validation
├── Identity rules
├── Password handling
└── Persistence
│
▼
SQLAlchemy / Database
│
▼
PostgreSQL12. Identity Data Model
AuthX currently maintains two primary persistence models:
UserIdentity
│
│ 1
│
│ N
▼
RefreshTokenUserIdentity
Represents the authoritative AuthX identity.
Important attributes include:
id
email
username
password_hash
sso_provider
sso_id
is_active
is_verified
is_staff
is_superuser
created_at
updated_at
deleted_at
last_loginThe identity is the source of truth for authentication-related identity data.
RefreshToken
Represents server-side refresh-token state.
Important attributes include:
id
identity_id
jti
is_revoked
expires_at
created_atThe jti provides the lookup identity for refresh-token state.
13. Database Architecture
AuthX uses PostgreSQL as its persistent identity store.
flowchart TB
AUTHX["AuthX FastAPI"]
SESSION["Database Session"]
IDENTITY["UserIdentity"]
REFRESH["RefreshToken"]
PG[("AuthX PostgreSQL")]
AUTHX --> SESSION
SESSION --> IDENTITY
SESSION --> REFRESH
IDENTITY --> PG
REFRESH --> PGThe database is an AuthX-owned persistence boundary.
A consuming application should not directly connect to the AuthX database for identity operations.
Instead:
Consumer
│
▼
AuthX API
│
▼
AuthX DatabaseThis preserves AuthX as the identity authority.
14. Password Security
Passwords are never stored as plaintext.
The persisted credential is:
password_hashPassword hashing is handled inside AuthX.
Conceptually:
Plain Password
│
▼
Password Hashing
│
▼
password_hash
│
▼
PostgreSQLAuthentication performs verification against the stored hash.
The hash is never returned through the internal or public identity responses.
15. JWT Architecture
AuthX is the sole JWT signing authority.
flowchart LR
AUTHX["AuthX"]
PRIVATE["RSA Private Key"]
JWT["Signed JWT<br/>RS256"]
CONSUMER["Consumer"]
PUBLIC["RSA Public Key<br/>or JWKS"]
VERIFY["Local JWT Verification"]
AUTHX --> PRIVATE
PRIVATE --> JWT
JWT --> CONSUMER
CONSUMER --> PUBLIC
PUBLIC --> VERIFY
JWT --> VERIFYAuthX signs tokens using:
RS256The private signing key remains inside the AuthX deployment.
Consumers receive only the public key.
16. JWT Issuer and Audience
AuthX requires explicit JWT issuer and audience configuration.
JWT_ISSUER
JWT_AUDIENCEJWT_ISSUER identifies the identity authority.
It must be a valid HTTP(S) URL without a query string or fragment.
Production deployments require HTTPS.
JWT_AUDIENCE identifies the intended application or API consuming the
token.
These values are validated both when AuthX issues tokens and when consumers verify them.
This creates an explicit trust relationship:
AuthX
│
├── iss = configured JWT_ISSUER
│
└── aud = configured JWT_AUDIENCE
│
▼
Consumer validates
expected issuer/audienceThe issuer is an identity authority identifier; it does not necessarily have to be the same URL that a backend uses to reach the AuthX process.
17. JWT Claims
Access tokens currently contain identity and token metadata such as:
sub
iss
aud
iat
exp
jti
type = access
email
username
is_verified
is_staff
is_superuserRefresh tokens contain:
sub
iss
aud
iat
exp
jti
type = refreshThe type claim allows consumers and AuthX to distinguish access tokens from
refresh tokens.
18. JWKS Architecture
AuthX exposes:
GET /jwksThe endpoint returns the public signing key as a JSON Web Key Set.
A consumer can therefore verify a JWT without obtaining the private signing key.
sequenceDiagram
participant C as Consumer
participant J as AuthX /jwks
participant A as AuthX
C->>J: GET /jwks
J-->>C: Public JWK Set
A->>A: Sign JWT with private key
A-->>C: JWT
C->>C: Verify JWT using public keyCurrent key metadata includes:
kty = RSA
use = sig
alg = RS256
kid = authx-key-1Consumers may cache the JWKS according to their own verification strategy.
19. Access Token Architecture
Access tokens are designed for stateless authentication.
The important distinction is:
Access Token
│
├── Signed by AuthX
├── Contains claims
├── Has expiration
└── Can be locally verifiedA consumer does not need to make an AuthX HTTP request for every authenticated API request merely to verify the JWT signature.
Instead:
Client
│
│ Authorization: Bearer JWT
▼
Consumer API
│
▼
Local JWT verification
│
├── Signature
├── Algorithm
├── Issuer
├── Audience
└── ExpirationThis is a major scalability property of the architecture.
20. Refresh Token Architecture
Refresh tokens intentionally use server-side state.
flowchart TD
CLIENT["Client"]
REFRESH["Refresh Token"]
AUTHX["AuthX"]
JWT["JWT Validation"]
STATE["RefreshToken Database State"]
NEW["New Access + Refresh Token"]
CLIENT --> REFRESH
REFRESH --> AUTHX
AUTHX --> JWT
JWT --> STATE
STATE -->|"Valid / not revoked"| NEW
STATE -->|"Revoked / expired"| REJECT["Reject"]
NEW --> CLIENTAuthX supports refresh-token rotation.
The high-level behavior is:
- Receive refresh token.
- Validate its JWT.
- Identify the refresh-token
jti. - Check server-side state.
- Reject revoked or expired state.
- Mark the presented refresh token revoked.
- Issue a new access token.
- Issue a replacement refresh token.
This provides revocation and rotation capabilities that a purely stateless refresh-token implementation would not provide.
21. Userinfo Architecture
The public identity endpoint is:
GET /userinfo
Authorization: Bearer <access-token>The endpoint validates the access token and returns the public identity representation.
Example:
{
"sub": "<identity-uuid>",
"email": "user@example.com",
"email_verified": true,
"preferred_username": "user"
}The public response intentionally contains significantly less information than the internal identity representation.
22. Internal Identity API Architecture
The internal API exists for trusted backend consumers.
sequenceDiagram
participant APP as Consumer Backend
participant AUTH as AuthX
participant DB as PostgreSQL
APP->>AUTH: X-Service-Token
AUTH->>AUTH: Validate service credential
APP->>AUTH: Identity operation
AUTH->>AUTH: Identity Service
AUTH->>DB: Read / Write identity
DB-->>AUTH: Result
AUTH-->>APP: Identity responseSupported operations include:
POST /internal/identities
GET /internal/identities/{id}
GET /internal/identities/by-email/{email}
GET /internal/identities/by-sso/lookup
PATCH /internal/identities/{id}
DELETE /internal/identities/{id}The internal API is not intended to replace the public authentication API.
It exists to allow trusted services to provision and manage identities.
23. Internal Service Authentication
Every internal identity-management request requires:
X-Service-Token: <AUTHX_SERVICE_TOKEN>AuthX compares the supplied credential against its configured internal service token.
The trust relationship is:
Trusted Backend
│
│ X-Service-Token
▼
AuthX Internal API
│
▼
Identity ServiceThe service credential must remain server-side.
It must never be exposed through:
- Browser JavaScript
- Mobile applications
- Public API responses
- Client-side configuration
- User-visible configuration
24. Soft Deletion
Identity deletion is implemented as a soft-delete operation.
The identity is retained, while its active state is disabled and deletion metadata is recorded.
Conceptually:
DELETE /internal/identities/{id}
│
▼
UserIdentity
│
├── deleted_at = current UTC time
└── is_active = falseDeleted identities are excluded from normal identity lookup and authentication flows.
This preserves historical identity data while preventing normal use of the account.
25. Consumer Architecture
AuthX is intentionally consumer-agnostic.
DjangoPlay is only one possible consumer.
flowchart TB
AUTHX["AuthX<br/>Identity Authority"]
DP["Django Application"]
MOBILE["Mobile Backend"]
API["REST API Platform"]
CLI["CLI / Developer Tool"]
OTHER["Other Application"]
AUTHX -->|"JWT"| DP
AUTHX -->|"JWT"| MOBILE
AUTHX -->|"JWT"| API
AUTHX -->|"JWT"| CLI
AUTHX -->|"JWT"| OTHER
DP -->|"Internal API"| AUTHX
MOBILE -->|"Internal API"| AUTHX
API -->|"Internal API"| AUTHX
CLI -->|"Internal API"| AUTHX
OTHER -->|"Internal API"| AUTHXEach consumer is responsible for its own domain.
For example:
AuthX
└── Identity: 1234
DjangoPlay
└── User profile
└── Organization membership
└── Application permissions
Another Application
└── Customer profile
└── Application-specific rolesThe AuthX identity identifier provides the connection between these systems.
26. Consumer-Side Integration Library
The distribution provides:
authx_clientwith two important abstractions:
AuthXClient
AuthXJWTAuthXClient
Used for server-to-server identity operations.
Typical operations include:
client.create_identity(...)
client.get_by_id(...)
client.get_by_email(...)
client.get_by_sso(...)The client communicates with AuthX internal endpoints using the configured service token.
AuthXJWT
Used by a consumer to verify AuthX-issued JWTs locally.
Conceptually:
Consumer
│
├── AuthXClient
│ └── HTTP → AuthX internal API
│
└── AuthXJWT
└── Local JWT verificationThe Django client is therefore an optional convenience layer; it does not change AuthX's architecture or identity authority.
27. Django Consumer Integration
When a Django application uses the optional client package, the normal architecture is:
flowchart LR
REQUEST["Django API Request"]
AUTH["AuthXJWT"]
MIRROR["Local Identity Mirror"]
API["Django Application"]
AUTHX["AuthX"]
REQUEST --> AUTH
AUTH -->|"Local verification"| API
API --> MIRROR
API -->|"Identity management"| AUTHXThe important distinction is:
JWT verification
→ local
Identity management
→ AuthX HTTP APIA consuming application does not need to call AuthX for every bearer-token verification.
28. Identity Ownership Boundary
The ownership model is central to AuthX's architecture.
| Data / Capability | AuthX | Consumer |
|---|---|---|
| Identity ID | Owner | Reference |
| Owner | Mirror/reference as required | |
| Password | Owner | No ownership |
| Password hash | Owner | Never receives |
| SSO provider linkage | Owner | Reference |
| Authentication | Owner | Consumer trusts AuthX |
| JWT signing | Owner | No |
| JWT verification | Provides authority | Performs verification |
| Application profile | No | Owner |
| Application roles | No | Owner |
| Domain entities | No | Owner |
| Organization data | No | Owner |
This prevents identity responsibilities from leaking into consuming applications.
29. Configuration Architecture
AuthX is configured through environment variables.
Configuration areas include:
Application
APP_ENV
APP_HOST
APP_PORT
APP_BASE_URL
Database
DATABASE_URL
DATABASE_URL_SYNC
POSTGRES_USER
POSTGRES_PASSWORD
POSTGRES_DB
JWT
JWT_PRIVATE_KEY
JWT_PUBLIC_KEY
JWT_ALGORITHM
JWT_ACCESS_TOKEN_EXPIRE_MINUTES
JWT_REFRESH_TOKEN_EXPIRE_DAYS
JWT_ISSUER
JWT_AUDIENCE
Internal Authentication
AUTHX_SERVICE_TOKEN
CORS
CORS_ORIGINSJWT_ISSUER and JWT_AUDIENCE are required rather than silently using
DjangoPlay-specific defaults. The issuer is validated as an HTTP(S) URL and
production requires HTTPS.
30. AuthX Service URL vs JWT Issuer
These concepts must remain separate.
APP_BASE_URL
Describes where the AuthX service is reachable.
Example:
http://127.0.0.1:8100JWT_ISSUER
Describes the identity authority asserted inside the JWT.
Example:
https://auth.example.comTherefore:
APP_BASE_URL
│
└── Network/service location
JWT_ISSUER
│
└── Identity authorityThey may intentionally differ.
31. CORS Architecture
AuthX supports explicit CORS configuration through:
CORS_ORIGINSThis is intended for browser-based consumers that need cross-origin access.
The production configuration should contain only the browser origins that actually require access.
CORS is separate from backend service authentication:
CORS
└── Browser origin policy
X-Service-Token
└── Backend service authenticationA valid CORS origin does not grant access to internal identity-management operations.
32. Security Boundaries
AuthX contains several explicit trust boundaries.
flowchart TB
UNTRUSTED["Untrusted Client"]
PUBLIC["Public OIDC API"]
AUTHX["AuthX"]
INTERNAL["Internal API"]
SERVICE["Trusted Backend"]
PRIVATE["JWT Private Key"]
PUBLICKEY["JWKS / Public Key"]
DB[("AuthX PostgreSQL")]
UNTRUSTED --> PUBLIC
PUBLIC --> AUTHX
SERVICE -->|"X-Service-Token"| INTERNAL
INTERNAL --> AUTHX
AUTHX --> PRIVATE
AUTHX --> DB
AUTHX -->|"Signed JWT"| UNTRUSTED
UNTRUSTED -->|"JWT verification"| PUBLICKEYThe critical boundaries are:
- Client → public API
- Trusted backend → internal API
- AuthX → database
- AuthX private signing key → signed JWT
- Consumer → JWT verification
- Consumer → application authorization
33. Request Processing Model
The general AuthX request path is:
HTTP Request
│
▼
FastAPI
│
▼
API Endpoint
│
├── Public OIDC request
│
└── Internal identity request
│
▼
Validation / Authentication
│
▼
Service Layer
│
▼
Database / Security Operations
│
▼
ResponseThe service layer is the main boundary for identity operations.
34. Middleware and Operational Concerns
AuthX contains middleware and logging components separate from its domain services.
This allows cross-cutting concerns such as request logging and operational instrumentation to remain outside individual endpoint implementations.
Conceptually:
Request
│
▼
Middleware
│
▼
FastAPI Router
│
▼
Endpoint
│
▼
ServiceLogging should not change the identity or authorization semantics of the request.
35. Database Migration Architecture
AuthX uses Alembic for database schema migrations.
The migration path is separate from normal runtime database access.
AuthX Source
│
▼
Alembic
│
▼
AuthX PostgreSQL SchemaThe service uses:
DATABASE_URLfor asynchronous application database access and:
DATABASE_URL_SYNCfor synchronous migration/tooling operations.
This separation is reflected in the AuthX configuration and deployment model.
36. Deployment Architecture
AuthX is designed to run as an independent service.
A typical deployment is:
flowchart TB
EDGE["Reverse Proxy / Load Balancer"]
AUTHX1["AuthX Instance"]
DB[("PostgreSQL")]
EDGE --> AUTHX1
AUTHX1 --> DBFor a simple deployment:
Reverse Proxy
│
▼
Uvicorn / AuthX
│
▼
PostgreSQLFor larger deployments:
flowchart TB
LB["Load Balancer"]
A1["AuthX Instance 1"]
A2["AuthX Instance 2"]
A3["AuthX Instance N"]
DB[("PostgreSQL")]
LB --> A1
LB --> A2
LB --> A3
A1 --> DB
A2 --> DB
A3 --> DBBecause access-token verification is based on signed JWTs rather than server sessions, AuthX instances can independently process token operations.
However, refresh-token state remains shared through the AuthX database.
37. Stateless and Stateful Components
AuthX deliberately combines stateless and stateful mechanisms.
| Component | State Model | Reason |
|---|---|---|
| Access JWT | Stateless | Fast local verification |
| JWT signature | Stateless | Public-key verification |
| JWKS | Public metadata | Key distribution |
| Identity | Stateful | Authoritative identity persistence |
| Password hash | Stateful | Credential persistence |
| Refresh token | Stateful | Rotation and revocation |
| Internal service token | Configuration state | Backend trust |
This hybrid model provides both scalability and revocation capabilities.
38. Horizontal Scaling Considerations
AuthX's architecture supports horizontal scaling of the API layer.
Load Balancer
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
AuthX-1 AuthX-2 AuthX-3
│ │ │
└────────────┼────────────┘
▼
PostgreSQLAll instances must share the same logical identity authority and compatible configuration, including:
- JWT issuer
- JWT audience
- JWT signing key material
- Database
- Internal service credential policy
JWT signing configuration is particularly important: consumers must be able to verify tokens issued by any active AuthX instance.
39. Key Management
AuthX uses an RSA key pair.
JWT_PRIVATE_KEY
│
└── AuthX only
JWT_PUBLIC_KEY
│
└── Consumer verificationThe private key must never be:
- committed to source control
- included in container images unnecessarily
- returned through an API
- provided to consuming applications
The public key can be distributed through:
GET /jwksor configured directly in a consumer where supported.
A new deployment should generate a fresh key pair rather than reusing an exposed key.
40. API Schema Boundaries
AuthX intentionally separates internal and public response schemas.
Internal Identity Response
│
├── email
├── username
├── SSO information
├── status flags
├── timestamps
└── identity metadata
Public Userinfo Response
│
├── sub
├── email
├── email_verified
└── preferred_usernameSensitive credential information is excluded from both.
This prevents internal identity-management data from automatically becoming public authentication data.
41. Error and Validation Boundaries
AuthX uses API-level validation before identity operations are executed.
Typical examples include:
Invalid UUID
│
▼
Request validation
│
▼
HTTP 422Authentication failures are handled separately:
Invalid credentials
│
▼
Authentication failure
│
▼
HTTP 401Internal service authentication failures are distinct:
Invalid X-Service-Token
│
▼
Internal authorization failure
│
▼
HTTP 403This separation is useful operationally because it distinguishes:
- malformed requests
- failed user authentication
- failed backend authentication
42. Health Architecture
AuthX exposes:
GET /healthThe endpoint is intended for operational health checks.
Logical response:
{
"status": "ok",
"service": "authx"
}A reverse proxy, process manager, container platform, or monitoring system can use this endpoint to determine whether the service is responding.
43. End-to-End Authentication Flow
The complete authentication lifecycle can be summarized as:
sequenceDiagram
participant U as User / Client
participant A as AuthX
participant DB as PostgreSQL
participant C as Consumer Application
U->>A: Authenticate
A->>DB: Load identity
DB-->>A: Identity + credential state
A->>A: Verify credentials
A->>A: Create signed JWT
A->>DB: Store refresh-token state
A-->>U: Access + Refresh JWT
U->>C: Bearer Access JWT
C->>C: Verify signature locally
C->>C: Validate issuer / audience / expiry
C-->>U: Authorized application responseAuthX therefore remains out of the hot path for normal access-token verification.
44. Refresh Lifecycle
sequenceDiagram
participant C as Client
participant A as AuthX
participant DB as PostgreSQL
C->>A: Refresh token
A->>A: Validate JWT
A->>DB: Lookup jti
DB-->>A: Refresh state
alt Valid
A->>DB: Revoke old refresh token
A->>A: Issue new access token
A->>A: Issue new refresh token
A->>DB: Persist new refresh state
A-->>C: New token pair
else Revoked / Expired
A-->>C: Reject refresh request
end45. Identity Lifecycle
flowchart TD
CREATE["Create Identity"]
ACTIVE["Active Identity"]
UPDATE["Update Identity"]
LOGIN["Authenticate"]
SOFT["Soft Delete"]
INACTIVE["Inactive / Deleted"]
CREATE --> ACTIVE
ACTIVE --> UPDATE
UPDATE --> ACTIVE
ACTIVE --> LOGIN
ACTIVE --> SOFT
SOFT --> INACTIVEThe identity remains persisted after soft deletion but is excluded from normal authentication and lookup behavior.
46. Architecture Responsibilities
AuthX is responsible for:
- Identity persistence
- Credential management
- Password hashing
- Authentication
- SSO identity association
- Identity lifecycle
- JWT issuance
- JWT signing
- Refresh-token rotation
- Refresh-token revocation
- OIDC discovery
- JWKS publication
- Userinfo
- Trusted backend identity-management APIs
Consumers are responsible for:
- Application profiles
- Application/domain data
- Application-specific authorization
- Organization membership
- Business rules
- Resource ownership
- Application UI/API behavior
- Local JWT verification
This separation is fundamental to the architecture.
47. What AuthX Does Not Own
AuthX intentionally does not attempt to become a general application database.
It does not own:
Customer profiles
Organizations
Teams
Invoices
Projects
Business entities
Application permissions
Application workflows
Application-specific domain dataA consuming application should not place these responsibilities into AuthX merely because AuthX provides the identity.
The intended relationship is:
AuthX
└── "Who is this identity?"
Consumer
└── "What can this identity do in my application?"48. Security Model Summary
The complete security model can be summarized as:
AuthX
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
Credentials JWTs Identity DB
│ │ │
│ │ │
▼ ▼ ▼
Password RS256 PostgreSQL
Hashing Signing
│
▼
Public JWKS
│
▼
ConsumersThe most important security properties are:
- Credentials remain inside AuthX.
- JWT private keys remain inside AuthX.
- Consumers receive only public verification material.
- Access tokens can be verified locally.
- Refresh tokens have server-side revocation state.
- Internal identity APIs require backend authentication.
- Public identity responses expose only required information.
- Consumer authorization remains outside AuthX.
49. Architectural Benefits
This architecture provides several important benefits.
Centralized Identity
Multiple applications can share the same identity authority.
Reduced Credential Duplication
Applications do not need independent password stores.
Local JWT Verification
Consumers can authenticate requests without an AuthX network round-trip for every request.
Controlled Internal Access
Identity-management operations are separated from public authentication.
Independent Application Evolution
Consumers can evolve their own domain models without modifying AuthX.
Horizontal API Scaling
Multiple AuthX instances can serve authentication traffic while sharing the same identity persistence layer.
Clear Security Boundaries
Private signing material, credentials, identity persistence, and application authorization have explicit ownership boundaries.
50. Reference Architecture
The complete AuthX architecture can be summarized as:
flowchart TB
CLIENT["Clients<br/>Browser / Mobile / CLI / API"]
subgraph AX["AuthX Identity Service"]
API["FastAPI"]
OIDC["Public OIDC API"]
INTERNAL["Internal Identity API"]
SERVICE["Identity Service"]
SECURITY["Security / JWT"]
MODELS["UserIdentity"]
REFRESH["RefreshToken"]
CONFIG["Configuration"]
end
DB[("AuthX PostgreSQL")]
subgraph CONSUMERS["Consumer Applications"]
APP1["Application A"]
APP2["Application B"]
APP3["Application N"]
end
CLIENT --> OIDC
OIDC --> SECURITY
OIDC --> SERVICE
INTERNAL --> SERVICE
SERVICE --> MODELS
SERVICE --> REFRESH
MODELS --> DB
REFRESH --> DB
SECURITY -->|"RS256 JWT"| CLIENT
CLIENT -->|"Bearer JWT"| APP1
CLIENT -->|"Bearer JWT"| APP2
CLIENT -->|"Bearer JWT"| APP3
APP1 -->|"X-Service-Token"| INTERNAL
APP2 -->|"X-Service-Token"| INTERNAL
APP3 -->|"X-Service-Token"| INTERNAL
CONFIG --> API
CONFIG --> SECURITY
CONFIG --> DB51. Final Architecture Statement
AuthX is a standalone identity authority, not an authentication library embedded inside a single application.
Its architecture separates:
Identity
│
├── Credentials
├── Authentication
├── SSO
└── Identity Lifecycle
Tokens
│
├── JWT Issuance
├── JWT Signing
├── JWKS
└── Refresh Rotation
Persistence
│
├── UserIdentity
└── RefreshToken
Integration
│
├── Public OIDC API
├── Internal Identity API
└── Consumer Client
Security
│
├── Password Hashing
├── RSA Signing
├── Issuer / Audience Validation
└── Backend Service AuthenticationThe resulting architecture allows AuthX to act as a reusable identity platform for Django applications, APIs, mobile backends, command-line applications, and other systems without making any individual consumer the owner of identity.
DjangoPlay is one consumer of this architecture; AuthX itself remains consumer-independent.