KolektivComputer / KolektivComputer/kalendee
LDAP M1: configuration and directory bind login
- Dominant language
- Kotlin
- Stars
- 0
- Forks
- 0
- Avg merge
- 11h 20m
- Merged PRs (30d)
- 23
Description
## Context
Self-hosted and enterprise deployments need to authenticate against an existing directory instead of managing per-user passwords. M1 adds HOCON `auth.ldap.*` configuration and a `UserDirectory` seam in `AuthService.login`, validating credentials with an LDAP bind and failing closed when the directory is unavailable. Local login, throttling, and sessions stay as they are, so enabling LDAP is additive and reversible.
## Tasks
- [ ] `auth.ldap.*` config in `application.conf` + examples: `enabled`, `url`, `baseDn`, `bindDn`, `bindPassword` (`${?KALENDEE_LDAP_BIND_PASSWORD}`), user filter, `startTls`, timeouts
- [ ] `UserDirectory` interface with a no-op default and an UnboundID-based `LdapDirectory`
- [ ] Wire the directory into `AuthService.login` (`AuthService.kt:173`) without changing local-password semantics
- [ ] Fail closed: directory outage/bind errors never authenticate; generic failure message, no user enumeration, no credential logging
- [ ] Attribute mapping for username/email/display name, case normalization
- [ ] Tests with the UnboundID in-memory directory server: success, wrong password, unknown user, directory down, StartTLS option
- [ ] Docs: `application.conf.example` + `DEVELOPING.md`
## References
- `server/src/main/kotlin/dev/kolektiv/kalendee/auth/AuthService.kt:173` — `login`
- `server/src/main/kotlin/dev/kolektiv/kalendee/auth/AuthSettings.kt`
- `server/src/main/resources/application.conf`, `application.conf.example`
- `GOALS.md` — HOCON configuration rules
- `docs/external-calendars.md` — identity/email-matching context
## Dependencies
- None hard; independent of `feat/oauth-foundation`.
- M2 (#10) builds on this; keep the seam source-neutral (`local`/`ldap`/OAuth) so `user_identities` can be shared.
Contributor guide
Assessment
This issue has not been assessed yet.