peter
peter

Reputation: 1

System.InvalidOperationException in AspNetCore.Authorization

We receive the mentioned exception on our productive environment (azure web app) and have not found a way to reproduce this exception. Those exceptions occur during the usage peak of our application but when the application is used less frequent it does not happen at all. Saying...under good conditions our code is working just fine.

In general we understand what the exception is trying to say in terms of an enumerable that is modified somewhere. Problem is that we have no idea which enumerable is falsely modified at which point of time.

I am happy to provide any information but at the current point of time we have no clue which part could be problematic.

Using .NET 8.0

Startup.cs

services.AddSingleton<IMemoryCache, MemoryCache>();
services.TryAddSingleton<ITicketStore, CookieSessionStore>();
services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = LoginService.AuthenticationSchemaName;
        options.DefaultForbidScheme = LoginService.AuthenticationSchemaName;
        options.DefaultChallengeScheme = LoginService.AuthenticationSchemaName;
    })
    .AddCookie(LoginService.AuthenticationSchemaName, options => ConfigureCookieAuthentication(options, services.BuildServiceProvider().GetService<ITicketStore>(), cookieSessionStoreActive))
    .AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>(CustomAuthenticationHandler.SchemaName, null);
...
public static void ConfigureCookieAuthentication(CookieAuthenticationOptions options, ITicketStore? ticketStore, bool cookieSessionStoreActive)
{
    options.Cookie.Name = CustomAuthenticationHandler.CookieName;
    options.Cookie.HttpOnly = true;
    options.Cookie.MaxAge = TimeSpan.FromHours(12);
    options.ExpireTimeSpan = TimeSpan.FromHours(1);
    options.SlidingExpiration = true;
    options.SessionStore = ticketStore;
    
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
        return Task.CompletedTask;
    };
    options.Events.OnRedirectToAccessDenied = context =>
    {
        context.Response.StatusCode = StatusCodes.Status403Forbidden;
        return Task.CompletedTask;
    };
    options.LogoutPath = null;
    options.LoginPath = null;
}

CookieSessionStore

public class CookieSessionStore(ILogger<CookieSessionStore> logger, IMemoryCache cache) : ITicketStore
{
    public Task RemoveAsync(string key)
    {
        logger.LogDebug($"Trying to remove {key}");
        cache.Remove(key);

        return Task.CompletedTask;
    }

    public Task<AuthenticationTicket> RetrieveAsync(string key)
    {
        logger.LogDebug($"Trying to get {key}");
        var ticket = cache.Get<AuthenticationTicket>(key);

        return Task.FromResult(ticket);
    }

    public Task RenewAsync(string key, AuthenticationTicket ticket)
    {
        logger.LogDebug($"Trying to set {key}");
        cache.Set(key, ticket);

        return Task.CompletedTask;
    }

    public Task<string> StoreAsync(AuthenticationTicket ticket)
    {
        logger.LogDebug("Trying to StoreAsync");
        var claims = ticket.Principal.Claims.ToList();
        var key = claims
            .First(c => c.Type == SessionStoreConstants.SessionIdClaimName).Value;
        logger.LogDebug($"Trying to StoreAsync with {key}");

        var options = new MemoryCacheEntryOptions
        {
            SlidingExpiration = TimeSpan.FromHours(1)
        };

        cache.Set(key, ticket, options);

        return Task.FromResult(key);
    }
}

Following Exception occurs: Collection was modified; enumeration operation may not execute. StackTrace:

System.InvalidOperationException:
   at System.ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Collections.Generic.List`1+Enumerator.MoveNext (System.Private.CoreLib, Version=8.0.0.0, Culture=neutra)
   at System.Linq.Enumerable+WhereListIterator`1.MoveNext (System.Linq, Version=8.0.0.0, Culture=neutral)
   at System.Collections.Generic.List`1.AddRange (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at Microsoft.Extensions.Internal.SecurityHelper.MergeUserPrincipal (Microsoft.AspNetCore.Authorization.Policy, Version=8.0.0.0, Culture=neutral)
   at Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator+<AuthenticateAsync>d__2.MoveNext (Microsoft.AspNetCore.Authorization.Policy, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware+<Invoke>d__11.MoveNext (Microsoft.AspNetCore.Authorization.Policy, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext (Microsoft.AspNetCore.Authentication, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Private.CoreLib, Version=8.0.0.0, Culture=neutral)
   at ...ExceptionMiddlewareBase+<Invoke>d__3.MoveNext (..., Version=null, Culture=neutral)

We already tried to add .ToList() at a couple of enumerables that look suspicious but had no succes. We are looking for a better understanding of what is causing this exception

Upvotes: 0

Views: 43

Answers (0)

Related Questions