---
since: 1.1.1
---
# 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.
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
```mermaid
flowchart LR
APP["DjangoPlay
Backend Application"]
CLIENT["AuthXClient
HTTP client"]
AUTH["AuthX
Identity Service"]
DB[("AuthX PostgreSQL
Identity Store")]
TOKEN["AUTHX_SERVICE_TOKEN
Backend credential"]
APP --> CLIENT
CLIENT -->|"X-Service-Token"| AUTH
TOKEN -.->|"Authentication"| AUTH
AUTH --> DB
classDef app fill:#e5f6f1,stroke:#159a7a,stroke-width:2px,color:#075d4b
classDef auth fill:#fceee8,stroke:#d65a2a,stroke-width:2px,color:#7d321c
classDef db fill:#eeeeff,stroke:#5a55c9,stroke-width:2px,color:#403b91
classDef credential fill:#f5f3ed,stroke:#777,stroke-width:1px,color:#444
class APP,CLIENT app
class AUTH auth
class DB db
class TOKEN credential
````
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 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:
```
---
# 6. Create Identity
## Request
```http
POST /internal/identities
X-Service-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:
```
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:
```
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=
X-Service-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:
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:
```
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:
```mermaid
flowchart TD
CREATE["Create Identity"]
ACTIVE["Active Identity"]
UPDATE["Update Identity"]
VERIFY["Verification / Status Changes"]
DELETE["Soft Delete"]
RETAINED["Retained Identity Record"]
CREATE --> ACTIVE
ACTIVE --> UPDATE
UPDATE --> ACTIVE
ACTIVE --> VERIFY
VERIFY --> ACTIVE
ACTIVE --> DELETE
DELETE --> RETAINED
classDef action fill:#e6f1fb,stroke:#2474b5,stroke-width:2px,color:#174d7a
classDef active fill:#e5f6f1,stroke:#159a7a,stroke-width:2px,color:#075d4b
classDef deleted fill:#fceee8,stroke:#d65a2a,stroke-width:2px,color:#7d321c
class CREATE,UPDATE,VERIFY action
class ACTIVE active
class DELETE,RETAINED deleted
```
---
# 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.**