Skip to content

Add Basic Auth Support #1089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

JustinMissmahl
Copy link

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: [email protected]
   - 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
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 on lines -30 to +32
# build:
# context: .
build:
context: .
dockerfile: Dockerfile
Copy link
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 on lines +30 to +32
build:
context: .
dockerfile: Dockerfile
Copy link
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 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
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

@@ -92,7 +97,9 @@ services:
# Read more at https://docs.khoj.dev/miscellaneous/telemetry
# - 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
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

@@ -92,7 +97,9 @@ services:
# Read more at https://docs.khoj.dev/miscellaneous/telemetry
# - 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
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

if not state.anonymous_mode:
from khoj.routers.auth import auth_router
if state.controlled_access_mode:
Copy link
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>)

client_id = request.query_params.get("client_id")
if client_id:
# Get the client secret, which is passed in the Authorization header
Copy link
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
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 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
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

Copy link
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

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