New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No sign-out authentication handler is registered for the scheme 'Identity.External' #2082

Closed
OphiCA opened this Issue Nov 27, 2018 · 4 comments

Comments

Projects
None yet
2 participants
@OphiCA

OphiCA commented Nov 27, 2018

Hello,

For several months now I've been trying to solve an issue with Identity, where 30-min on the dot after signing in, I am greeted by an Invalid Operation Exception:

InvalidOperationException: No sign-out authentication handler is registered for the scheme 'Identity.External'. The registered sign-out schemes are: Identity.Application. Did you forget to call AddAuthentication().AddCookies("Identity.External",...)?

Since it was on my blog site, I didn't put too much effort into it, even though it was an annoyance. Now, I'm looking into possibly some real world client work where I'd like to use ASP.NET Core with Identity, but I can't be having this same issue.

Could someone please tell me why this exception throws? I don't want to use external schemes, so why is it trying to sign out of one? When did it sign into one?

Here's the relevant code from my app, hopefully someone can point me in the right direction because I sure as heck can't.

Startup.cs

public sealed class Startup {
	public void ConfigureServices(
		IServiceCollection services) {
		//...
		services.AddApplicationIdentity();
		//...
		services.ConfigureApplicationCookie(
			o => {
				o.Cookie.SameSite = SameSiteMode.Strict;
				o.Cookie.SecurePolicy = CookieSecurePolicy.Always;

				o.AccessDeniedPath = new PathString("/admin");
				o.ExpireTimeSpan = TimeSpan.FromHours(4);
				o.LoginPath = new PathString("/admin");
				o.LogoutPath = new PathString("/admin/sign-out");
			});
		services.Configure<IdentityOptions>(
			o => {
				o.Password.RequiredLength = 8;

				o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
				o.Lockout.MaxFailedAccessAttempts = 5;
			});
	}

	public void Configure(
		IApplicationBuilder app) {
		//...
		app.UseAuthentication();
		//...
	}
}

ServiceCollectionExtensions

public static class ServiceCollectionExtensions {
	public static IdentityBuilder AddApplicationIdentity(
		this IServiceCollection services) {
		services.AddAuthentication(
			o => {
				o.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
				o.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
				o.DefaultSignInScheme = IdentityConstants.ApplicationScheme;
			}).AddCookie(IdentityConstants.ApplicationScheme,
			o => {
				o.Events = new CookieAuthenticationEvents {
					OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
				};
			});

		services.TryAddScoped<IdentityErrorDescriber>();
		services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
		services.TryAddScoped<IPasswordHasher<User>, PasswordHasher<User>>();
		services.TryAddScoped<IPasswordValidator<User>, PasswordValidator<User>>();
		services.TryAddScoped<IUserClaimsPrincipalFactory<User>, UserClaimsPrincipalFactory<User>>();
		services.TryAddScoped<UserManager<User>>();
		services.TryAddScoped<IUserStore<User>, ApplicationUserStore>();
		services.TryAddScoped<IUserValidator<User>, UserValidator<User>>();
		services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<User>>();
		services.TryAddScoped<SignInManager<User>>();

		return new IdentityBuilder(typeof(User), services);
	}
}

I'm not going to include the ApplicationUserStore because I highly doubt it has anything to do with the exception. I'd appreciate any help because I am just struggling at this point. Thanks!

@HaoK

This comment has been minimized.

Member

HaoK commented Nov 27, 2018

SignInManager.SignOut expects there to be an external cookie registered as well which is where that signout call is coming, you can either override SignInManager's SignOut method here: https://github.com/aspnet/Identity/blob/master/src/Identity/SignInManager.cs#L206

Or you can add all of the identity cookies.

@HaoK HaoK added the question label Nov 27, 2018

@OphiCA

This comment has been minimized.

OphiCA commented Nov 28, 2018

@HaoK Thanks for the pointer, it looks like it fixed the exception. I was wondering why the SignOut method was being called, and now that the exception is no longer an issue I'm simply redirected to the login screen. I guess the session was expiring and thus triggering the SignOut method.

So, my next question is, why is it that my session is set for only 30 minutes? In the ConfigureApplicationCookie I do set the ExpireTimeSpan to four hours, so why is it being signed out earlier? Do I need to set the Cookie.Expiration property too? I thought the ExpireTimeSpan is the recommended property for controlling the lifetime of a cookie?

Thanks again!

@HaoK

This comment has been minimized.

Member

HaoK commented Nov 28, 2018

The security stamp validator runs every 30 minutes and that's probably invalidating your cookie, you can try removing the registration of that to see if that stops the behavior you are seeing

@OphiCA

This comment has been minimized.

OphiCA commented Nov 29, 2018

@HaoK I figured it out! After your last comment I downloaded a copy of the solution and followed along the method calls to see where I was failing. After a few hours, it turned out that I, for whatever reason months ago, decided not to store a security stamp in the database. I guess I was being lazy since I was going to be the only user, not really sure? Anyway, once I added it in everything started working as I expected it to.

Thank you for pointing me in the right direction, I really appreciate it!

@OphiCA OphiCA closed this Nov 29, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment