fix(auth): canonical username is the attribute value the user matched (Auth-009)
ExtractUserName returned the first value of a possibly multi-valued UserNameAttribute (default cn), so jsmith could sign in as "John Smith" depending on server ordering. It now prefers the value equal to the typed name ignoring case (still canonicalising case) and falls back to the first value only when none matches. (scadaproj#46) Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
| Last reviewed | 2026-11-09 (re-review; baseline 2026-06-01 at `5f75cd4`) |
|
||||
| Reviewer | Claude (2026-11-09 re-review, scadaproj#15; baseline: Claude automated) |
|
||||
| Commit reviewed | `91fb2b4` |
|
||||
| Open findings | 3 |
|
||||
| Open findings | 2 |
|
||||
|
||||
## Summary
|
||||
|
||||
@@ -429,7 +429,7 @@ I verified this live against a SQL Server 2022 container:
|
||||
| Severity | Low |
|
||||
| Priority | P3 |
|
||||
| Category | Correctness & logic bugs |
|
||||
| Status | Open |
|
||||
| Status | Resolved |
|
||||
| Location | `ZB.MOM.WW.Auth/src/ZB.MOM.WW.Auth.Ldap/LdapAuthService.cs:437` |
|
||||
|
||||
**Description**
|
||||
@@ -454,6 +454,20 @@ fake connection: typed `jsmith` returned `Username == "John Smith"`.
|
||||
Prefer the attribute value that equals the typed (normalised) name under `OrdinalIgnoreCase`, which still
|
||||
canonicalises case. Fall back to `values[0]` only when no value matches. Add a multi-valued-attribute test.
|
||||
|
||||
**Resolution**
|
||||
|
||||
Resolved 2026-11-09 (scadaproj#46, Auth `0.4.4`, unpublished). Re-verified through the fake connection: with
|
||||
`cn: ["John Smith", "jsmith"]`, typed `jsmith` returned `Username == "John Smith"`. `ExtractUserName` now returns the
|
||||
attribute value that equals the typed (normalised) name under `OrdinalIgnoreCase`. That keeps 0.4.1's case
|
||||
canonicalisation, so typed `jsmith` against `JSmith` still returns `JSmith`. Only when no value matches does it fall
|
||||
back to the first non-blank value, and then to the typed name, as 0.4.1 did. Both bind modes go through
|
||||
`SucceedFromEntry`, so both are covered.
|
||||
|
||||
Tests (`LdapAuthServiceTests`):
|
||||
- `Username_FromAMultiValuedAttribute_IsTheValueTheUserMatched` fails pre-fix.
|
||||
- `..._StillTakesTheDirectorysCase` fails pre-fix.
|
||||
- `Username_FallsBackToTheFirstValue_WhenNoValueMatchesTheTypedName` is a guard that passes both ways.
|
||||
|
||||
### Auth-010 — `ApiKeyVerifier` lets store exceptions escape despite its "only exception path is cancellation" contract
|
||||
|
||||
| | |
|
||||
|
||||
Reference in New Issue
Block a user