Anonymous probes against API routes return inconsistent status codes:
GET /api/invoices → 401
GET /api/invoices/1 → 302 → /Identity/Account/Login?ReturnUrl=…
GET /api/invoices/1/pdf → 302 → /Identity/Account/Login?ReturnUrl=…
POST /api/customers → 401
POST /api/invoices/1/mark-paid → 401
DELETE /api/invoices/1 → 302
Same authorization, different responses. JS clients that check if (res.status === 401) renewToken() get into redirect chains for some paths. Cookie-auth's challenge appears to sniff the Accept header / route shape and sometimes redirects.
Not a security bug
Both 401 and 302 block anonymous access. This is a UX wart, not a hole.
Fix
In the framework's cookie-auth setup, override OnRedirectToLogin to detect /api/* request paths and return 401 unconditionally:
services.ConfigureApplicationCookie(options =>{varexisting=options.Events.OnRedirectToLogin;options.Events.OnRedirectToLogin= ctx =>{if(ctx.Request.Path.StartsWithSegments("/api")){ctx.Response.StatusCode=401;returnTask.CompletedTask;}returnexisting(ctx);};});
Anonymous probes against API routes return inconsistent status codes:
Same authorization, different responses. JS clients that check
if (res.status === 401) renewToken()get into redirect chains for some paths. Cookie-auth's challenge appears to sniff the Accept header / route shape and sometimes redirects.Not a security bug
Both 401 and 302 block anonymous access. This is a UX wart, not a hole.
Fix
In the framework's cookie-auth setup, override
OnRedirectToLoginto detect/api/*request paths and return 401 unconditionally: