Profile
This commit is contained in:
@@ -210,6 +210,103 @@ but membership no longer checks directory recreation during login. Preserve the
|
||||
connector mapping for other services; migrating Dex to immutable user IDs is a
|
||||
separate coordinated change, not an automatic part of this release.
|
||||
|
||||
### Self-service account profile
|
||||
|
||||
Signed-in members can choose **Edit profile** from their membership page.
|
||||
Deploy the new membership image, apply migration `0005_profile_email_change`,
|
||||
and deploy the updated static CSS/proxy configuration. No new public settings
|
||||
or credentials are required. Login remains Dex-only: the profile editor reads
|
||||
LDAP **only when opened**, because the configured Dex LDAP connector exposes
|
||||
username/email/name/groups, not arbitrary LDAP attributes. Cached OIDC claims
|
||||
are neither a complete nor a current editable profile. Do not map the gamer tag
|
||||
to `preferred_username` or change `idAttr` to expose it.
|
||||
|
||||
| Profile label | LDAP attribute |
|
||||
| --- | --- |
|
||||
| About you | `description` |
|
||||
| Gamer tag (one value) | `displayName` |
|
||||
| Email address (verified separately) | `mail` |
|
||||
| First name / Last name | `givenName` / `sn` |
|
||||
| Profile photo | `jpegPhoto` |
|
||||
| City/town / State/province | `l` / `st` |
|
||||
| Websites | `labeledURI` |
|
||||
| Mobile numbers / Phone numbers | `mobile` / `telephoneNumber` |
|
||||
| Organizations / Job titles | `o` / `title` |
|
||||
| Postal addresses / Postal codes | `postalAddress` / `postalCode` |
|
||||
| Street addresses / Room numbers | `street` / `roomNumber` |
|
||||
| SSH public keys | `sshPublicKey` |
|
||||
| Password | RFC 3062 Password Modify (never read back) |
|
||||
|
||||
The form preserves existing multi-value attributes. Enter one value per line;
|
||||
separate multiline postal addresses with a blank line. Blank optional fields
|
||||
are removed on save; `sn` remains required by the directory schema. JPEGs are
|
||||
limited to 1 MiB and 4096 pixels per side/16 million pixels, resized to fit 512
|
||||
pixels and reencoded without metadata. Existing photos are sanitized again
|
||||
before private, authenticated delivery. No arbitrary URLs are fetched. Supported
|
||||
SSH keys are Ed25519, RSA >=2048 bits and ECDSA NIST P-256/P-384/P-521; private
|
||||
keys, authorized_keys options and malformed values are rejected.
|
||||
|
||||
**Directory prerequisites:**
|
||||
|
||||
- The service account needs read/search access to the profile attributes above,
|
||||
plus `uid`, `entryUUID`, `objectClass` and `modifyTimestamp`, across the
|
||||
intended account search tree. It never needs read access to `userPassword`.
|
||||
Accounts are pinned to immutable UUIDs; missing/deleted entries do not fall
|
||||
back to a reused username. LDAP unavailability disables editing rather than
|
||||
presenting an empty form that could erase values.
|
||||
- Every write binds with the member's **current LDAP password** and checks that
|
||||
entry's UUID again. Configure directory **self-write ACLs** only for these
|
||||
profile attributes and self Password Modify; do not grant writes to `uid`,
|
||||
`entryUUID`, account DNs, POSIX IDs, group membership or administrative fields.
|
||||
This supports existing Dex users outside the website registration OU without
|
||||
granting the membership service unrestricted directory write permissions.
|
||||
- Install the `ldapPublicKey` auxiliary schema before SSH editing. When a user
|
||||
supplies keys and the class is absent, the application adds **only** the fixed
|
||||
`ldapPublicKey` class in the same modify. Either pre-add that class to editable
|
||||
accounts or permit precisely that self-add with value-scoped `objectClass`
|
||||
ACLs. Never grant arbitrary self-write to `objectClass`. No schema/ACL changes
|
||||
are automatically applied by the website or OpenLDAP role.
|
||||
- OpenLDAP must support critical RFC 4528 assertion controls. Profile/email
|
||||
writes assert UUID and last-modified time, and profile forms carry a signed,
|
||||
one-hour revision to reject stale edits. A server rejecting the critical
|
||||
control must fail closed; do not silently retry without it.
|
||||
- Maintain directory-side unique `mail` and `uid` enforcement across all
|
||||
registrars. A client-side email preflight cannot prevent concurrent claims
|
||||
and may be restricted by self-read ACLs; the server uniqueness overlay is
|
||||
required. Review which services use `mail` as an account/recovery identifier.
|
||||
|
||||
Email is changed separately: the user enters their current password, receives
|
||||
a one-hour verification link at the new mailbox, then signs into the same local
|
||||
account and enters their password again. GET/scanner visits never modify LDAP.
|
||||
Tokens are stored only as hashes, bound to account/LDAP UUID, and consumed once.
|
||||
Confirming replaces **all existing mail values** with the verified address and
|
||||
updates the local contact address; it does not attach another user's billing
|
||||
history. Old Dex/downstream tokens may retain the prior email until refreshed.
|
||||
|
||||
Password changes send current/new passwords through Password Modify as the
|
||||
authenticated user, never a service-account reset or direct `userPassword`
|
||||
write. **Hashing remains OpenLDAP's policy**: no MD5-Crypt hash is generated by
|
||||
the application, no stored hash is exposed, and the application does not force
|
||||
or silently change the server's scheme. A legacy MD5-Crypt directory can still
|
||||
verify current passwords; do not introduce MD5-Crypt as a new application-side
|
||||
hashing scheme. Audit/migrate weak server hashing separately. The existing
|
||||
Argon2 gate for new registration remains unchanged. Password changes sign out
|
||||
the current membership browser; other membership/Dex/service sessions are not
|
||||
automatically revoked—use each service's session controls when necessary.
|
||||
|
||||
All writes are CSRF-protected and rate-limited per account/IP. Passwords and
|
||||
profile form bodies must never be logged by ingress/APM/LDAP debug logging.
|
||||
Profile data can be shared by directory-consuming services: the page is private,
|
||||
but it does not make phone/address/SSH fields private in the directory. Enforce
|
||||
directory read ACLs and tell users what other services can access. TLS defaults
|
||||
are unchanged; the existing explicit plaintext opt-in also exposes profile
|
||||
passwords/data and should not be used on untrusted networks.
|
||||
|
||||
The supplied Kubernetes ingress accepts up to 2 MiB; Apache allows that limit
|
||||
only under `/members/profile/` and retains 256 KiB for other member routes.
|
||||
Mirror the limits at any additional edge proxy. Oversized or invalid uploads
|
||||
must be rejected before reaching image processing.
|
||||
|
||||
### Database ProgrammingError during callback
|
||||
|
||||
`Dex callback rejected kind=ProgrammingError` in older images is a database
|
||||
|
||||
Reference in New Issue
Block a user