Skip to content

Replace Google OAuth with generic OAuth/OIDC provider support#1283

Open
tomaszzmuda wants to merge 2 commits intokhoj-ai:masterfrom
tomaszzmuda:generic_oauth
Open

Replace Google OAuth with generic OAuth/OIDC provider support#1283
tomaszzmuda wants to merge 2 commits intokhoj-ai:masterfrom
tomaszzmuda:generic_oauth

Conversation

@tomaszzmuda
Copy link

@tomaszzmuda tomaszzmuda commented Mar 19, 2026

Problem

Khoj authentication is hardcoded to Google Sign-In only. Self-hosted users who use other identity providers (Authentik, Auth0, Keycloak, etc.) cannot use OAuth at all and are forced to use magic links or anonymous mode.

Solution

Replace the Google-specific OAuth implementation with a generic OAuth 2.0 / OpenID Connect system configurable via environment variables. Any OIDC-compliant provider works out of the box.

⚠️ Breaking: irreversible migration

Migration 0102_remove_googleuser drops the GoogleUser table. Once applied, you cannot roll back to a version that uses GoogleUser.

Migration 0101 copies all existing Google auth data into the new OAuthAccount model before the table is removed, so no user data is lost during upgrade.

Back up your database before running migrations.

Configuration

Required:

Variable Description
GENERIC_OAUTH_ENABLED Set to True to enable
GENERIC_OAUTH_CLIENT_ID OAuth client ID
GENERIC_OAUTH_CLIENT_SECRET OAuth client secret

Endpoints (one of the two options is required):

Option Variable Description
A (recommended) GENERIC_OAUTH_ISSUER OIDC issuer URL — auto-discovers all endpoints
B GENERIC_OAUTH_AUTHORIZATION_ENDPOINT Manual auth endpoint
B GENERIC_OAUTH_TOKEN_ENDPOINT Manual token endpoint

Without at least one endpoint option, OAuth login will not work.

Optional:

Variable Description Default
GENERIC_OAUTH_PROVIDER_NAME Display name for login button OAuth
GENERIC_OAUTH_BUTTON_LABEL Custom button label Continue with {name}
GENERIC_OAUTH_SCOPE OAuth scopes openid profile email
GENERIC_OAUTH_USERINFO_ENDPOINT Userinfo endpoint (if no issuer) -
GENERIC_OAUTH_JWKS_URI JWKS URI (if no issuer) -

Set redirect URI in your provider to: https://your-khoj-domain/auth/oauth/oauth

Changes

Backend

  • New OAuthAccount model (replaces GoogleUser) with provider-agnostic fields and raw_info JSON for full userinfo storage
  • New oauth_config.py — reads GENERIC_OAUTH_* env vars, supports OIDC discovery and manual endpoint modes
  • Refactored auth.py — unified /auth/login/{provider} and /auth/oauth/{provider} endpoints, uses Authlib's built-in userinfo() instead of manual HTTP calls
  • Updated adapters: get_or_create_user_oauth, get_user_by_oauth, create_user_by_oauth
  • Registered OAuthAccount in Django admin
  • Fixed sync update_or_create → async aupdate_or_create in OAuth account creation
  • Removed httpx dependency from auth module

Frontend

  • Removed GoogleSignIn.tsx component and loginPrompt.module.css
  • loginPrompt.tsx now dynamically renders login buttons for all configured providers
  • Supports GENERIC_OAUTH_BUTTON_LABEL for custom button text
  • Cleaned stale accounts.google.com entries from CSP headers

Documentation

  • Updated authentication.mdx with generic OAuth/OIDC setup guide, examples for Google and Authentik
  • Updated privacy docs to reference generic OAuth instead of Google SSO

Tests

  • Added tests/test_oauth.py — 28 tests covering config helpers, database adapters, userinfo extraction, and user name/photo fallbacks

Backward Compatibility

  • ✅ Existing Google users are migrated automatically via data migration
  • ✅ Google still works — just configure it as an OIDC provider with GENERIC_OAUTH_ISSUER=https://accounts.google.com
  • ⚠️ Old GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET env vars are no longer used — must switch to GENERIC_OAUTH_* vars
  • ❌ Cannot roll back past migration 0102 — GoogleUser table is dropped

How it works:

  GENERIC_OAUTH_ENABLED: "True"
  GENERIC_OAUTH_ISSUER: "https://authentik.contoso.net/application/o/<slug>/"
  GENERIC_OAUTH_PROVIDER_NAME: "Authentik"
  GENERIC_OAUTH_CLIENT_ID: myclientid
  GENERIC_OAUTH_CLIENT_SECRET: mysecret
image

I set it as draft for now cause I haven't tested all paths - it works with Authentik but I need to check Google and if migration from Google works properly.

---EDIT---
I've tested Google and Authentik integration and migration from Google to Authentik and everything is good.
This is ready to be merged.

@tomaszzmuda tomaszzmuda marked this pull request as ready for review March 20, 2026 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant