--- 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.**