Skip to content

feat: OIDC Docker fix (discovery_url + endpoint rewriting) + auto-create database + entry CRUD #320

Closed

Description

@allamiro

Problem

Two independent problems found during end-to-end OIDC/Keycloak testing in Docker Compose:

1. OIDC Docker split-brain — token exchange fails with Connection refused

When the app container reaches Keycloak via an internal Docker hostname (e.g. keycloak:8180) while the browser reaches it via localhost:8180, Keycloak's --hostname flag causes it to return all endpoint URLs (including token_endpoint and jwks_uri) using the external hostname in every discovery document — even when the document is fetched from the internal URL.

The app then tries to POST to http://localhost:8180/token from inside its container → Connection refused.

Additionally, the openidconnect crate's discover_async enforces that the discovery URL's origin matches the issuer, making it impossible to use separate internal/external hostnames without a workaround.

2. No way to create entries or bootstrap a database through the web UI

The web interface was read-only. Users had to manage the .kdbx file on the desktop and restart the stack to add entries.

Fix

OIDC Docker fix

  • New optional discovery_url config field: fetch the OIDC discovery document from an internal URL (e.g. http://keycloak:8180/...) while validating tokens against the external issuer (e.g. http://localhost:8180/...).
  • After fetching, server-to-server endpoint URLs (token_endpoint, jwks_uri, userinfo_endpoint, etc.) are rewritten to use the internal host so the app can reach them. Browser-facing URLs (authorization_endpoint, end_session_endpoint) are left pointing at the external host.
  • The JWKS is fetched explicitly from the (rewritten) jwks_uri since raw JSON deserialization of the discovery document does not populate the JWKS (openidconnect marks it #[serde(skip)]).
  • Keycloak test realm updated to include http://localhost:8088/callback_user_auth as a valid redirect URI.

Auto-create database

If the configured .kdbx path does not exist when the user first unlocks the vault, a new empty KeePass 4 database is created with the provided master password and written to that path automatically.

Entry CRUD + save to disk

  • POST /api/v1/entry — create a new entry in a group
  • PUT /api/v1/entry — update an existing entry
  • DELETE /api/v1/entry — delete an entry
  • POST /api/v1/save_db — flush the current in-memory database back to the .kdbx file (requires re-entering the master password)
  • Frontend: New Entry inline form in the group panel, Delete button per entry, Save button in the navbar.

Config example

OIDC:
  issuer: 'http://localhost:8180/realms/keepass'
  # Only needed in Docker where app and browser reach the provider via different hostnames:
  discovery_url: 'http://keycloak:8180/realms/keepass/.well-known/openid-configuration'
  client_id: 'keepass4web'
  client_secret: 'secret'

Activity

  1. added 3 commits that reference this issue on Aug 26, 2026
    1ebb2aa
    89cbee9
    367f222
  2. lixmal commented on Aug 27, 2026

    @lixmal
    Owner

    Done across #315 and #326: discovery_url with the endpoint rewriting that keeps the browser facing endpoints on the external host, a database created when none exists, and entry CRUD. #315 also checks that a document fetched from discovery_url declares the configured issuer, so the fetch address stays an internal detail rather than deciding which keys tokens are verified with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions