Skip to content

Add Basic Auth Support#1089

Closed
JustinMissmahl wants to merge 1 commit intokhoj-ai:masterfrom
JustinMissmahl:controlled-access
Closed

Add Basic Auth Support#1089
JustinMissmahl wants to merge 1 commit intokhoj-ai:masterfrom
JustinMissmahl:controlled-access

Conversation

@JustinMissmahl
Copy link
Copy Markdown

Adds username/password authentication mode for self-hosted instances that want to manage users manually without OAuth providers.

Changes:

Backend:

  • basic_auth.py: Login endpoint and metadata endpoint returning {"google": null}
  • state.py: Added controlled_access_mode flag
  • main.py: CLI flag and env var handling
  • configure.py: Router mounting and auth middleware

Frontend (loginPrompt.tsx):

  • Basic auth detection from metadata response
  • Username/password form with loading/error states
  • Works in both mobile/desktop views
  • Preserves existing OAuth/email flows

Usage:

  1. Enable controlled access mode via:

    • CLI: --controlled-access
    • ENV: KHOJ_CONTROLLED_ACCESS=true
  2. Initial admin credentials:

  3. Managing Users:

Security Notes:

  • Default admin should be changed after first login
  • Each user needs to be manually created by admin
  • No self-registration - controlled environment

Testing:

docker compose up  # Uses KHOJ_CONTROLLED_ACCESS=true
  1. Visit http://localhost:42110 - should show username/password form
  2. Login with admin credentials
  3. Create test user in admin panel
  4. Test login with new user

Adds username/password authentication mode for self-hosted instances that want to manage users manually without OAuth providers.

Changes:

Backend:
- basic_auth.py: Login endpoint and metadata endpoint returning {"google": null}
- state.py: Added controlled_access_mode flag
- main.py: CLI flag and env var handling
- configure.py: Router mounting and auth middleware

Frontend (loginPrompt.tsx):
- Basic auth detection from metadata response
- Username/password form with loading/error states
- Works in both mobile/desktop views
- Preserves existing OAuth/email flows

Usage:
1. Enable controlled access mode via:
   - CLI: --controlled-access
   - ENV: KHOJ_CONTROLLED_ACCESS=true

2. Initial admin credentials:
   - Username: admin@example.com
   - Password: admin

3. Managing Users:
   - Login as admin at http://localhost:42110/server/admin
   - Use Django admin interface to:
     * Create new users
     * Set passwords
     * Manage permissions
   - Users can then login with their credentials at http://localhost:42110

Security Notes:
- Default admin should be changed after first login
- Each user needs to be manually created by admin
- No self-registration - controlled environment

Testing:
```bash
docker compose up  # Uses KHOJ_CONTROLLED_ACCESS=true
```
1. Visit http://localhost:42110 - should show username/password form
2. Login with admin credentials
3. Create test user in admin panel
4. Test login with new user
Copy link
Copy Markdown
Member

@debanjum debanjum left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating a PR to add basic auth support! I've left some comments to simplify the code. Let me know if you have any questions?

Comment thread docker-compose.yml Outdated
Comment on lines +30 to +32
# build:
# context: .
build:
context: .
dockerfile: Dockerfile
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given context: . defaults to dockerfile: Dockerfile, the new dockerfile: Dockerfile line shouldn't be necessary

Comment thread docker-compose.yml
Comment on lines +30 to +32
build:
context: .
dockerfile: Dockerfile
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be commented out by default and the image: config above should be uncommented, so folks can use the pre-built image (instead of having to build the docker image locally)

Comment thread docker-compose.yml Outdated
Comment on lines +95 to +102
command: --host="0.0.0.0" --port=42110 -vv --anonymous-mode --non-interactive
entrypoint: python3 src/khoj/main.py --host=0.0.0.0 --port=42110 -vv --controlled-access --non-interactive
# entrypoint: python3 src/khoj/main.py --host=0.0.0.0 --port=42110 -vv --anonymous-mode --non-interactive
# entrypoint: python3 src/khoj/main.py --host=0.0.0.0 --port=42110 -vv --non-interactive
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabling basic auth via environment variable maybe better. That is by adding - ENABLE_CONTROLLED_ACCESS=True in the environment section for the Khoj service above

Comment thread docker-compose.yml
# - KHOJ_TELEMETRY_DISABLE=True
# Comment out this line when you're using the official ghcr.io/khoj-ai/khoj-cloud:latest prod image.
command: --host="0.0.0.0" --port=42110 -vv --anonymous-mode --non-interactive
entrypoint: python3 src/khoj/main.py --host=0.0.0.0 --port=42110 -vv --controlled-access --non-interactive
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can revert this be a command as the Dockerfile sets the ENTRYPOINT to python3 src/khoj/main.py already

Comment thread docker-compose.yml
# - KHOJ_TELEMETRY_DISABLE=True
# Comment out this line when you're using the official ghcr.io/khoj-ai/khoj-cloud:latest prod image.
command: --host="0.0.0.0" --port=42110 -vv --anonymous-mode --non-interactive
entrypoint: python3 src/khoj/main.py --host=0.0.0.0 --port=42110 -vv --controlled-access --non-interactive
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should default to anonymous mode for self-hosting users in my opinion. Multi-user setups for self-hosting users is not expected to be default

Comment thread src/khoj/configure.py
# Add auth router if not in anonymous mode
if not state.anonymous_mode:
from khoj.routers.auth import auth_router
if state.controlled_access_mode:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same ordering of conditionals comment as above. Let's check for OAuth first (i.e if not state.controlled_access_mode <add_oauth_router> else: <add_basic_auth_router>)

Comment thread src/khoj/configure.py Outdated
# Handle WhatsApp client
client_id = request.query_params.get("client_id")
if client_id:
# Get the client secret, which is passed in the Authorization header
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep this and the comment below?

@@ -4,38 +4,38 @@

"@alloc/quick-lru@^5.2.0":
version "5.2.0"
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
resolved "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be reverted to use yarn instead of npm, e.g yarn install

Comment thread Dockerfile
Comment on lines +37 to +41
django==5.0.10 \
fastapi==0.115.6 \
uvicorn==0.30.6 \
pydantic==2.10.5 \
starlette==0.41.3
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear why django and other package dependencies are being installed here instead of in pyproject.toml which also installs these dependencies

Comment thread Dockerfile
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should revert changes to this file, they seem tangential to this PR

@debanjum debanjum force-pushed the master branch 2 times, most recently from 535f353 to 0f0cfba Compare July 9, 2025 06:27
@debanjum
Copy link
Copy Markdown
Member

debanjum commented Jan 6, 2026

Closing this PR for now. It has gone stale and comments haven't been resolved.

@debanjum debanjum closed this Jan 6, 2026
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.

2 participants