authx-identity / API / AuthX — Internal Identity API
DocsAuthx-IdentityAPIAuthX — Internal Identity API

AuthX — Internal Identity API

The Internal Identity API is the trusted backend interface used by DjangoPlay and other authorized backend consumers to manage identities in AuthX.

9 min readApplies to v1.1.1
On this page ▾
  1. 1. Architecture
  2. 2. Trust Model
  3. 3. Authentication
  4. 4. Identity Ownership
  5. Request
  6. Password handling
  7. Duplicate identity

AuthX remains the authoritative identity service. Consuming applications must not implement their own copy of AuthX credential management, password hashing, or identity persistence logic.

The internal API is intentionally separate from the public authentication endpoints.


1. Architecture

The normal communication path is:

text
DjangoPlay
    │
    │ AuthXClient
    │
    │ X-Service-Token
    ▼
AuthX Internal API
    │
    ▼
Identity Service
    │
    ▼
AuthX PostgreSQL

2. Trust Model

The Internal Identity API is not a browser-facing API.

Only trusted backend applications should have access to the service credential.

text
Browser / Public Client
        │
        │  NO SERVICE TOKEN
        ▼
   Public AuthX APIs


DjangoPlay Backend
        │
        │ X-Service-Token
        ▼
 /internal/identities/*

The credential is:

text
AUTHX_SERVICE_TOKEN

It must remain server-side and must never be exposed to:

  • Browser JavaScript
  • HTML
  • Mobile clients
  • Public API consumers
  • Frontend configuration

3. Authentication

Every internal identity request requires:

http
X-Service-Token: <AUTHX_SERVICE_TOKEN>

AuthX validates the supplied token before processing the identity operation.

The same backend credential must be configured on both sides:

text
DjangoPlay
    │
    └── AUTHX_SERVICE_TOKEN
             │
             │ must match
             ▼
AuthX
    │
    └── AUTHX_SERVICE_TOKEN

Invalid or missing service authentication is rejected by AuthX.

The service credential is separate from:

  • DjangoPlay database credentials
  • AuthX database credentials
  • JWT signing keys
  • User passwords

4. Identity Ownership

AuthX owns the authoritative identity record.

AuthX is responsible for:

  • Identity persistence
  • Password credentials
  • Password hashing
  • SSO identity linkage
  • Authentication
  • Identity status
  • Verification status
  • Staff/superuser identity flags

DjangoPlay maintains a local identity mirror for application-level relationships and data.

text
             SOURCE OF TRUTH
                    │
                    ▼
             AuthX Identity
                    │
                    │ identity response
                    ▼
          DjangoPlay UserIdentity
              local mirror

The consuming application should not directly modify AuthX's database.


5. Endpoints

The internal identity API currently exposes the following operations:

Method Endpoint Purpose
POST /internal/identities Create an identity
GET /internal/identities/{id} Retrieve an identity by ID
PUT /internal/identities/{id} Update an identity
GET /internal/identities/by-email/{email} Find an identity by email
GET /internal/identities/by-sso/lookup Find an identity by SSO provider and provider ID

All endpoints require:

http
X-Service-Token: <AUTHX_SERVICE_TOKEN>

6. Create Identity

Request

http
POST /internal/identities
X-Service-Token: <token>
Content-Type: application/json

Example request:

json
{
  "email": "user@example.com",
  "username": "user",
  "password": "strong-password",
  "sso_provider": null,
  "sso_id": null,
  "is_active": true,
  "is_verified": false,
  "is_staff": false,
  "is_superuser": false
}

The exact fields accepted by the current AuthX schema should be treated as the authoritative contract.

Password handling

The caller supplies the plaintext password only over the protected backend request.

AuthX is responsible for hashing the password before persistence.

text
DjangoPlay
    │
    │ password
    ▼
AuthX
    │
    │ password hashing
    ▼
password_hash
    │
    ▼
AuthX PostgreSQL

DjangoPlay must not reproduce AuthX's password hashing implementation.

Duplicate identity

An identity conflict, such as an existing email or conflicting SSO identity, is reported as a conflict response rather than silently creating another identity.


7. Get Identity by ID

http
GET /internal/identities/{id}
X-Service-Token: <token>

The {id} value is the AuthX identity UUID.

Example:

text
GET /internal/identities/550e8400-e29b-41d4-a716-446655440000

The endpoint returns the corresponding identity when it exists and is eligible for normal lookup.


8. Get Identity by Email

http
GET /internal/identities/by-email/{email}
X-Service-Token: <token>

Example:

text
GET /internal/identities/by-email/user@example.com

This endpoint is used when a backend consumer needs to resolve an AuthX identity from its email address.

Email lookup should be performed through AuthX rather than by querying the AuthX database directly.


9. Get Identity by SSO Identity

http
GET /internal/identities/by-sso/lookup

Query parameters:

text
provider
sso_id

Example:

http
GET /internal/identities/by-sso/lookup?provider=GOOGLE&sso_id=<provider-id>
X-Service-Token: <token>

The combination of:

text
sso_provider
sso_id

identifies the external SSO identity.

This allows DjangoPlay to resolve an existing AuthX identity during an SSO onboarding or login flow.


10. Update Identity

http
PUT /internal/identities/{id}
X-Service-Token: <token>
Content-Type: application/json

The update operation modifies the authoritative AuthX identity.

Example:

json
{
  "email": "updated@example.com",
  "username": "updated-user",
  "is_active": true,
  "is_verified": true
}

Only fields supplied by the caller are intended to be changed according to the current request schema.

If a password is supplied, AuthX performs the password hashing before persisting the new credential.

text
DjangoPlay
    │
    ▼
AuthXClient
    │
    │ PUT /internal/identities/{id}
    ▼
AuthX
    │
    ├── Validate request
    ├── Apply identity changes
    ├── Hash password if supplied
    └── Persist
         │
         ▼
    AuthX PostgreSQL

After a successful update, DjangoPlay synchronizes its local identity mirror.


11. Identity Synchronization

DjangoPlay does not treat its local identity record as the authoritative identity source.

For example:

text
DjangoPlay
    │
    │ create/update identity
    ▼
AuthX
    │
    │ authoritative identity
    ▼
AuthX PostgreSQL
    │
    │ response
    ▼
DjangoPlay
    │
    ▼
sync_identity()
    │
    ▼
Local UserIdentity mirror

The local mirror contains identity information required by DjangoPlay, including values such as:

text
authx_id
username
email
sso_provider
sso_id
is_active
is_verified
is_staff
is_superuser

This allows DjangoPlay to maintain:

  • Application relationships
  • Foreign keys
  • Profiles
  • Groups
  • Application permissions
  • Domain-specific records
  • Local history

without becoming the owner of AuthX credentials.


12. Soft Delete

Identity deletion is represented as a soft-delete operation.

http
DELETE /internal/identities/{id}
X-Service-Token: <token>

The identity record is retained rather than physically removed.

Conceptually:

text
deleted_at = current UTC time
is_active  = false

Deleted identities are excluded from normal identity lookup.

This preserves the identity record for data integrity and historical purposes while preventing the identity from remaining active.


13. Identity Lifecycle

The complete lifecycle can be represented as:


14. DjangoPlay Integration

DjangoPlay uses its AuthX integration layer rather than calling internal endpoints directly throughout the application.

The main components are:

text
users/
    services/
        authx_sync.py

authx_client
    AuthXClient

The integration layer provides operations such as:

text
create_identity_and_mirror()
update_identity_and_mirror()
sync_identity()

The resulting architecture is:

text
DjangoPlay UI / API
        │
        ▼
Application Service
        │
        ▼
AuthX Synchronization Service
        │
        ▼
AuthXClient
        │
        │ X-Service-Token
        ▼
AuthX Internal Identity API

This keeps HTTP communication and identity synchronization outside the individual Django views.


15. Error Handling

Consumers should distinguish between authentication failures, validation errors, missing identities, and identity conflicts.

Typical categories include:

Response Meaning
401 Authentication/authorization mechanism requires attention
403 Invalid or missing internal service credential
404 Requested identity does not exist
409 Identity conflict, such as duplicate identity data
422 Request validation failure

For example, an invalid UUID supplied to an identity endpoint can result in a validation response before identity lookup occurs.

This is useful when diagnosing connectivity because a validation response demonstrates that the request reached the AuthX endpoint and passed the service-authentication boundary.


16. Security Requirements

The following rules are mandatory for consumers:

  1. Keep AUTHX_SERVICE_TOKEN server-side.
  2. Never expose the service token to frontend code.
  3. Never commit the service token to source control.
  4. Never query the AuthX database directly from DjangoPlay.
  5. Never duplicate AuthX password hashing logic.
  6. Never store AuthX passwords in DjangoPlay.
  7. Use AuthXClient for internal identity operations.
  8. Treat AuthX as the identity source of truth.
  9. Keep AuthX JWT private keys exclusively inside AuthX.
  10. Maintain a local identity mirror only for application-level requirements.

17. Credential Separation

DjangoPlay and AuthX intentionally have separate database credentials.

text
DjangoPlay
    │
    └── DB_PASSWORD
         │
         └── DjangoPlay PostgreSQL


AuthX
    │
    ├── POSTGRES_USER
    ├── POSTGRES_PASSWORD
    ├── POSTGRES_DB
    ├── DATABASE_URL
    └── DATABASE_URL_SYNC
         │
         └── AuthX PostgreSQL

The DjangoPlay → AuthX service credential is separate:

text
AUTHX_SERVICE_TOKEN

AuthX JWT signing material is also separate:

text
JWT_PRIVATE_KEY
JWT_PUBLIC_KEY

The private signing key must remain exclusively within AuthX.


18. Operational Boundary

In the current DjangoPlay deployment, AuthX runs as a separate identity service.

The production runtime intentionally keeps AuthX locally bound on the application host:

text
127.0.0.1:8100

DjangoPlay communicates with it over the local service boundary.

The public JWT issuer is a separate concept:

text
https://auth.djangoplay.org

Therefore:

text
APP_BASE_URL
    =
where AuthX is reachable

JWT_ISSUER
    =
identity authority asserted by AuthX JWTs

These values do not need to be identical.


19. Example Backend Call

A backend consumer should conceptually perform:

text
AuthXClient
    │
    ├── resolve AuthX base URL
    ├── attach X-Service-Token
    ├── send internal request
    ├── validate HTTP response
    └── return identity data

The consumer should not construct raw database operations or reproduce AuthX's internal identity logic.


20. Summary

The AuthX Internal Identity API provides a controlled backend interface for identity lifecycle management.

Its primary characteristics are:

Area Design
Consumer Trusted backend applications
Authentication X-Service-Token
Credential AUTHX_SERVICE_TOKEN
Identity authority AuthX
Persistence AuthX PostgreSQL
Password hashing AuthX
Identity lookup ID, email, SSO
Updates PUT
Deletion Soft delete
Django integration AuthXClient + synchronization service
Local application identity DjangoPlay mirror
JWT authority AuthX
JWT signing key AuthX only

The fundamental architectural rule is:

AuthX owns identity; DjangoPlay consumes and mirrors identity.