Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set-cookie not working for IE11/10 after clearing cache

I'm currently experiencing a problem where after clearing cache/cookies IE10 & IE11 will not set the cookie again. The requests and responses look almost identical but after clearing the cache the cookie is never passed up even though it appears to be set correctly.

Heres how my login method flows:

 1. VerifyLogin()    -> Fail: Go To Login page
                     -> Pass: Call rest of the AJAX Methods // Enter Login Credentials and submit
 2. Authentication() -> Fail: Prompt the user
                     -> Pass: set forms auth cookie and navigate back to original page, where it will call VerifyLogin() again

This once Authentication() passes they should then slip through VerifyLogin() with no problem and continue using the product. All the calls will now have the forms authentication cookie passed up.

In the instance im seeing it fail, the Authentication() call passes and gets a 200 OK (and has a set-cookie response header) however, the VerifyLogin() then fails because it hasn't passed up the cookie.

I have had a real hard time reproducing this but so far the reproduction steps i have are as follows. This is starting with no instance of IE running. I'm not 100% sure this is the exact same issue my customers are experiencing however it seems to reveal the same problem they are seeing.

  1. Start IE
  2. Browse to the index page of the site and get bounced to the login (verify failed)
  3. Login with credentials, Authentication() returns a 200 OK and has a set-cookie response header. It then navigates you and calls VerifyLogin() which passes. The cookie is sent up in the request and its all successful. Subsequent calls all work.
  4. Clear my cache and cookies
  5. Browse to the index page of the site and get bounced to the login (verify failed as it should)
  6. Login with credentials, Authentication() returns a 200 OK and has a set-cookie response header. It then navigates you and calls VerifyLogin() at this point fails. The cookie isn't passed up in the request, even though it was previously set in the response of Authentication(). If i close and reopen IE it will work again.

So, its like the second time round the set-cookie response is just not setting the cookie.

Firstly, Heres the relevent sections of my web.config and how i set my forms cookie.

web.config:

 <authentication mode="Forms">
      <forms enableCrossAppRedirects="true" name="Gator.Express.Auth" timeout="2880" />
    </authentication>

setAuthenticationCookie method:

 public void SetAuthenticationCookie(string userName, CookieData cookieData)
        {
            //In order to pickup the settings from config, we create a default cookie and use its values to create a 
            //new one.
            var cookie = FormsAuthentication.GetAuthCookie(userName, true);
            var ticket = FormsAuthentication.Decrypt(cookie.Value);

            if (ticket == null)
                throw new Exception("Error setting authorisation cookie. Decryption of default cookie failed.");

            var jsonToken = JsonConvert.SerializeObject(cookieData);

            var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
                ticket.IsPersistent, jsonToken, ticket.CookiePath);
            var encTicket = FormsAuthentication.Encrypt(newTicket);

            cookie.Value = encTicket;

            HttpContext.Current.Response.Cookies.Add(cookie);
        }

Now below here are the requests and responses in order.

Working Authentication Request

POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache

Username=michaelGator&Password=XXXX

# Working Authentication Response

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01020FCCF4658183D208FE0F4CC8BA1385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:28:39 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 14

"michaelGator"

# Working VerifyLogin Request

GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733
Cookie: Gator.Express.Auth=0102054E17668183D208FE05CEEABA1385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF

# Working VerifyLogin response

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:28:39 GMT
Content-Length: 0

Below here is the non-working set of requests and responses. Note that the Authentication method returns a 200 OK and a set-cookie command but in the next verify login call, the coookie is gone.

# Authentication Request - Returns as it should but part of the non-working set of requests

POST http://localhost:55733/api/Authentication HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://localhost:61496/Login.html
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 35
DNT: 1
Host: localhost:55733
Pragma: no-cache

Username=michaelGator&Password=XXXX

# Authentication Response- Returns as it should but part of the non-working set of requests

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
Set-Cookie: Gator.Express.Auth=01022054EB9B8183D208FE20D4BEF01385D208000C6D00690063006800610065006C004700610074006F00720000012F00FF; path=/; HttpOnly
Set-Cookie: Gator.Express.Auth=01028447109C8183D208FE84C7E3F01385D208010C6D00690063006800610065006C004700610074006F007200377B002200530073006F004100630063006F0075006E0074004900640022003A002200300030003000300030003000300030002D0030003000300030002D0030003000300030002D0030003000300030002D0030003000300030003000300030003000300030003000300022007D00012F00FF; expires=Sun, 05-Jul-2015 08:30:10 GMT; path=/; HttpOnly
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcQXV0aGVudGljYXRpb24=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 14

"michaelGator"

# Non-Working VerifyLogin Request - note, no cookie passes up

GET http://localhost:55733/api/VerifyLogin HTTP/1.1
Referer: http://localhost:61496/
Accept: */*
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
DNT: 1
Host: localhost:55733

# Non-Working VerifyLogin response - Fails as no Forms Cookie was passed up

HTTP/1.1 401 Unauthorized
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcV29ya2luZ1xnYXRvci5nYXRvcndlYnNlcnZpY2VcU291cmNlXEdhdG9yV2ViU2VydmljZVxhcGlcVmVyaWZ5TG9naW4=?=
Access-Control-Allow-Origin: http://localhost:61496
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, token
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
Date: Fri, 03 Jul 2015 08:30:10 GMT
Content-Length: 71

{"$id":"1","Message":"Authorization has been denied for this request."}

Any one have any ideas on this?

like image 769
Piercy Avatar asked Jul 03 '15 10:07

Piercy


People also ask

Are cookies set automatically?

Cookies are usually set by a web-server using the response Set-Cookie HTTP-header. Then, the browser automatically adds them to (almost) every request to the same domain using the Cookie HTTP-header.

How do I delete cookies on IE?

To delete cookies In Internet Explorer, select the Tools button, point to Safety, and then select Delete browsing history. Select the Cookies and website data check box, and then select Delete.


1 Answers

You seem to get getting two authentication cookies, which suggests that your implementation is clashing with something that ASP.Net is trying to automate for you.

There is a FormsAuthentication.SetAuthCookie that creates and sets the cookie, and I think this has already applied, so:

  1. FormsAuthentication.SetAuthCookie gets the cookie (already set in the same response).
  2. Your SetAuthenticationCookie fires.
  3. This calls FormsAuthentication.GetAuthCookie and processes (embeds JSON serialised data into a new cookie) the original.
  4. You call HttpContext.Current.Response.Cookies.Add to create a second cookie.
  5. Both cookies are delivered in the header with the same name

You haven't cleared the original cookie, and .Net doesn't know how to process your processed cookie.

I think you have two options:

  1. Split out your JSON data into a completely separate cookie with a different name.
  2. Roll your own cookies from scratch and don't use any of .Net's FormsAuthentication methods.

I'd personally go with the former as the simplest and quickest to implement.

It might also be worth experimenting with cookie names - I'm not sure all browsers support periods in cookie names, but they are all case sensitive.

Finally something else worth checking - it's almost never worth setting a cookie's path in .Net, as IIS treats URL as case insensitive, but browsers all treat cookie names as case-sensitive.

like image 152
Keith Avatar answered Oct 06 '22 14:10

Keith