Authx-Identity
A standalone OpenID Connect (OIDC) identity microservice, built with FastAPI, plus a small Django client for services that need to talk to it.
pip install authx-identityStart here
The shortest path from nothing to your first result.
Browse by topic
Grouped the same way as the sidebar.
Works with
Projects that Authx-Identity declares a relationship with in project.json.
Full project README
- Website:: https://djangoplay.org
- Documentation:: https://docs.djangoplay.org
- Contact: contact@djangoplay.org
AuthX provides a centralized identity authority for applications that need authentication, SSO, JWT issuance, identity management, and local JWT verification without making each application responsible for becoming its own identity provider.
Contents
- Overview
- What AuthX Provides
- Package Components
- Architecture
- Identity Ownership
- Quick Start
- Running the AuthX Service
- Using AuthX from Django
- API
- Configuration
- JWT Verification
- Security Model
- Database
- Production Deployment
- Development
- License
Overview
AuthX is a standalone identity service implementing an OIDC-oriented authentication architecture.
It provides:
- Email/password identity management
- SSO identity support
- JWT access tokens
- JWT refresh tokens
- OIDC discovery
- JWKS public-key distribution
- UserInfo
- Trusted internal identity-management APIs
- Local JWT verification for consuming applications
- PostgreSQL-backed identity persistence
The central architectural principle is:
AuthX is the JWT signing authority.
AuthX owns the identity layer while consuming applications remain responsible for their own domain data and business logic.
This allows multiple applications to use the same identity authority without coupling their domain models to the identity service.
What AuthX Provides
Identity Authority
AuthX owns identity information such as:
- Email addresses
- Password credentials
- SSO provider identities
- Identity status
- Identity lifecycle
Consuming applications reference an AuthX identity rather than becoming the source of truth for authentication credentials.
Authentication
AuthX supports authentication flows based on:
- Email/password credentials
- SSO identity providers
- Access tokens
- Refresh tokens
The authentication service is exposed through a FastAPI application.
OpenID Connect Endpoints
AuthX exposes standard discovery and identity endpoints including:
/.well-known/openid-configuration
/token
/token/refresh
/userinfo
/jwks
`These allow clients and consuming services to discover AuthX, obtain tokens, retrieve user information, and verify JWT signatures.
Internal Identity API
Trusted backend applications can use the internal identity API to:
- Create identities
- Retrieve identities
- Find identities by email
- Find identities by SSO provider and provider ID
- Update identities
- Soft-delete identities
Internal identity operations are protected by a service credential.
They are intended for server-to-server communication only.
Package Components
The authx-identity distribution contains two closely related components.
| Component | Purpose |
|---|---|
authx |
FastAPI identity microservice, database models, API endpoints, and migrations |
authx_client |
Client library for consuming AuthX from Django/Python applications |
Install the complete distribution:
pip install authx-identityFor Django applications:
pip install "authx-identity[django]"A consuming application can use authx_client without running its own AuthX instance.
Architecture
flowchart TB
CLIENT["Clients<br/>Web • API • SSO"]
AUTHX["<b>AuthX</b><br/>FastAPI Identity Service"]
IDENTITY["Identity Store<br/>UserIdentity + RefreshToken"]
DB[("PostgreSQL")]
JWT["JWT Authority<br/>RS256 Signing"]
KEY["RSA Private Key"]
TOKEN["Signed Access / Refresh Tokens"]
JWKS["JWKS<br/>RSA Public Key"]
DJANGO["<b>DjangoPlay</b><br/><br/>Domain Data<br/>Business Logic<br/>Authorization"]
OTHER["<b>Other Consumer</b><br/><br/>Domain Data<br/>Business Logic<br/>Authorization"]
CLIENT -->|"Authentication / OIDC"| AUTHX
AUTHX --> IDENTITY
IDENTITY --> DB
AUTHX --> JWT
JWT --> KEY
JWT --> TOKEN
JWT --> JWKS
TOKEN -->|"Bearer JWT"| DJANGO
TOKEN -->|"Bearer JWT"| OTHER
JWKS -->|"Signature verification"| DJANGO
JWKS -->|"Signature verification"| OTHER
AUTHX -->|"Internal identity API"| DJANGO
AUTHX -->|"Internal identity API"| OTHERAuthX owns identity and token authority; consuming applications own their domain data, business logic, and authorization.
And DjangoPlay is shown as one consumer, not as something AuthX was specifically designed around.
The architectural boundary is deliberate:
AuthX
└── Identity
Consuming Application
└── DomainAuthX does not own application-specific business records.
A consuming application should normally store the AuthX identity ID alongside its own domain data.
Identity Ownership
The system separates identity ownership from domain ownership.
AuthX owns
- Authentication credentials
- Identity records
- SSO identity relationships
- Identity status
- JWT issuance
- JWT signing keys
Consuming applications own
- Profiles
- Organizations
- Roles and application permissions
- Business entities
- Financial records
- Application-specific preferences
- Domain workflows
Conceptually:
AuthX Identity
│
identity_id
│
┌────────────┴────────────┐
│ │
▼ ▼
DjangoPlay Other App
Domain User Domain User
Organization Organization
Business Data Business DataThis prevents the identity service from becoming a shared database for unrelated application domains.
Quick Start
Installation
Install AuthX:
pip install authx-identityFor Django consumers:
pip install "authx-identity[django]"Running the AuthX Service
1. Clone the repository
git clone https://github.com/codefleetx/authx-identity.git
cd authx-identityCreate the environment file:
cp env.example .envAuthX reads configuration from .env.
2. Generate JWT keys
AuthX uses RSA/RS256 for JWT signing.
Generate a private key:
openssl genrsa -out jwt_private.pem 2048Generate the corresponding public key:
openssl rsa \
-in jwt_private.pem \
-pubout \
-out jwt_public.pemValidate the private key:
openssl rsa \
-in jwt_private.pem \
-check \
-nooutExpected:
RSA key ok3. Configure the PEM values
AuthX accepts the PEM keys through environment variables.
The .env representation should contain literal \n sequences between PEM lines:
JWT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
JWT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"The settings layer converts these literal sequences into actual newlines before loading the keys.
Do not expose or commit the private key.
4. Configure JWT settings
Example:
JWT_ALGORITHM=RS256
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
JWT_REFRESH_TOKEN_EXPIRE_DAYS=30
JWT_ISSUER=https://auth.example.com
JWT_AUDIENCE=your-applicationIssuer
JWT_ISSUER identifies the AuthX deployment issuing the token.
It must be a valid HTTP(S) URL without:
- Query strings
- URL fragments
Production deployments must use HTTPS.
Example:
JWT_ISSUER=https://auth.djangoplay.orgAudience
JWT_AUDIENCE identifies the intended consumer of the token.
Example:
JWT_AUDIENCE=djangoplayThe consuming application must validate the expected issuer and audience.
5. Configure the service token
Internal identity APIs require:
AUTHX_SERVICE_TOKEN=<strong-random-secret>Generate a strong value:
python -c "import secrets; print(secrets.token_hex(48))"This credential is strictly backend-only.
Never expose it to:
- Browsers
- Frontend JavaScript
- Mobile applications
- End users
- Public API clients
6. Configure PostgreSQL
Example:
DATABASE_URL=postgresql+asyncpg://authx:<password>@127.0.0.1:5432/authx
DATABASE_URL_SYNC=postgresql+psycopg2://authx:<password>@127.0.0.1:5432/authxWhen running PostgreSQL through Docker Compose, the hostname can be the database service name instead.
7. Configure CORS
CORS origins are configured as a comma-separated list:
CORS_ORIGINS=http://localhost:3000,https://example.comOnly include origins that actually require browser access to AuthX.
8. Run migrations
alembic upgrade head9. Start AuthX
For development:
uvicorn authx.main:app \
--host 0.0.0.0 \
--port 8100AuthX defaults to:
http://localhost:810010. Verify the service
Health check:
curl http://localhost:8100/healthExpected:
{
"status": "ok",
"service": "authx"
}OIDC discovery:
curl http://localhost:8100/.well-known/openid-configurationJWKS:
curl http://localhost:8100/jwksUsing AuthX from Django
Install the Django extra:
pip install "authx-identity[django]"Configure the Django application:
AUTHX_BASE_URL = "https://auth.example.com"
AUTHX_SERVICE_TOKEN = "..."
AUTHX_JWT_ALGORITHM = "RS256"
AUTHX_JWT_AUDIENCE = "your-application"
AUTHX_JWT_ISSUER = "https://auth.example.com"The Django application does not need the AuthX private key.
It should only have access to:
- AuthX's public key
- AuthX JWKS
- Its own service credential where internal APIs are required
Creating an identity
A backend consumer can use the client:
from authx_client import AuthXClient
client = AuthXClient()
identity = client.create_identity(
email="user@example.com",
username="user",
password="...",
)An existing identity can be looked up:
identity = client.get_by_email("user@example.com")The exact client API should be treated as the integration boundary rather than calling AuthX's HTTP endpoints directly throughout the application.
API
Public Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/.well-known/openid-configuration |
OIDC discovery |
GET |
/jwks |
Public JWT signing keys |
POST |
/token |
Issue access and refresh tokens |
POST |
/token/refresh |
Refresh an access token |
GET |
/userinfo |
Retrieve authenticated identity information |
Internal Endpoints
Internal identity endpoints require the configured service credential.
| Method | Endpoint | Purpose |
|---|---|---|
POST |
/internal/identities |
Create identity |
GET |
/internal/identities/{id} |
Retrieve identity |
GET |
/internal/identities/by-email/{email} |
Find identity by email |
GET |
/internal/identities/by-sso/lookup |
Find identity by SSO provider and ID |
PATCH |
/internal/identities/{id} |
Update identity |
DELETE |
/internal/identities/{id} |
Soft-delete identity |
These endpoints are designed for trusted backend services.
Configuration
AuthX configuration is environment-based.
Application
| Variable | Purpose | Default |
|---|---|---|
APP_ENV |
Runtime environment | development |
APP_HOST |
Bind host | 0.0.0.0 |
APP_PORT |
Service port | 8100 |
APP_BASE_URL |
AuthX base URL | http://localhost:8100 |
Database
| Variable | Purpose |
|---|---|
DATABASE_URL |
Async SQLAlchemy/PostgreSQL connection |
DATABASE_URL_SYNC |
Synchronous PostgreSQL connection used for migration tooling |
JWT
| Variable | Purpose | Default |
|---|---|---|
JWT_PRIVATE_KEY |
RSA private signing key | Required |
JWT_PUBLIC_KEY |
RSA public key | Required |
JWT_ALGORITHM |
JWT signing algorithm | RS256 |
JWT_ACCESS_TOKEN_EXPIRE_MINUTES |
Access-token lifetime | 60 |
JWT_REFRESH_TOKEN_EXPIRE_DAYS |
Refresh-token lifetime | 30 |
JWT_ISSUER |
JWT issuer | Required |
JWT_AUDIENCE |
JWT audience | Required |
Internal API
| Variable | Purpose |
|---|---|
AUTHX_SERVICE_TOKEN |
Backend service authentication |
CORS
| Variable | Purpose | Default |
|---|---|---|
CORS_ORIGINS |
Allowed browser origins | http://localhost:3000 |
JWT Verification
AuthX signs JWTs using its RSA private key.
Consumers verify those tokens using AuthX's public key or JWKS.
AuthX
│
│
Private Key
│
▼
Sign JWT
│
▼
JWT
│
▼
Consumer Application
│
│ verify
▼
Public Key
/ JWKSThe AuthX private key must remain inside the AuthX deployment.
Consumers should never receive:
JWT_PRIVATE_KEYThey should instead use:
JWT_PUBLIC_KEYor:
/jwksRequired JWT validation
Consumers should validate:
- Signature
- Algorithm
- Expiration (
exp) - Issuer (
iss) - Audience (
aud)
The expected issuer and audience must be explicitly configured by the consuming application.
Security Model
AuthX has two important security boundaries.
1. JWT signing boundary
Only AuthX owns the JWT signing private key.
┌─────────────────┐
│ AuthX │
│ │
│ Private Key │
│ │ │
│ ▼ │
│ Sign JWT │
└───────┬─────────┘
│
▼
JWT
│
▼
Consumer Apps
│
▼
Verify locallyThis makes AuthX the single JWT signing authority.
2. Internal API boundary
The internal identity API requires:
X-Service-TokenThe service token is intended for trusted backend-to-backend communication.
It must never be sent to an untrusted client.
Private key protection
Never commit:
jwt_private.pem
.env
JWT_PRIVATE_KEYto source control.
If a private signing key is exposed, it should be treated as compromised and replaced.
Database
AuthX uses PostgreSQL for persistent identity data.
The service uses:
- SQLAlchemy
- Async PostgreSQL access
- Synchronous PostgreSQL access for migration tooling
- Alembic migrations
The database belongs to AuthX.
Consuming applications should not directly read or write the AuthX database.
The correct integration boundary is:
Consumer Application
│
▼
AuthX Client
│
▼
AuthX API
│
▼
AuthX PostgreSQLProduction Deployment
AuthX is designed to run as a standalone service.
A typical deployment can use:
Internet
│
▼
Reverse Proxy
│
▼
AuthX
│
▼
PostgreSQLWhen deployed alongside DjangoPlay:
Cloudflare
│
▼
Nginx
┌────┴────┐
│ │
▼ ▼
DjangoPlay AuthX
│ │
▼ ▼
PostgreSQL PostgreSQLAuthX should normally run behind the production reverse proxy rather than exposing the application server directly to the Internet.
Internal identity-management endpoints should be protected from unauthorized public access.
Production environment
Production should use:
APP_ENV=production
JWT_ISSUER=https://auth.example.com
JWT_AUDIENCE=your-application
JWT_ALGORITHM=RS256Because production mode requires the JWT issuer to use HTTPS:
https://...is required for JWT_ISSUER.
Development
Install the development dependencies:
pip install -e ".[dev]"Run the test suite:
pytestRun linting:
ruff check .Build the package:
python -m buildValidate the distributions:
twine check dist/*Package Information
Current package:
authx-identityCurrent release:
1.1.0post1Python support:
Python >= 3.11The distribution contains:
authx
authx_clientProject Structure
The package is organized broadly as:
authx/
│
├── authx/
│ ├── api/
│ ├── core/
│ ├── db/
│ ├── middleware/
│ └── models/
│
├── authx_client/
│
├── alembic/
│
├── tests/
│
├── static/
│
├── Dockerfile
├── docker-compose.yml
├── docker-compose.fullstack.yml
├── pyproject.toml
├── CHANGELOG.md
├── LICENSE
├── NOTICE
├── PyPI.md
└── README.mdThe microservice and client are distributed together so consuming applications can install the integration client from the same package.
Relationship with DjangoPlay
DjangoPlay uses AuthX as its external identity authority.
The architectural relationship is:
AuthX Identity
│
Authentication / JWT
│
▼
DjangoPlay
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Users Policy Engine Domain Apps
│
┌────────────┼────────────┐
▼ ▼ ▼
Finance Helpdesk EntitiesDjangoPlay owns its application-domain data.
AuthX owns identity.
This separation allows AuthX to serve DjangoPlay and other applications without making those applications share their domain databases.
Documentation
The README provides the primary installation and architectural overview.
Additional project documentation is maintained in the repository, including:
CHANGELOG.mdPyPI.md- API documentation
- Deployment configuration
- Infrastructure configuration
License
MIT License.