AspNetKatana icon indicating copy to clipboard operation
AspNetKatana copied to clipboard

Stop 401 redirection without creating a nonce cookie for OpenIdConnect

Open pergardebrink opened this issue 3 years ago • 2 comments

Hi,

We have some api endpoints that returns 401 when the authentication cookie is expired. Since those endpoints are called from ajax calls, it should not be redirected to the OpenId Connect Identity Provider (but instead detected client side to cause a re-login in another way, for example refresh the page).

I found that by intercepting the RedirectToIdentityProvider, I could implement my custom logic to exclude those calls and call the .HandleResponse() to stop the redirect to the Identity Provider from happening. However, the nonce cookie (OpenIdConnect.nonce.) is always created, meaning that if too many 401s happened due to multiple ajax calls happening, the cookie store in the browser would be too large for following requests ("Request too big").

Looking at the code, I could see that the nonce cookie is set before RedirectToIdentityProvider is called: https://github.com/aspnet/AspNetKatana/blob/d196e785e277452f1382dded08ca12974d29170e/src/Microsoft.Owin.Security.OpenIdConnect/OpenidConnectAuthenticationHandler.cs#L195

The only workaround I could find was to manually delete the cookie in the same request by finding the nonce to recreate the cookie name and then issue a DeleteCookie

var nonce = notification.ProtocolMessage.Nonce;
using var hashAlgorithm = SHA256.Create();
var cookieName = "OpenIdConnect.nonce." + Convert.ToBase64String(hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(nonce)));
notification.Options.CookieManager.DeleteCookie(notification.OwinContext, cookieName, new CookieOptions());
notification.HandleResponse();

Apart from being ugly, it also ends up sending two Set-Cookie instructions to the browser, but at least ending up with no cookie stored.

Is there any other (better) way to stop redirect for 401 without the nonce cookie being created?

pergardebrink avatar Feb 07 '22 10:02 pergardebrink

Looking at the code in OpenidConnectAuthenticationHandler.cs, wouldn't it just be possible to move this code:

if (Options.ProtocolValidator.RequireNonce)
{
    AddNonceToMessage(openIdConnectMessage);
}

To be inside the if (!notification.HandledResponse) block on line 205?

pergardebrink avatar Feb 07 '22 14:02 pergardebrink

Rather than trying to change the handler implementation, it seems better to set the OpenIdConnectAuthenticationOptions.AuthenticationMode to Passive so it doesn't trigger by default on your API calls. Have you tried that? Then control would fall through to cookie auth, which already has logic like this built in. https://github.com/aspnet/AspNetKatana/blob/d196e785e277452f1382dded08ca12974d29170e/src/Microsoft.Owin.Security.Cookies/Provider/DefaultBehavior.cs#L14-L34 For APIs you'd get back 401, for non-APIs you'd redirect to a local login page that could then Challenge for OpenIdConnect auth.

Tratcher avatar Feb 09 '22 23:02 Tratcher