Commit graph

6 commits

Author SHA1 Message Date
e76259cca2 Richer Client/Details view for admin triage
The previous Details view was a sketch: a handful of fields, a
half-broken <dt>/<dd> pairing around FrontChannelLogoutUri, and
nothing about token lifetimes, security flags, or collection sizes.
For an admin trying to understand what a given OIDC client actually
does (and why a login flow fails), that meant bouncing between the
list page and the edit page to read off half a dozen scalars.

The new view surfaces the same property surface as Edit.cshtml, but
read-only:

- Two-column layout: Identity + Security on the left, Tokens + Logout
  on the right. Security flags render as a Bootstrap 3 label
  (green/grey) so an admin can spot at a glance whether PKCE, consent,
  offline access, etc. are on or off.
- Lifetimes are formatted in human units (5 min, 2 h, 30 d) instead of
  raw seconds. Zero / unset is rendered as 'default' or '—' to avoid
  the silent-zero footgun.
- Enum-valued columns (AccessTokenType, RefreshTokenUsage,
  RefreshTokenExpiration) are rendered as their integer value since
  that's the on-disk representation in IdentityServer8.
- The Collections list is mirrored from Edit.cshtml so every nested
  editor (scopes, grant types, redirect URIs, CORS origins, IdP
  restrictions, claims, properties, secrets) is one click away.
- Secrets get a structured table: type, description, created/expiration
  timestamps, and a status badge (active / expires soon / expired /
  no expiry). Secret values are never displayed — only the freshly
  generated one, via the existing RegenerateSecret flow — and the
  note is repeated here so the table can't be misread.
- Footer promoted from inline links to a button bar (Edit, Regenerate
  secret, Back to List) for clearer call-to-action.

The ClientSecret property surface was confirmed by decompiling
IdentityServer8.EntityFramework.Storage 8.0.5: Expiration is
DateTime? (null = no expiry), Created is DateTime (default UtcNow).
No MinValue sentinel — previous draft's handling was wrong and has
been replaced by a single DateOrDash(DateTime?) helper.
2026-06-25 20:57:56 +01:00
ecac359344 yavsc-org: OAuth2 client admin editor overhaul — per-collection pages + missing fields
The OAuth2 client editor at /Client/Edit/{id} previously exposed 8
fields out of ~30 scalars and 10 collections on the IdentityServer8
Client entity. Editing the collections (RedirectUris, Scopes, Grant
Types, Cors Origins, IdP Restrictions, Claims, Properties, Secrets)
was either impossible or jammed into a single broken text input that
bound against an IEnumerable<string> property.

Restructure into per-collection subpages, each with its own
list/add/remove flow:

- RedirectUris       /Client/EditRedirectUris/{id}
- PostLogoutRedirectUris /Client/EditPostLogoutRedirectUris/{id}
- Scopes             /Client/EditScopes/{id}
- GrantTypes         /Client/EditGrantTypes/{id}
- CorsOrigins        /Client/EditCorsOrigins/{id}
- IdPRestrictions    /Client/EditIdPRestrictions/{id}
- Claims             /Client/EditClaims/{id}
- Properties         /Client/EditProperties/{id}
- Secrets            /Client/EditSecrets/{id}

Implementation:

- New partial class ClientController.Collections.cs with one
  GET/Add/Remove trio per collection. Add/Remove dispatch through
  generic helpers that handle the EF row + ClientId check.
- Shared _EditableStringList.cshtml partial consumed by the six
  single-string-field collection pages. Uses reflection to pull
  the value field and the row Id off the entity — avoids six
  nearly-identical table+form copies.
- Claims / Properties / Secrets each have their own view because
  they carry 2+ fields (Type+Value, Key+Value, or
  Type+Value+Description+Expiration).
- Main Edit.cshtml enriched: ClientId/Id hidden, all scalar
  fields split into fieldsets (Core, Security, Logout, Tokens,
  Device flow, Tokens extra), nav links to the 9 subpages with
  current row counts as badges.
- ClientController.Edit(int) GET now loads the client with all
  navigations via LoadClientAsync so the Edit.cshtml nav badges
  render real counts.

Field-correctness notes (verified by disassembling HigginsSoft
IdentityServer8.EntityFramework.Entities.Client 8.0.5-preview-net9):

- The property is PairWiseSubjectSalt, not PairwiseSubjectSalt
  (capital W on 'Wise').
- CibaLifetime and PollingInterval do NOT exist on Client in this
  IdentityServer8 version — those properties were a guess. The
  Device flow fieldset contains DeviceCodeLifetime + UserCodeType
  instead.
- AllowedIdentityTokenSigningAlgorithms and AllowAccessTokensViaBrowser
  were missing from the original form and are now exposed.
- ConsentLifetime and UserSsoLifetime are int? (nullable); the form
  binds them as plain int fields which accept empty strings.

Security:

- All new actions stay under [Authorize('AdministratorOnly')].
- Each Add/Remove takes an explicit id (Client.Id) and the row's
  ClientId is checked on the server before any delete; a rowId
  from another client returns NotFound.

Docs:

- doc/dev-tracking/client-editor-overhaul.md — inventory, status,
  follow-up ideas (confirmation prompts, validation, MVC tests).
2026-06-21 16:53:34 +01:00
19cf073677 Regenerate the secret 2026-06-19 01:36:08 +01:00
Paul Schneider
be7df3d054 APi Scopes 2026-03-16 23:16:12 +00:00
Paul Schneider
e042e34bf7 refact and login 2026-03-09 02:07:42 +00:00
Paul Schneider
40e8e08690 reorg 2026-02-28 21:17:54 +00:00