-
Notifications
You must be signed in to change notification settings - Fork 719
IdentityServer4 4.x: HTTP call never returns if .AspNetCore.Identity.Application fails security stamp fails validation #4644
Comments
Running the identity quickstart, logging in, then waiting 30 minutes and hitting a proctected page gives me different output than my application.
|
Here is the callstack for that call that it seems to never come back from. I added my own override for ValidatePrincipalAsync so that I get the debugging information.
Here is my simple code that I used to enable me to break at this point. public class ConfigureCookieOptionsService : IPostConfigureOptions<CookieAuthenticationOptions>
{
public void PostConfigure(string name, CookieAuthenticationOptions options)
{
options.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = ValidatePrincipalAsync
};
}
public static async Task ValidatePrincipalAsync(CookieValidatePrincipalContext context)
{
await SecurityStampValidator.ValidateAsync<ISecurityStampValidator>(context);
Console.WriteLine("I made it!");
}
} |
#4592 I hope it will help you |
I spent a bunch of time on this today and I think I may have figured out how I created this issue. On adding my external provider I was missing the code from the quickstart: options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; So I may have been creating some kind of invalid identity token in my external controller, but I'm not sure. Still seems strange that the cookie could cause the server to not return a response. I've updated all my code to follow the v4 quickstart code more closely and I am testing it out now. If that works then I may try to put some of my old (probably invalid code) into the quickstart to see if I can create a situation that can easily reproduce the issue. |
Ok, I was able to reproduce the issue with the quickstart by using my previous setup which worked with ID4 3.x. It ends up getting into a stack overflow:
The way I created this issue was with the IdentityServerAspNetIdentity quickstart.
// options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
[HttpGet]
public IActionResult Challenge(string scheme, string returnUrl)
{
var props = _signInManager.ConfigureExternalAuthenticationProperties(scheme, Url.Action(nameof(Callback), new { returnUrl }));
return new ChallengeResult(scheme, props);
}
[HttpGet]
public async Task<IActionResult> Callback(string returnUrl = null)
{
var info = await _signInManager.GetExternalLoginInfoAsync();
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
ApplicationUser user;
if (result.Succeeded)
{
user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
}
else
{
user = await AutoProvisionUserAsync(info.LoginProvider, info.ProviderKey, info.Principal.Claims);
}
await _signInManager.SignInAsync(user, isPersistent: false);
var isuser = new IdentityServerUser(user.Id)
{
DisplayName = user.UserName,
IdentityProvider = info.LoginProvider
};
await HttpContext.SignInAsync(isuser);
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
await _events.RaiseAsync(new UserLoginSuccessEvent(info.LoginProvider, info.ProviderKey, user.Id, user.UserName, true, context?.Client?.ClientId));
return Redirect(returnUrl);
}
public class ConfigureSecurityStampValidatorOptionsService : IPostConfigureOptions<SecurityStampValidatorOptions>
{
public void PostConfigure(string name, SecurityStampValidatorOptions options)
{
options.ValidationInterval = TimeSpan.FromMinutes(1);
}
}
} and somewhere in the ConfigureSerices in startup services.AddSingleton<IPostConfigureOptions<SecurityStampValidatorOptions>, ConfigureSecurityStampValidatorOptionsService>(); Start the application, log in using the external provider, then wait the validation interval time (30 minutes if you skipped part 4, otherwise 1 minute), refresh the page. You should get a stack overflow if you're running with the local reference or you will get the gateway timeout after 4 minutes if you're using the nuget packages. |
This is an ugly fix but it does solve the stack overflow issue described in #4644.
Confirmed. I'll put out a fix in our next patch. |
PR submitted. |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I have a ASP.Net Core 3.1 application hosted on a Linux App Service in Azure. It is used for identity server purposes and is also using IdentityServer4. Recently I started getting reports of my server not responding and users getting a 504 Gateway Timeout error message. I was able to reproduce this myself with a cookie on my machine and using Postman I narrowed it down to the .AspNetCore.Identity.Application cookie.
This started happening after upgrading from 3.x to 4.x. I can reproduce it locally by authenticating with the external provider, then waiting 30 minutes (the default for the validation to trigger). The response will never return. I originally raised this issue with the aspnetcore team but found that if I took the AddIdentityServer out of my startup the issue went away.
The request comes in, the stamp fails to validate, and then after 4 minutes you end up with a 504 gateway timeout error.
I'm testing to see if I can reproduce it with the quickstart.
The text was updated successfully, but these errors were encountered: