Identityserver4: Cookies won't disappear after signout

Created on 8 Jun 2018  路  8Comments  路  Source: IdentityServer/IdentityServer4

Hi, we are facing an issue with the deletion of cookies in IdentityServer 4 after a signout.

Steps to reproduce the problem

First we do a GOOGLE login with request:

https://url/connect/authorize?response_type=code+id_token&nonce=cf2ca6784faa609a29c9e967c411fc56&state=ea0f106f446475ae817eea7954bb3ffa&code_challenge=ajp3jwHXGpVEQP5S1fJfZ3t2tb_0v38VnobkjXZo5D8&code_challenge_method=S256&client_id=client.android&scope=openid+profile&redirect_uri=android.client.com%3A%2Foauth2redirect

We're getting a login result:

android.client.com:/oauth2redirect#code=11d1f983de0e28c3ba4fea018fb8f70fb119b3052e99ea902e1ea874f0151d68&id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkE5MzdEQ0RGQTQ0RThFQTFGMjVBQTFFNkYxNkQwODQyNzk3QjA5MDciLCJ0eXAiOiJKV1QiLCJ4NXQiOiJxVGZjMzZST2pxSHlXcUhtOFcwSVFubDdDUWMifQ.eyJuYmYiOjE1MjgyMjk0MDUsImV4cCI6MTUyODIyOTcwNSwiaXNzIjoiaHR0cHM6Ly9pZHAtdGVzdC5xLXBhcmsuY29tIiwiYXVkIjoiY29tLnFwYXJrLm1vYmlscGFyay5hbmRyb2lkIiwibm9uY2UiOiJjZjJjYTY3ODRmYWE2MDlhMjljOWU5NjdjNDExZmM1NiIsImlhdCI6MTUyODIyOTQwNSwiY19oYXNoIjoiSGpJWl93dlVLajhxRG1sXzg4OFVkUSIsInNpZCI6IjIzM2IzMjBlOWViMzRkYzdiZjdkMzMyNTI1OTgwNTQ2Iiwic3ViIjoiZTczZWY4ZmMtMDZjOS00NGRkLTg0ZTgtNjE0YzZjOTI0NWYzIiwiYXV0aF90aW1lIjoxNTI4MjI5NDA0LCJpZHAiOiJHb29nbGUiLCJuYW1lIjoiRXVyb3BlYW5BcHBGYWN0b3J5QGNlZ2VrYS5iZSIsImdpdmVuX25hbWUiOiJFdXJvcGVhbkFwcEZhY3RvcnlAY2VnZWthLmJlIiwibGFuZ3VhZ2UiOiJlbi1HQiIsImFtciI6WyJleHRlcm5hbCJdfQ.JIiwuwswhcrMET5SWHLEj0oQ5oq3xjnLzavADgZA4U6_dkEDHcJnFzY_9_me8bjepWMv57aHOJ8qtetdzhNKk6VhvFVnZD7HbnZVOrkXJJD5KM4zQQJ-4yNmlJ_VK4mmm_zA-c1uK0y7inRqkNHkkHSg9YO2XAsybRyZTBhNJd6KesJwcj5qhilrglE4u2ktJjbj-R_qkBjvWDGpyJxb6UFXKSWfsDaCGZV7VI-gG5rS9gjwr8vSG84RCzGslD_fZyh3wUfav6zlvx_9k2XpxGK5g61Lvl5td54xlCx9GFvT1j7i7R_kFtRojatqSpYutwQKq2RLfHGGGtZORn24bQ&scope=openid%20profile&state=ea0f106f446475ae817eea7954bb3ffa&session_state=k5ItjHn8qb-teyTBsbelBLRotI0cemvasrH-Vfhqg1M.9e74fe0cfd89e45079b9bb82a428f500

Some cookies were made (idsrv.session / AspNetCore.Cookies / ....)

Now we do a logout by calling the connect/endsession endpoint:

https://url/connect/endsession?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IkE5MzdEQ0RGQTQ0RThFQTFGMjVBQTFFNkYxNkQwODQyNzk3QjA5MDciLCJ0eXAiOiJKV1QiLCJ4NXQiOiJxVGZjMzZST2pxSHlXcUhtOFcwSVFubDdDUWMifQ.eyJuYmYiOjE1MjgyMjk0MDYsImV4cCI6MTUyODIyOTcwNiwiaXNzIjoiaHR0cHM6Ly9pZHAtdGVzdC5xLXBhcmsuY29tIiwiYXVkIjoiY29tLnFwYXJrLm1vYmlscGFyay5hbmRyb2lkIiwibm9uY2UiOiJjZjJjYTY3ODRmYWE2MDlhMjljOWU5NjdjNDExZmM1NiIsImlhdCI6MTUyODIyOTQwNiwiYXRfaGFzaCI6ImVuaTliTnBaT1Itbm1hMXhOLVNlZ3ciLCJzaWQiOiIyMzNiMzIwZTllYjM0ZGM3YmY3ZDMzMjUyNTk4MDU0NiIsInN1YiI6ImU3M2VmOGZjLTA2YzktNDRkZC04NGU4LTYxNGM2YzkyNDVmMyIsImF1dGhfdGltZSI6MTUyODIyOTQwNCwiaWRwIjoiR29vZ2xlIiwibmFtZSI6IkV1cm9wZWFuQXBwRmFjdG9yeUBjZWdla2EuYmUiLCJnaXZlbl9uYW1lIjoiRXVyb3BlYW5BcHBGYWN0b3J5QGNlZ2VrYS5iZSIsImxhbmd1YWdlIjoiZW4tR0IiLCJhbXIiOlsiZXh0ZXJuYWwiXX0.LzipvjLXFuVDF-yMnJQvggM86TM4BYgdMEF4kAPXuwAKiIZd7Ez82cMFMCtmidW1uedzOsvvUGJuixYGx7ckgXFRsNTmsacfouE5VRyTJxBlYImLzZHGczpirMIexUyS-uV4jWTpgk0j_dULdkaFh5G37I6IHfTR-NwBrn02mO4g3PS3CIhd-SLVZE3INM20IW9ftv4XIuvKApNXM0be6T1DXMHBI7xsYfOMj1rEtG6b8ziEJe54ZmyumJJWGunSfLVwS6U6LJ0kh0Y689YMOUKhISqV5YZOwr85aH_bkCI85i8vEmyry10bVQXh_ZcuA3VL04RYS-iyUWn897XQ9g&post_logout_redirect_uri=android.client.com%3A%2Foauth2redirect

After sign-out we're getting a signout confirmation window. When we click "yes", the cookies are still existing.

So when we're doing a second login attempt

https://url/connect/authorize?response_type=code+id_token&nonce=640c477ae7c5684e21d90f434d23e7bc&state=27a658e7c26696327946a690985fe595&code_challenge=TA9aAAheUqcxhH5RouZyh2jvG2_px58YrYSZvkApIOA&code_challenge_method=S256&client_id=client.android&scope=openid+profile&redirect_uri=android.client.com%3A%2Foauth2redirect

The second login result as the same state / id token as the first, because cookies are still existing

android.client.com:/oauth2redirect#code=11d1f983de0e28c3ba4fea018fb8f70fb119b3052e99ea902e1ea874f0151d68&id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IkE5MzdEQ0RGQTQ0RThFQTFGMjVBQTFFNkYxNkQwODQyNzk3QjA5MDciLCJ0eXAiOiJKV1QiLCJ4NXQiOiJxVGZjMzZST2pxSHlXcUhtOFcwSVFubDdDUWMifQ.eyJuYmYiOjE1MjgyMjk0MDUsImV4cCI6MTUyODIyOTcwNSwiaXNzIjoiaHR0cHM6Ly9pZHAtdGVzdC5xLXBhcmsuY29tIiwiYXVkIjoiY29tLnFwYXJrLm1vYmlscGFyay5hbmRyb2lkIiwibm9uY2UiOiJjZjJjYTY3ODRmYWE2MDlhMjljOWU5NjdjNDExZmM1NiIsImlhdCI6MTUyODIyOTQwNSwiY19oYXNoIjoiSGpJWl93dlVLajhxRG1sXzg4OFVkUSIsInNpZCI6IjIzM2IzMjBlOWViMzRkYzdiZjdkMzMyNTI1OTgwNTQ2Iiwic3ViIjoiZTczZWY4ZmMtMDZjOS00NGRkLTg0ZTgtNjE0YzZjOTI0NWYzIiwiYXV0aF90aW1lIjoxNTI4MjI5NDA0LCJpZHAiOiJHb29nbGUiLCJuYW1lIjoiRXVyb3BlYW5BcHBGYWN0b3J5QGNlZ2VrYS5iZSIsImdpdmVuX25hbWUiOiJFdXJvcGVhbkFwcEZhY3RvcnlAY2VnZWthLmJlIiwibGFuZ3VhZ2UiOiJlbi1HQiIsImFtciI6WyJleHRlcm5hbCJdfQ.JIiwuwswhcrMET5SWHLEj0oQ5oq3xjnLzavADgZA4U6_dkEDHcJnFzY_9_me8bjepWMv57aHOJ8qtetdzhNKk6VhvFVnZD7HbnZVOrkXJJD5KM4zQQJ-4yNmlJ_VK4mmm_zA-c1uK0y7inRqkNHkkHSg9YO2XAsybRyZTBhNJd6KesJwcj5qhilrglE4u2ktJjbj-R_qkBjvWDGpyJxb6UFXKSWfsDaCGZV7VI-gG5rS9gjwr8vSG84RCzGslD_fZyh3wUfav6zlvx_9k2XpxGK5g61Lvl5td54xlCx9GFvT1j7i7R_kFtRojatqSpYutwQKq2RLfHGGGtZORn24bQ&scope=openid%20profile&state=ea0f106f446475ae817eea7954bb3ffa&session_state=k5ItjHn8qb-teyTBsbelBLRotI0cemvasrH-Vfhqg1M.9e74fe0cfd89e45079b9bb82a428f500

IdentityServer configuration:

            var connectionString = configService.GetConnectionString("ClientDb");
            var migrationsAssembly = typeof(IdentityServerStartup).Assembly.GetName().Name;

            services.AddDbContext<IdentityDbContext>(builder =>
                builder.UseSqlServer(connectionString, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)));

            services.AddIdentity<IdentityUser, IdentityRole>(
                options =>
                {
                    options.Password.RequireDigit = false;
                    options.Password.RequiredLength = 8;
                    options.Password.RequireNonAlphanumeric = false;
                    options.Password.RequireUppercase = true;
                    options.Password.RequireLowercase = false;
                    options.Lockout.MaxFailedAccessAttempts = (3);
                    options.Lockout.AllowedForNewUsers = true;
                    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1);

                    options.SignIn.RequireConfirmedEmail = true;
                })
                .AddEntityFrameworkStores<IdentityDbContext>()
                .AddUserManager<UserManager<IdentityUser>>()
                .AddSignInManager<SignInManager<IdentityUser>>()
                .AddDefaultTokenProviders();

            services.AddIdentityServer(options =>
            {
                options.Events.RaiseErrorEvents = true;
                options.Events.RaiseInformationEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseSuccessEvents = true;
            })
#if DEBUG
                .AddDeveloperSigningCredential()
#else
                .AddSigningCredential(configService.GetSetting("Certificate.Thumbprint"), StoreLocation.LocalMachine, NameType.Thumbprint)
#endif
                .AddAspNetIdentity<IdentityUser>()
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                    {
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                    };
                })
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = builder =>
                        builder.UseSqlServer(connectionString,
                            sql => sql.MigrationsAssembly(migrationsAssembly));
                    options.EnableTokenCleanup = true;
                    options.TokenCleanupInterval = 30;
                })
                .AddClientStore<ClientStore>()
                .AddProfileService<ProfileService>();

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddGoogle("Google", options =>
            {
                options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
                options.ClientId = configService.GetSetting("Google.Client.Id");
                options.ClientSecret = configService.GetSetting("Google.Client.Secret");
            });

            services.AddCors().AddMvc();

Are we doing something wrong of is this an issue?

question

Most helpful comment

If you're using ASP.NET Identity, then you should be using the SignInManager to call SignOut as they have their own cookies.

All 8 comments

After sign-out we're getting a signout confirmation window. When we click "yes", the cookies are still existing.

This is where you need to debug. Your login page should be triggering signout, thus removing the cookies. Also perhaps look in fiddler to see what's happening in the response headers.

Response headers:

EndSession:

HTTP/1.1 302 Found Date: Fri, 08 Jun 2018 13:44:51 GMT Server: Kestrel Content-Length: 0 Location: http://url/account/logout?logoutId=CfDJ8D7D88KTGL9GigpjtZbZNPtHsA4gCde2-AABtlOSRny8VfGsJVA8LsJii94Og0hxcEay2A122WB8rQTBYukJycFEzhK77l0sSfoW4_oIKTmsw5eyGJWEnoG7XYVNayqlvOhpY2fdLQz-CGzqLI2_CZn6UraHrgTDCvgs2YD5uTogXFnd9_aZqVo-ckUBiwVkBAG5AiG2LABI91ACEJofTEGuvt4hnuDYDgLEEuSmGxlOQF6d7mZ8UqFNOMKjM-dkbQ Request-Context: appId=cid-v1:93e20b5c-4c41-45ec-a522-2282c5cdf8c7 InstanceId: 16af

Logout:

HTTP/1.1 200 OK Date: Fri, 08 Jun 2018 13:44:51 GMT Content-Type: text/html; charset=utf-8 Server: Kestrel Transfer-Encoding: chunked Request-Context: appId=cid-v1:93e20b5c-4c41-45ec-a522-2282c5cdf8c7 InstanceId: 16af X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN Content-Security-Policy: default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self'; script-src 'self' 'unsafe-eval'; X-Content-Security-Policy: default-src 'self'; object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts; base-uri 'self'; script-src 'self' 'unsafe-eval'; Referrer-Policy: no-referrer

To remove the cookie, it needs to call the SignOutAsync as stated in the doc, right?

EndSession endpoint won't remove the cookie.

When I call the endsession endpoint I added the SignOutAsync in the code (just for testing purpose). But still no removal of the cookies.

To be clear you are not talking about signing out of Google right? You are talking about signing out of your identity server.

Try these:

await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignOutAsync("idsrv.external");
await HttpContext.SignOutAsync("idsrv.session");

If you're using ASP.NET Identity, then you should be using the SignInManager to call SignOut as they have their own cookies.

All set on this issue -- can we close?

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

klioqc picture klioqc  路  3Comments

user1336 picture user1336  路  3Comments

eshorgan picture eshorgan  路  3Comments

Aravind1729 picture Aravind1729  路  3Comments

brockallen picture brockallen  路  3Comments