fix(auth): the wiki-index BasicAuth credentials read the API again #15

Merged
k.renner merged 1 commits from feat/basic-auth-machines into main 2026-10-19 14:13:53 +00:00
Member

Fixes a regression from #14. External agents reach the wiki through wiki-index.renner.uno with BasicAuth only. Since #14 the read API also wanted an OIDC session or an API key, so they got 401.

Change: the service checks Authorization: Basic itself, against the same htpasswd lines Traefik's wiki-api-basic-auth middleware uses.

  • Auth:Basic:UsersPath is a file, or a mounted Secret directory where every visible key is read, the same way Traefik reads every key of an Opaque Secret.
  • This is a password check in the service, not trust in a proxy: the header proves nothing unless the password matches the hash.
  • Hash formats: bcrypt ($2a$/$2b$/$2y$, via BCrypt.Net-Next 4.2.1), Apache MD5 ($apr1$, implemented here and checked against the Traefik docs example and openssl passwd -apr1) and SHA1 ({SHA}). Any other format authenticates nobody.
  • Scope: BasicAuth can read only. Writes still need an API key and the UI still needs an OIDC login.
  • Without UsersPath the scheme authenticates nobody, so this can merge before or after the homelab mount PR (linked below).

Tests: dotnet test passes locally, 154/154. Covered:

  • all three hash formats read the API;
  • a wrong password, an unknown user, an empty password, and a user found only in a hidden Secret entry each get 401;
  • BasicAuth can't write and doesn't open the UI.
**Fixes a regression from #14.** External agents reach the wiki through wiki-index.renner.uno with BasicAuth only. Since #14 the read API also wanted an OIDC session or an API key, so they got 401. **Change:** the service checks `Authorization: Basic` itself, against the same htpasswd lines Traefik's `wiki-api-basic-auth` middleware uses. - `Auth:Basic:UsersPath` is a file, or a mounted Secret directory where every visible key is read, the same way Traefik reads every key of an Opaque Secret. - This is a password check in the service, not trust in a proxy: the header proves nothing unless the password matches the hash. - **Hash formats:** bcrypt (`$2a$`/`$2b$`/`$2y$`, via BCrypt.Net-Next 4.2.1), Apache MD5 (`$apr1$`, implemented here and checked against the Traefik docs example and `openssl passwd -apr1`) and SHA1 (`{SHA}`). Any other format authenticates nobody. - **Scope:** BasicAuth can read only. Writes still need an API key and the UI still needs an OIDC login. - Without `UsersPath` the scheme authenticates nobody, so this can merge before or after the homelab mount PR (linked below). **Tests:** `dotnet test` passes locally, 154/154. Covered: - all three hash formats read the API; - a wrong password, an unknown user, an empty password, and a user found only in a hidden Secret entry each get 401; - BasicAuth can't write and doesn't open the UI.
hermes-bot added 1 commit 2026-10-19 14:07:26 +00:00
fix(auth): the wiki-index BasicAuth credentials read the API again
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
50fb31b950
#14 put the read API behind a session or an API key. External agents
reach the wiki through wiki-index.renner.uno with BasicAuth only, and
since #14 they got 401: a regression.

The service now checks `Authorization: Basic` itself against the same
htpasswd lines Traefik's wiki-api-basic-auth middleware uses
(Auth:Basic:UsersPath: a file, or a mounted Secret directory where every
visible key is read, as Traefik reads every key of an Opaque Secret).
This is a credential check in the service, not trust in a proxy: the
header proves nothing unless the password matches the hash.

- Hash formats Traefik accepts: bcrypt ($2a$/$2b$/$2y$, BCrypt.Net-Next
  4.2.1), Apache MD5 ($apr1$, implemented here and checked against the
  Traefik docs example and `openssl passwd -apr1`), SHA1 ({SHA}). Any
  other format authenticates nobody.
- The identity is a machine named after the BasicAuth user.
- Policy "read" accepts it; "write" stays API-key only, and the UI stays
  OIDC only.
- A verified (user, password, hash) triple is cached in memory, so bcrypt
  costs once per process.
- With no UsersPath configured the scheme authenticates nobody, so this
  image is safe before the deployment mounts the Secret.

Tests: all three hash formats read the API; a wrong password, an unknown
user, an empty password and a user found only in a hidden Secret entry
are 401; BasicAuth cannot write and does not open the UI.
k.renner merged commit fbd5a2529a into main 2026-10-19 14:13:53 +00:00
k.renner deleted branch feat/basic-auth-machines 2026-10-19 14:13:53 +00:00
Sign in to join this conversation.