I created an OpenIddict auth server for my existing application which uses AspNetCore Identity. The login process works great, but the logout process causes an infinite loop between my app and the auth server. Here's my setup:
Startup.cs
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = OpenIddictServerAspNetCoreDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme, options =>
{
options.SignInScheme = IdentityConstants.ApplicationScheme;
options.Authority = "https://localhost:44395";
options.ClientId = "myclient";
options.ResponseType = OpenIdConnectResponseType.Code;
options.Scope.Add(Scopes.Profile);
options.Scope.Add(Scopes.Email);
options.CallbackPath = "/signin-oidc";
options.SaveTokens = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = Claims.Name
};
options.GetClaimsFromUserInfoEndpoint = true;
options.SignedOutRedirectUri = "/Account/Login";
});
The Logout() method in my AccountController:
[HttpPost, ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return SignOut(authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
}
The Startup of my auth server:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme);
services.AddControllersWithViews();
services.AddRazorPages();
services.AddDbContext<UserDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("connection-dev"));
options.UseOpenIddict();
});
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<UserDbContext>()
.AddDefaultTokenProviders()
.AddDefaultUI();
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.None;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
options.ClaimsIdentity.EmailClaimType = Claims.Email;
options.SignIn.RequireConfirmedAccount = false;
});
services.AddCors(options =>
{
options.AddPolicy("AllowMyOrigins",
builder =>
{
builder
.AllowCredentials()
.WithOrigins(
["http://localhost:5000"])
.AllowAnyHeader()
.AllowAnyMethod();
});
});
services.AddOpenIddict()
.AddCore(options =>
{
options.UseEntityFrameworkCore()
.UseDbContext<UserDbContext>();
})
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("connect/authorize")
.SetIntrospectionEndpointUris("connect/introspect")
.SetLogoutEndpointUris("connect/logout")
.SetTokenEndpointUris("connect/token")
.SetUserinfoEndpointUris("connect/userinfo")
.SetVerificationEndpointUris("connect/verify");
options.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();
options.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles);
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableLogoutEndpointPassthrough()
.EnableTokenEndpointPassthrough()
.EnableUserinfoEndpointPassthrough()
.EnableStatusCodePagesIntegration();
})
.AddValidation(options =>
{
options.UseLocalServer();
options.UseAspNetCore();
});
And the AuthorizationController.Logout(): I removed the consent logout part so it should just log the user out right away.
[HttpGet("~/connect/logout")]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return SignOut(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "/"
});
}
The post_logout_redirect_uri is http://localhost:5000/signout-callback-oidc.
When I try to logout, it enters an infinite loop like this:
I think I want it to go back to the auth server's login page on logout. I definitely don't want it circling around forever :).
Here's the requests in table form:
| Method | Endpoint | Status Code | Type | Source |
|--------|----------|-------------|------|--------|
| GET | http://localhost:5000/Account/Logout | 302 | xhr / Redirect | user-profile.component.ts:42 |
| GET | logout?post_logout_redirect_uri=http%3A%2F%2Flocal…Ib3Ak&x-client-SKU=ID_NET8_0&x-client-ver=7.2.0.0 | 302 | xhr / Redirect | - |
| GET | https://localhost:44395/connect/logout?post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fsignout-callback-oidc&id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIzMEYxN0VGRkVBM0RERTFGNTYzNkRCMDcwNzA1NDYxRDExRjk0RkEiLCJ4NXQiOiJJdzhYN182ajNlSDFZMjJ3Y0hCVVlkRWZsUG8iLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDM5NS8iLCJleHAiOjE3MTA4Mzk4MzEsImlhdCI6MTcxMDgzODYzMSwiYXVkIjoib29kbGVhbmd1bGFyY2xpZW50Iiwic3ViIjoiMGQ1ZDZmYzAtNzIxZS00YmI5LWJmNTYtZTcxMjhiMGQxMzU4IiwibmFtZSI6InN0ZWljaG1hbkBvb2RsZWNsb3VkLmNvbSIsImVtYWlsIjoic3RlaWNobWFuQG9vZGxlY2xvdWQuY29tIiwib2lfYXVfaWQiOiJhYzdlYWYwMi01NmI4LTQzY2QtYWFiMC1iZGRlMDhkMWU4ZTMiLCJhenAiOiJvb2RsZWFuZ3VsYXJjbGllbnQiLCJub25jZSI6IjYzODQ2NDM1NDIwMzU2NzIxOS5ZV1F4WVRNNE1EZ3RObU5oWkMwME56RXlMVGt3Tm1VdE1tWTNOak5rTUdWak5EYzRPVFU0Tm1abFl6VXROelE0WVMwMFlqTXpMV0kwWVRrdFpEazVaRGd3T1RBMk5HUm0iLCJhdF9oYXNoIjoiUXplNmxfVDBwRGhjUjAyY2VHM2FpQSIsIm9pX3Rrbl9pZCI6IjVjNzJhZmVjLTI3YzktNDkxNS05NjdlLTVlYTNkNTQwNDVkNyJ9.sTuSjQCxqh89nEqOn-zfykkLiZoB_UOcbE8FHG5_v8sjJHx5Ytn6YxONpQenIjZggDLvXSBs4MBN9oRe2VqQpkFO2i1RBaCIiCfmyYY4YDQ4EiAr3R7Z9TpJ_W-4rHkczlHYsU9WT9OtOfXUOpy1uHQPIRgrDHBScZVMo0Uz0Q9BlU2d0Dg3rs3esRxA3MJJn3fedqQoSYlnBFdRxo-4-szu4krldn4mhkns-ua96pCQWQwIGetFKzhV2MDOzFF5vj38mjwKNw80v4dP-H8Prq1Q8LuzCIXyra8USx6WQVYaQVVb3c_5FxEVCaBCxB-XaZN8lP3Ajw9Ed-KWaXcdgA&state=CfDJ8DwhaUXmuCROpCgfCLIYTwyHz6Z_WecMr8WjPz6O6F48TU3RrqurGDWG2WoOY-Y52iZP5ykUZFDFVFqOL4j8yiARGAVHDLii8h4JD6zFXKf82zGODbRgPYNex7wH8okYB4LUyfQqxyNGjJ9A4lIb3Ak&x-client-SKU=ID_NET8_0&x-client-ver=7.2.0.0 | 204 | preflight | Preflight |
| GET | logout?post_logout_redirect_uri=http%3A%2F%2Flocal…Ib3Ak&x-client-SKU=ID_NET8_0&x-client-ver=7.2.0.0 | 302 | xhr / Redirect | Logout |
| GET | signout-callback-oidc?state=CfDJ8DwhaUXmuCROpCgfCL…zFXKf82zGODbRgPYNex7wH8okYB4LUyfQqxyNGjJ9A4lIb3Ak | http://localhost:5000/signout-callback-oidc?state=CfDJ8DwhaUXmuCROpCgfCLIYTwyHz6Z_WecMr8WjPz6O6F48TU3RrqurGDWG2WoOY-Y52iZP5ykUZFDFVFqOL4j8yiARGAVHDLii8h4JD6zFXKf82zGODbRgPYNex7wH8okYB4LUyfQqxyNGjJ9A4lIb3Ak | 204 | preflight | Preflight |
| GET | signout-callback-oidc?state=CfDJ8DwhaUXmuCROpCgfCL…zFXKf82zGODbRgPYNex7wH8okYB4LUyfQqxyNGjJ9A4lIb3Ak | http://localhost:5000/signout-callback-oidc?state=CfDJ8DwhaUXmuCROpCgfCLIYTwyHz6Z_WecMr8WjPz6O6F48TU3RrqurGDWG2WoOY-Y52iZP5ykUZFDFVFqOL4j8yiARGAVHDLii8h4JD6zFXKf82zGODbRgPYNex7wH8okYB4LUyfQqxyNGjJ9A4lIb3Ak | 302 | xhr / Redirect | logout |
| GET | http://localhost:5000/ | 204 | preflight | Preflight |
| GET | http://localhost:5000/ | 400 | xhr | signout-callback-oidc |
| GET | http://localhost:5000/GetXsrfToken | 200 | xhr | user-profile.component.ts:42 |
What could be causing it to keep redirecting to Logout?