Logout reconciler: one subject's unexpected exception does not stop the pass

Caught per subject, logged at error with the subject id and exception type only, authorizations
left valid; cancellation still stops the pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-28 01:50:54 +01:00
commit 8340ee0e92

View file

@ -15,7 +15,8 @@ namespace Bifrost.Web.Features.Oidc;
/// authorizations of the configured client; for each one the shared active-member reading refuses, it POSTs one signed
/// OIDC back-channel logout token to MAS and, only after a 2xx, revokes that subject's authorizations. The
/// authorizations table is the queue: nothing is stored, so a restart, a MAS outage or a later-set URI resumes from it.
/// Per-subject backoff lives in memory only. It never writes membership.
/// Per-subject backoff lives in memory only. One subject's unexpected exception is logged and skipped, never aborting the
/// pass. It never writes membership.
/// </summary>
public sealed class OidcLogoutReconciler(
IServiceScopeFactory scopeFactory,
@ -80,8 +81,21 @@ public sealed class OidcLogoutReconciler(
foreach (var subject in subjects)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
await ReconcileSubjectAsync(subject, cancellationToken);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
throw;
}
catch (Exception error)
{
// One subject's fault never stops the pass: its authorizations stay valid and the next tick retries it.
// The subject id and the exception type only: messages can carry connection strings or URLs.
logger.LogError("Back-channel logout for subject {Subject} failed: {ErrorType}", subject, error.GetType().Name);
}
}
}
private async Task<HashSet<string>> ListSubjectsAsync(CancellationToken cancellationToken)