--- since: 1.1.1 --- # DjangoPlay — AuthX Troubleshooting Guide --- ## 1. Overview This document contains troubleshooting procedures for the DjangoPlay integration with **AuthX**. It focuses on problems that can occur at the boundary between the DjangoPlay web application and the AuthX identity service, including: * Authentication failures * Login and SSO redirect problems * HTTP `401` / `403` responses * AuthX connectivity problems * Credential and secret mismatches * Password hashing compatibility * Request/response debugging * Configuration verification * Service and deployment diagnostics Some sections document **previously investigated issues**. These are retained because they provide useful diagnostic procedures for future development and deployment. --- # 2. Authentication Request Flow The basic integration path is: ```text Browser │ ▼ DjangoPlay │ │ Authentication / SSO request ▼ AuthX │ │ Identity response ▼ DjangoPlay │ ▼ Authenticated Session ``` When authentication fails, determine which boundary is failing before changing application code. --- # 3. First-Level Diagnostics When an AuthX-related problem occurs, check the following in order. ### 3.1 Confirm AuthX is reachable From the DjangoPlay host: ```bash curl -i ``` Verify: * DNS resolution * Network connectivity * Correct port * HTTP/HTTPS availability * AuthX service availability If the connection itself fails, investigate infrastructure before debugging Django authentication code. --- ### 3.2 Verify DjangoPlay configuration Check the environment/configuration used by the running Django process. Important values include: ```text AUTHX_BASE_URL AUTHX_CLIENT_ID AUTHX_CLIENT_SECRET ``` Do **not** print secret values into logs. Instead, verify that: * The variable exists. * The expected environment is loaded. * The value is not accidentally empty. * The Django process has been restarted after configuration changes. --- ### 3.3 Verify the running environment A common source of confusion is debugging one environment while Django is running with another configuration. Confirm: ```bash python manage.py check ``` and inspect the effective settings/configuration through safe diagnostic output. For systemd deployments, also inspect: ```bash sudo systemctl status djangoplay sudo journalctl -u djangoplay -n 100 --no-pager ``` For Celery-related authentication workflows: ```bash sudo systemctl status djangoplay-celery sudo journalctl -u djangoplay-celery -n 100 --no-pager ``` --- # 4. HTTP 401 vs 403 Distinguish authentication failure from authorization failure. | Status | Meaning | | --------------------------- | --------------------------------------------------------------------- | | `401 Unauthorized` | Authentication credentials are missing, invalid, expired, or rejected | | `403 Forbidden` | The request reached the application but access was denied | | `404 Not Found` | Endpoint/path/routing problem | | `422 Unprocessable Entity` | Request reached validation but supplied data was rejected | | `500 Internal Server Error` | Application-side failure | A `403` should therefore **not automatically be treated as an invalid password problem**. --- # 5. Debugging an AuthX 403 A previous DjangoPlay/AuthX investigation involved an HTTP `403` response. The useful diagnostic sequence is: ```text 403 Response │ ▼ Is request reaching AuthX? │ ├── No → DjangoPlay routing/network/configuration │ └── Yes │ ▼ Are required authentication headers present? │ ▼ Are credentials/client configuration correct? │ ▼ Is the requested AuthX endpoint correct? │ ▼ Is the authenticated identity allowed to perform this operation? ``` ### Diagnostic checklist Inspect the actual request being sent by DjangoPlay: * HTTP method * URL/path * Request headers * Authentication mechanism * Request body * Content type * Response status * Response body * AuthX server logs Never log secrets or bearer tokens in plaintext. For temporary debugging, log only safe metadata such as: ```text AuthX request: method=POST endpoint=/... status=403 ``` --- ## 5.1 Compare direct and application requests When possible, compare: ```text Working direct request │ ▼ AuthX ``` against: ```text DjangoPlay request │ ▼ AuthX ``` Compare: * HTTP method * URL * Headers * Payload * Content type * Client identity * Authentication mechanism This frequently identifies integration problems faster than inspecting Django views. --- # 6. Credential / Secret Verification Authentication failures can be caused by credentials that appear correct but are not the credentials actually used by the running process. Check: ```bash systemctl show djangoplay --property=Environment ``` or inspect the service configuration without exposing secrets. Also verify: ```text Django configuration │ ▼ Environment variables │ ▼ Running systemd process │ ▼ AuthX request ``` Restart the application after changing service-level configuration: ```bash sudo systemctl restart djangoplay ``` --- # 7. Password Hashing Compatibility A previous AuthX integration investigation exposed a password-hashing compatibility concern. The important diagnostic principle is: > **Password verification must use a hashing scheme compatible with the system that originally created the password hash.** Do not assume that two Django/Python systems can verify each other's passwords merely because both use a conceptually similar password-hashing mechanism. When investigating password verification: ### Step 1 — Identify the hash format Determine: * Algorithm * Encoding * Salt format * Parameters/work factor * Stored hash structure For example, a Django-style encoded password commonly contains algorithm and parameters as part of the encoded value. ### Step 2 — Identify the producing system Determine whether the password was originally created by: ```text DjangoPlay ``` or: ```text AuthX ``` or another identity system. ### Step 3 — Verify using the producing system The safest test is to use the same password-verification implementation that created the stored hash. ### Step 4 — Do not manually transform hashes Do not: * Re-hash an existing hash as though it were a plaintext password. * Modify salts manually. * Strip algorithm metadata. * Assume SHA-256 equality implies password compatibility. Password hashing is intentionally designed so that the stored representation is not simply a reversible password value. --- # 8. SHA-256 Diagnostic Investigation During earlier debugging, SHA-256 values were used as **diagnostic fingerprints** to compare values without printing sensitive plaintext. This technique can be useful when verifying whether two values are identical: ```python import hashlib digest = hashlib.sha256(value.encode()).hexdigest() print(digest) ``` For example: ```text Value A → SHA-256 → Value B → SHA-256 → ``` If the fingerprints match, the original values match. If they differ, the original values differ. ### Important A SHA-256 fingerprint is useful for **comparison**, not password verification. Do not replace a password-hashing algorithm with plain SHA-256. Do not log plaintext passwords, API secrets, session tokens, or bearer tokens merely to diagnose an authentication problem. --- # 9. Login / Redirect Problems DjangoPlay contains custom authentication and SSO redirect handling. When login succeeds but the user lands on the wrong page, inspect: ```text Login Request │ ▼ AuthX / Social Provider │ ▼ DjangoPlay callback │ ▼ Redirect Resolution │ ├── next parameter ├── from parameter └── default login redirect ``` For DjangoPlay, redirect behavior may depend on: * `next` * `from` * authentication provider * requested application page * default login redirect Check the actual query parameters received by Django rather than assuming the browser initiated the expected redirect. --- # 10. Google / SSO Troubleshooting For SSO failures, isolate the provider from AuthX. ```text Browser │ ▼ Google / OAuth Provider │ ▼ AuthX │ ▼ DjangoPlay ``` Check: 1. OAuth redirect URI 2. Client configuration 3. AuthX callback configuration 4. DjangoPlay callback handling 5. Existing identity mapping 6. Session creation 7. Final redirect A successful OAuth provider response does not necessarily mean the DjangoPlay/AuthX onboarding flow completed successfully. --- # 11. Celery-Related Authentication Problems Some authentication workflows involve asynchronous email processing. For example: ```text DjangoPlay │ ▼ Celery Task │ ▼ Email Provider ``` If an email such as password reset or verification mail is incorrect or not delivered: Check: ```bash sudo systemctl status djangoplay-celery ``` Then: ```bash sudo journalctl -u djangoplay-celery -n 200 --no-pager ``` Verify that Celery is running with the **same environment/configuration** expected by DjangoPlay. A common diagnostic mistake is to verify configuration in the web process while the Celery worker is running with stale or different configuration. --- # 12. Email Link / Wrong Host or Port When authentication emails contain an incorrect URL, inspect the application URL construction rather than the email template alone. Trace: ```text Environment │ ▼ Site configuration │ ▼ URL builder │ ▼ AuthX / Django authentication flow │ ▼ Email template ``` Verify: * Protocol * Host * Port * Environment * Public application URL This is particularly important in local development where DjangoPlay may run behind custom hosts or non-standard ports. --- # 13. Database Diagnostics If authentication succeeds at AuthX but fails while creating or retrieving a DjangoPlay identity/session, inspect the Django database. Run: ```bash python manage.py check python manage.py showmigrations ``` If necessary: ```bash python manage.py migrate --plan ``` Then inspect application logs for: * Integrity errors * Missing records * Foreign-key failures * Duplicate identity records * Transaction failures Do not modify production authentication data manually until the owning service and data model are understood. --- # 14. Configuration Cache / Restart Issues After changing authentication configuration, restart the affected processes. For production: ```bash sudo systemctl restart djangoplay sudo systemctl restart djangoplay-celery ``` Then verify: ```bash sudo systemctl status djangoplay sudo systemctl status djangoplay-celery ``` Configuration problems can otherwise appear to persist even after the underlying environment has been corrected. --- # 15. Recommended Debugging Order When investigating an AuthX problem, use this order: ```text 1. Browser / Client │ ▼ 2. DjangoPlay endpoint │ ▼ 3. DjangoPlay logs │ ▼ 4. AuthX request │ ▼ 5. AuthX response │ ▼ 6. AuthX logs │ ▼ 7. Database / identity state │ ▼ 8. Celery / email infrastructure ``` This avoids changing application code before establishing which layer is actually failing. --- # 16. Safe Diagnostic Logging Authentication debugging must not expose secrets. ### Safe to log ```text HTTP method Endpoint Status code Request ID User ID Non-sensitive configuration names Execution duration Exception type ``` ### Do not log ```text Passwords API keys Client secrets OAuth client secrets Bearer tokens Session cookies Authorization headers Private keys Unencrypted credential values ``` When deeper debugging is necessary, use fingerprints or redacted values rather than plaintext secrets. --- # 17. Production Debugging Checklist Before modifying production code, collect: ```text [ ] DjangoPlay version / commit [ ] AuthX version / commit [ ] Environment [ ] Endpoint [ ] HTTP method [ ] HTTP status [ ] Request ID / correlation ID [ ] Django logs [ ] AuthX logs [ ] Relevant Celery logs [ ] Database error, if any [ ] Configuration variable names [ ] Whether the issue reproduces locally ``` Avoid changing multiple authentication components simultaneously. Change one layer, reproduce, and record the result. --- # 18. Historical Investigation Notes The following investigations are retained intentionally because they provide useful examples for future debugging: ### HTTP 403 investigation A `403` response was investigated by tracing the request boundary between DjangoPlay and AuthX rather than assuming that the user's credentials were invalid. The investigation demonstrated the importance of distinguishing: ```text Authentication failure ``` from: ```text Authorization / request-policy failure ``` The issue was subsequently resolved. The diagnostic procedure above should be reused if a similar response appears in the future. ### Password hashing investigation An earlier integration blocker involved compatibility between password-hashing representations. The lesson is that password verification must remain compatible with the identity authority responsible for creating the password hash. Hash strings should not be treated as interchangeable simply because they originate from systems using similar cryptographic terminology. ### SHA-256 comparison SHA-256 fingerprints were used during investigation to safely compare values without repeatedly exposing the underlying value. This remains a useful debugging technique for non-password secrets and controlled diagnostic comparisons, but **plain SHA-256 must not be used as a password-storage replacement**. --- # 19. Escalation Boundary If the problem cannot be isolated within DjangoPlay, determine whether it belongs to: ```text DjangoPlay │ ├── Configuration ├── Authentication integration ├── Session handling ├── Application logic └── Database │ ▼ AuthX │ ├── Identity ├── Credentials ├── SSO └── Authentication policy ``` The owning system should be identified before applying a fix. --- ## 20. Related Documentation For the broader architecture, refer to: * **Authentication Architecture** * **DjangoPlay–AuthX Integration** * **Security Architecture** * **Infrastructure Architecture** * **Deployment** * **Configuration** * **Application Architecture** The detailed documentation is maintained in the DjangoPlay documentation site. [DjangoPlay Documentation](https://docs.djangoplay.org/projects/djangoplay-web/) --- ## 21. Summary AuthX troubleshooting should follow a **boundary-first diagnostic approach**. Start with connectivity and configuration, then trace the request through DjangoPlay, AuthX, identity state, and asynchronous infrastructure. The most important lessons from previous investigations are: 1. A `403` is not automatically a password problem. 2. Authentication and authorization failures must be distinguished. 3. Password-hashing formats must remain compatible with their producing identity system. 4. SHA-256 fingerprints can assist controlled value comparison but are not a password-hashing substitute. 5. Never expose authentication secrets in diagnostic logs. 6. Web and Celery processes must be checked independently. 7. Configuration changes require restarting the affected processes. 8. Debug the failing boundary before changing application code.