Changelog ¶
All notable changes to this project are documented here.
Unreleased¶
[0.3.1] - 2026-07-14¶
Fixed¶
- Setting defaults are now applied under every server (gunicorn/uWSGI/ASGI), not just
runserver. django-gauth's optional settings (SCOPE,STATE_KEY_NAME,FINAL_REDIRECT_KEY_NAME,GOOGLE_LOGIN_PROMPT,CREDENTIALS_SESSION_KEY_NAME,GOOGLE_AUTH_FINAL_REDIRECT_URL) were previously filled in inside theset_defaultssystem check, which Django only runs for a few management commands — never when a WSGI/ASGI server imports the application object. Undergunicornthe defaults never applied, so runtime code reading e.g.settings.SCOPEcould raiseAttributeError. The defaults are now applied fromAppConfig.ready()(via a new idempotentapply_setting_defaults()), which runs for all entrypoints. Theset_defaultscheck is retained formanage.py checkvalidation.
Documentation¶
-
Documented that the view-protection helpers (
gauth_required,GauthRequiredMixin) support Django native views only, not Django REST Framework. DRF views use a different request/authentication/permission contract, so these helpers may behave incorrectly onAPIView/ViewSet/@api_viewendpoints. The limitation is now noted in the decorators API reference, the troubleshooting guide, and the module docstring, with the DRF-native adapters called out as planned work. -
added the link to django-gauth-samples for better user understanding on the package .
Added¶
- added
AGENTS.mdfile
0.3.0¶
2026-07-09
Added¶
- Django User Integration (issue #85) — an opt-in bridge to Django's own auth system,
so
request.user,@login_required, and the admin recognise Google-authenticated visitors — with nodjango-gauthmodels and zero migrations. Off by default; enable withGOOGLE_USER_INTEGRATION = Trueand registerGoogleAuthBackend. Adds theget_or_create_user_from_id_info()helper,gauth_required/GauthRequiredMixinview guards, fiveGOOGLE_USER_*settings, and amanage.py check(django_gauth.W001–W003). See Django User Integration. - Redirection Schemes (issue #77) — nested & dynamic Google auth out of the box.
login()accepts a?scheme=query parameter (PRESERVE_ORIGIN_QP,PRESERVE_ORIGIN_HP,LANDING_PAGE,DEFAULT) that sends users back to the exact page they authenticated from. Origins are same-origin validated to prevent open-redirect attacks. See Redirection Schemes. - Configurable
login()response type — a?response=parameter selectsredirect(default302) orjson({"redirect_to": ...}) delivery of the authorization URL. The JSON form lets an SPA drive the top-level navigation itself, and is required for thePRESERVE_ORIGIN_HPscheme. - Session Lifecycle Management (issue #86) — keep sessions alive past Google's ~1 hour
ID-token lifetime, plus a clean logout. See
Session Lifecycle.
logout()view (/gauth/logout/) — flushes the session and best-effort revokes the upstream Google token. Mirrorslogin()'s?response=convention (redirect→302,json→{"status": "logged_out"}). Revocation failures never block logout.session_status()probe (/gauth/session) — a JSON endpoint an SPA can poll:{"authenticated": bool, "user": {...} | null}. It transparently refreshes the access token and cachedid_infowhen they've expired but arefresh_tokenexists.get_credentials(request)accessor andrevoke_google_token(token)helper are exported fromdjango_gauth.utilities.- Configurable session policy —
GOOGLE_SESSION_AUTO_REFRESH(defaultTrue),GOOGLE_SESSION_MAX_AGE(absolute cap, defaultNone), andGOOGLE_SESSION_IDLE_TIMEOUT(idle cap, defaultNone) let you choose anything from an indefinite rolling session to forced periodic re-login. Defaults preserve the previous always-refresh behaviour. See Choosing a session policy. - Logout settings —
GOOGLE_TOKEN_REVOKE_ON_LOGOUT(defaultTrue) andGOOGLE_AUTH_LOGOUT_REDIRECT_URL(defaultNone).
Security¶
oauth_statecleared after successful auth —callback()now explicitly removes the OAuth2 CSRF nonce from the session once authentication completes. It is a single-use token and has no purpose after the token exchange; clearing it prevents stale CSRF material from persisting in the authenticated session. Error paths (state-mismatch400,access_deniedredirect) intentionally retain it to allow retry.
Changed¶
GOOGLE_AUTH_FINAL_REDIRECT_URLvalidation — The startup system check now uses URL parsing to validate the configured value. A non-empty string that lacks a scheme or host (e.g. a bare relative path like"/dashboard/") produces anInfo-level system check entry. Empty string andNoneare silently treated as "not configured". Use a fully-qualified URL (https://myapp.example.com/dashboard/) to keep system checks clean.- Session-policy-aware landing page — the built-in
/gauth/index resolves auth state throughget_credentials()(so it agrees with@gauth_requiredand/gauth/session), adds a Logout button, an effective-deadline countdown (earliest of token / max-age / idle), and a targeted "session expired" message naming the governing policy.
Fixed¶
- Scope-reduction crash on re-login —
callback()no longer raisesWarning: Scope has changed …when Google grants fewer scopes than requested (common after a logout that revoked the token); it tolerates the reduced set and logs a warning. - Reliable session recovery —
callback()resets the idle clock on re-login, so a stalegauth_last_activefrom a previously idle/expired session can no longer instantly re-expire the fresh one underGOOGLE_SESSION_IDLE_TIMEOUT. session_status()matches the guards — with Django User integration enabled, itsauthenticatedflag comes fromrequest.user.is_authenticated, agreeing with@gauth_required/@login_required.- Countdown precision — the landing-page timer no longer shows sub-second digits.
v0.2.2¶
2026-06-29
Fixed¶
- Callback scope mismatch —
callback()now usessettings.SCOPEinstead of a hardcoded scope list, preventing "Scope has changed" errors when a customSCOPEis configured. client_secretno longer stored in session —credentials_to_dict()omitsclient_id/client_secret; they are re-injected from settings when rebuildingCredentials.- Public
id_tokenaccessor — readscredentials.id_tokeninstead of the privatecredentials._id_token, avoiding breakage on futuregoogle-authreleases. - Friendly state-mismatch handling —
callback()compares the returnedstatewith the session value and returns a clear400instead of an opaque stack trace. - Callback error-path handling — provider errors (e.g. user clicks Deny →
?error=access_denied) redirect gracefully instead of crashing.
Added¶
- Repository hygiene files:
CONTRIBUTING.md,SECURITY.md,CODE_OF_CONDUCT.md, issue templates, and a pull request template.
v0.2.1¶
2026-06-25
Changed¶
- Removed
google-api-python-clientfrom runtime dependencies (unused) - Removed
mypyfrom runtime dependencies (dev-only tool) - Moved
devandlintextras from[project.optional-dependencies]to[dependency-groups](internal-only, not user-facing) - Fixed
runtests.pyto start coverage beforedjango.setup()for accurate module-level tracking - Repaired corrupted
pipintest-venv(circular import in vendoredpyparsing) - Uncommented
.vscode/in.gitignoreto exclude editor-specific config from version control
Added¶
- Extended test coverage to 99%
- Comprehensive MkDocs documentation with Mermaid diagrams, admonitions, tabs, and annotations
- New docs pages: Installation, Google Cloud Setup, OAuth2 Explained, Architecture, Settings Reference, URL Configuration, UI Customization, Production Deployment, Troubleshooting, API Views/Utilities/Checks, Flows, Changelog
- Detailed
ErrorCodesreference in docs with flowcharts, fix examples, and terminal output previews pdm.lockexplanation section indev.README.mdwith cross-link fromREADME.md- Extended unit tests (
test_coverage_boost.py) raising coverage from 37% → 99%
Removed¶
google-api-python-clientfrom runtime dependencies (confirmed unused in source)mypyfrom runtime dependencies (dev-only tool, remains in[dependency-groups])
v0.2.0¶
Latest
Changed¶
- Improved dependency version constraints with Python version markers
- Enhanced documentation with comprehensive guides and diagrams
Added¶
- System checks for all required settings
- Debug endpoint (when
DEBUG=True) - Origin URL validation for secure redirects
- UI customization via
DJANGO_GAUTH_UI_CONFIG
v0.1.2¶
Added¶
- Initial public release
- Google OAuth2 authentication flow
- Built-in landing page with authentication button
- Session-based credential storage
- Django admin integration for session management
- Support for Django 3.1 — 5.2
- Support for Python 3.9 — 3.12