Logout via Set-Cookie fails - authentication

We moved our website a while ago to a new hoster and experience sporadically issues where people cannot logout anymore. Not sure if that has anything to do with the hosting environment or with a code change.
This is the Wireshark log of the relevant bit - all is happening in the same TCP stream.
Logout request from the browser (note the authentication cookie):
GET /cirrus/logout HTTP/1.1
Host: subdomain.domain.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://subdomain.domain.com/cirrus/CA/Admin/AccountSwitch
Cookie: USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye
X-LogDigger-CliVer: client-firefox 2.1.5
X-LogDigger: logme=0&reqid=fda96ee5-2db4-f543-81b5-64bdb022d358&
Connection: keep-alive
Server response. It clears the cookie value and redirects
HTTP/1.1 302 Found
Server: nginx
Date: Fri, 22 Nov 2013 14:40:22 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 124
Connection: keep-alive
Cache-Control: private, no-cache="Set-Cookie"
Location: /cirrus
Set-Cookie: USER.AUTH=; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus
X-Powered-By: ASP.NET
X-UA-Compatible: chrome=IE8
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
Browser follows the redirection, but with the old cookie value:
GET /cirrus HTTP/1.1
Host: subdomain.domain.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://subdomain.domain.com/cirrus/CA/Admin/AccountSwitch
Cookie: USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye
X-LogDigger-CliVer: client-firefox 2.1.5
X-LogDigger: logme=0&reqid=0052e1e1-2306-d64d-a308-20f9fce4702e&
Connection: keep-alive
Is there anything obvious missing in the Set-Cookie header which could prevent the browser from deleting the cookie?
To change the value for an existing cookie, the following cookie parameters must match:
name
path
domain
name and path are set explecitely, the domain is not. Could that be the problem?
Edit: As it has been asked why the expiration date is set in the past, a bit more background.
This is using a slight modification of the AppHarbor Security plug-in: https://github.com/appharbor/AppHarbor.Web.Security
The modification is to include the path to the cookie. Please find here the modified logout method:
public void SignOut(string path)
{
_context.Response.Cookies.Remove(_configuration.CookieName);
_context.Response.Cookies.Add(new HttpCookie(_configuration.CookieName, "")
{
Expires = DateTime.UtcNow.AddMonths(-100),
Path = path
});
}
The expiration date in the past is done by the AppHarbor plug-in and is common practice. See http://msdn.microsoft.com/en-us/library/ms178195(v=vs.100).aspx

At a guess i'd say the historical expiry date is causing the whole Set-Cookie line to be ignored (why set a cookie that expired 8 years ago?).
expires=Fri, 22-Jul-2005

We have had issues with deleting cookies in the past and yes the domain and path must match the domain and path of the cookie you are trying to delete.
Try setting the correct domain and path in the HttpCookie.

Great question, and excellent notes. I've had this problem recently also.
There is one fail-safe approach to this, beyond what you ought to already be doing:
Set expiration in the past.
Set a path and domain.
Put bogus data in the cookie being removed!
Set-Cookie: USER.AUTH=invalid; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus; domain=subdomain.domain.com
The fail-safe approach goes like this:
Add a special string to all cookies, at the end. Unless that string exists, reject the cookie and forcibly reset it. For example, all new cookies must look like this:
Set-Cookie: USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye|1386510233; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus; domain=subdomain.domain.com
Notice the change: That extremely long string stored in USER.AUTH ends with |1386510233, which is the unix epoch of the moment when the cookie was set.
This adds a simple extra step to cookie parsing. Now you need to test for the presence of | and to discard the unix epoch unless you care to know when the cookie was set. To make it go faster, you can just check for string[length-10]==| rather than parsing the whole string. In the way I do it, I split the string at | and check for two values after the split. This bypasses a two-part parsing process, but this aspect is language specific and really just preferential when it comes to your choice of tactic. If you plan to discard the value, just check the specific index where you expect the | to be.
In the future if you change hosts again, you can test that unix epoch and reject cookies older than a certain point in time. This at the very most adds two extra processes to your cookie handler: removing the |unixepoch and if desired, checking when that time was to reject a cookie if you change hosts again. This adds about 0.001s to a pageload, or less. That is worth it compared to customer service failures and mass brain damage.
Your new cookie strategy allows you to easily reject all cookies without the |unixepoch immediately, because you know they are old cookies. And yes, people might complain about this approach, but it is the only way to truly know the cookie is valid, really. You cannot rely on the client side to provide you valid cookies. And you cannot keep a record of every single cookie out there, unless you want to warehouse a ton of data. If you warehouse every cookie and check it every time, that can add 0.01s to a pageload versus 0.001s in this strategy, so the warehousing route is not worth it.
An alternative approach is to use USER.AUTHENTICATION rather than USER.AUTH as your new cookie value, but that is more invasive perhaps. And you don't gain the benefit of what I said above if/when you change hosts again.
Good luck with your transition. I hope you get this sorted out. Using the strategy above, I was able to.

Related

I want to figure out how cookies/ session variables interact to validate a user session

---I have been experimenting on cookies/ session ids and have a little trouble digesting in the concepts.
I'm working on a Debian distro. Using Burp to capture/alter requests/ responses. What I know is below.
a. Cookies get stored in the client machine database at /root/.mozilla/firefox/pya18ecc.default/cookies.sqlite. In the moz_cookies table. I'm using sqlite3 to access the database.
b. Session variables are getting stored in /var/lib/PHP5 on the server.
The PHP code on the SERVER is below
<?php
require_once 'login.php';
$connection = new mysqli($db_hostname,$db_username,$db_password,$db_database);
if($connection->connect_error) die ($connect->connect_error);
if (isset($_SERVER['PHP_AUTH_USER']) &&
isset($_SERVER['PHP_AUTH_PW']))
{
$username = mysql_entities_fix($connection,$_SERVER['PHP_AUTH_USER']);
$password = mysql_entities_fix($connection,$_SERVER['PHP_AUTH_PW']);
$query = "SELECT * FROM user WHERE username = '$username'";
$result = $connection->query($query);
if(!$result) die ($connection->error);
elseif ($result->num_rows)
{
$row = $result->fetch_array(MYSQLI_NUM);
$result->close();
$salt1="!##$";
$salt2="$##!";
$token = hash('ripemd128',"$salt1$password$salt2");
if($token == $row[3])
{
session_start();
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
$_SESSION['forename'] = $row[0];
$_SESSION['surname'] = $row[1];
echo "$row[0] $row[1] : Hi '$row[0]' you are logged
in as '$row[2]'";
die("<p><a href = continue.php> CLICK HERE TO CONTINUE</a></p>");
}
else {die("Invalid Username/ Password Combination");}
}
else
{
die("Invalid Username/ Password Combination");
}
}
else
{
header('WWW-Authenticate: Basic realm="Restricted Section"');
header('HTTP/1.0 401 Unauthorized');
die("Please enter your username and password to Login");
}
$connection->close();
function mysql_entities_fix($connection,$var)
{
return htmlentities(mysql_entities_string($connection,$var));
}
function mysql_entities_string($connection,$var)
{
if (get_magic_quotes_gpc()) $var = stripslahes($var);
return $connection->real_escape_string($var);
}
?>
When I send in the request(1), it lookes like this.
request(1)
GET /ses3.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
The response(1) is a login page (Basic HTTP authentication)
response(1)
HTTP/1.0 401 Unauthorized
Date: Sat, 28 Mar 2015 07:27:44 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.36-0+deb7u3
WWW-Authenticate: Basic realm="Restricted Section"
Vary: Accept-Encoding
Content-Length: 48
Connection: close
Content-Type: text/html
Please enter your username and password to Login
----Till here there has no exchange of session ids or cookies. (If I'm wrong, prompt me ?)
I responded with the username and password and the request(2) is
request(2)
GET /ses3.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Authorization: Basic YnNtaXRoOm15c2VjcmV0
---- On forwarding the above request what I observe is that I've received the Session id: cl5mi7tbhdnobpv8kkau7thjo6 in the /var/lib/PHP5 even before forwarding the response(2). That's because Server
has created the same and is ready to fowrward it in the response (2)
The response(2) is
response(2)
HTTP/1.1 200 OK
Date: Sat, 28 Mar 2015 07:36:13 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.36-0+deb7u3
Set-Cookie: PHPSESSID=cl5mi7tbhdnobpv8kkau7thjo6; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must- revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 117
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
Bill Smith : Hi 'Bill' you are logged
in as 'bsmith'<p><a href = continue.php> CLICK HERE TO CONTINUE</a></p>
----Now on checking SELECT * FROM moz_cookies, I'm not seeing any cookies which are getting saved on the client m/c. So where are they getting saved ? (This is my first question)
Next I've deleted the session variable "cl5mi7tbhdnobpv8kkau7thjo6" from the server and again have hit the
refresh button on the client's browser. The request(3)/ response(3) are below
request(3)
GET /ses3.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=cl5mi7tbhdnobpv8kkau7thjo6
Authorization: Basic YnNtaXRoOm15c2VjcmV0
Connection: keep-alive
Cache-Control: max-age=0
response(3)
HTTP/1.1 200 OK
Date: Sat, 28 Mar 2015 07:50:01 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.36-0+deb7u3
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 117
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html
Bill Smith : Hi 'Bill' you are logged
in as 'bsmith'<p><a href = continue.php> CLICK HERE TO CONTINUE</a></p>
-----Now the Server has again got the same session variable set under the /var/lib/PHP5. Shouldn't the server not recognize the session variable ? Also if this is happening because of the saved Cookies, then why isn't I'm able to see them under moz_cookies table ..... Please explain ?(This is my second question)
A few items to consider:
Cookies can be stored on disk or in memory. How they are stored is dependent on browser settings (.e.g Private Browsing mode in Firefox) and server settings (see PHP docs on session handling).
HTTP connections can be cached using the Keep-Alive header.
It looks like you are set up to store session ids on the server in a file, but the browser cookie is being stored in memory rather than in a file, which is why you are seeing the PHP file but not a Firefox cookie file.
As to why the server is recognizing the session id even though you deleted the file, it looks like what is happening is that PHP knows the session is authenticated, meaning it must be cached in RAM on the server. (A PHP guru might be able to fill in the specifics of the session mechanics).
After receiving request 3, PHP looks for the session id file and when it doesn't see it, it writes the file again because it knows that the session is valid. This is expected behavior, because if you want to delete the session, you as a PHP programmer should be doing it in PHP rather than deleting the session id file behind the scenes.
You'll notice that the client sent the session id with request 3. The client will send the session id cookie with each request, but the server should not respond with the Set-Cookie instruction again during this session. The browser now has the session id cookie and can send it with each request, thus no further authentication is needed.
The weakness to this strategy is that it could leave open the possibility of session hijacking. If an attacker could obtain the session id cookie from your browser, they could execute commands against the server using your credentials.
Obtaining the session id may or may not be a trivial task for an attacker depending on many factors. If for instance the victim's computer is compromised with a virus or other malware controlled by the attacker, the attacker probably pwns the victim's computer at that point and can do whatever they want, including taking the session id. Other attacks use cross-site scripting ( XSS ) attacks to trick the victim's browser into divulging the session id.
There are specific defenses against XSS and session hijacking, again the subject is fairly complex and worth researching in detail. A more secure session, for instance, might use a one-time token that is changed with every response, although that strategy can be complicated by the use of asynchronous HTTP calls.
Till here there has no exchange of session ids or cookies. (If I'm wrong, prompt me ?)
No, that's correct. Until here, session_start hasn't been called, so there are no session cookies to exchange.
Now the Server has again got the same session variable set under the /var/lib/PHP5. Shouldn't the server not recognize the session variable ?
It probably should, but it isn't. What I think is happening: When a client sends a session id, the server is happy to use it, even if it doesn't know it yet. This can (in theory) be used for session fixation, which is why it is recommended to regenerate ids each time something in the session changes (in practice, session.use_trans_sid is set to 0 by default, which makes session fixation less of an issue).
What I find odd is that the data is also still there (I couldn't replicate this behavior). My guess would be that you are actually re-submitting the form?
Also if this is happening because of the saved Cookies, then why isn't I'm able to see them under moz_cookies table
My guess is that the cookies are still in the browser memory. Did you try the same thing, but deleting the cookie via the browser interface?
Misc
I know that this is just a test script, but still:
prepared statements are recommended over simple escaping.
don't store plaintext passwords in sessions).
don't echo user input unsanitized.
hashes should be user specific, not site specific.
htmlentities protects against XSS, not SQL injection, and should thus be applied when echoing data, not when inserting it into the database.

CORS complaint on Safari 5.1.7 (windows 7)

A page at http://www4.example.com that tries to an xhr connection to http://www6.example.com/
The browser sends a GET request with this header:
Origin: http://www4.example.com
The www6.example.com server sends back:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://www4.example.com
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/plain
Date: ...
Keep-Alive: timeout=5, max=100
Transfer-Encoding: Identity
Server: Apache/2.2.20 (Ubuntu)
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.6-13ubuntu3.7
And yet I get:
XMLHttpRequest cannot load http://www6.example.com/myscript.php?xhr=1&t=1234333223. Origin http://www4.example.com is not allowed by Access-Control-Allow-Origin.
My code matches my understanding of the CORS standard, and works fine with Chrome, Firefox, Opera, etc. so I'm going to assume this is a Safari 5.1 bug? My question is what do I need to do to work around it?
After a lot of trial and error, and watching network traffic, I think I can self-answer.
The Safari bug is that it sends an OPTIONS pre-flight request first, even though it is a GET request.
To add some extra complexity, it appears to only send this on the 2nd request. (I think this is because my 2nd request sends an extra custom header... but I couldn't actually isolate that, so I think there is something else going on as well - perhaps cache interactions?)
Sending Access-Control-Allow-Headers in the main response does not fix the problem: it does the OPTIONS request first, so never gets that far.
The fix I did was to put this at the very top of the PHP script:
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
header("Access-Control-Allow-Origin: ".#$_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Last-Event-Id, Origin, X-Requested-With, Content-Type, Accept, Authorization");
exit;
}
Sending back "Access-Control-Allow-Headers: *" did not work. You have to explicitly list the headers you want. I briefly experimented and it appears they are case-insensitive.
Sending back "Access-Control-Allow-Methods: POST, GET, OPTIONS" was not needed.
As an aside, Cookies are sent, but basic auth details are not sent (despite explicitly listing the Authorization header there). This might be a deliberate limitation of the CORS implementation, as of this version of WebKit (534.57.2), not a bug.

WIF: LocalSTS not authenticating

I'm totally new to WIF and to start playing with it a bit I tried the simplest "f5 experience" with an MVC4 application; according to the tutorials I found, which sadly for the most part refer to releases before .net 4.5, I should just create an MVC app, configure it with the identity and access tool and hit f5 to get up and running with local STS. Yet, I'm probably missing something obvious because when I try to access a restricted page I always end bumped back to the homepage.
Here is what I did, you can easily repro the issue with these steps (VS2012 in Win8 with WIF SDK; ensure to launch VS with admin rights):
create a new ASP.NET MVC4 Internet application. Set its port to 7777 (just picking the port number used in most code samples for the sake of commodity).
update all the NuGet packages (this is optional).
right click the solution, choose identity and access and set the IP=local STS, then click OK. Then reopen the identity and access popup, and choose generate a controller, then click OK.
add an [Authorize] attribute to the About action of the Home controller.
hit F5 and click the About link. As expected, the login view appears, prompting me to login: the only option is of course localSTS. When I click it, I am returned to the homepage and no authentication occurs. I can repeat the process, but nothing changes, so I can never access the secured About page.
The link underlying the localSTS anchor is:
http://localhost:14743/wsFederationSTS/Issue?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a7777%2f&wctx=rm%3d0%26id%3d664ff3c2-95b1-40b3-b538-a8357233ea7e%26ru%3dhttp%253a%252f%252flocalhost%253a7777%252f&wct=2013-03-10T13%3a39%3a32Z
AFAIK, its parameters look OK.
If I examine the network traffic, I cannot see any relevant item (if I understand well, I would expect a response setting some cookies for the current session, representing the IClaimsPrincipal).
(BTW, by looking at the web.config, I can see that in modules WSFederationAuthenticationModule is referenced from System.Identity.Services, which is NOT included in the solution after configuring Identity and access; I suppose this is a bug in the tool. Anyway I added a reference to it, but nothing changed.)
Update
Thank you for the reply! If I examine the traffic, here are the relevant GET/POSTs. I get no cookie. I tried recreating the whole test solution, even skipping step #2 above to keep it minimal, but nothing changed.
As for your suggestion #2, I tried to add in global asax:
FederatedAuthentication.WSFederationAuthenticationModule.SecurityTokenValidated
+= (sender, e) => FederatedAuthentication.SessionAuthenticationModule.IsReferenceMode = true;
but the SessionAuthenticationModule is null at the time this code executes and thus a corresponding exception is thrown. I cannot find up-to-date code samples or articles about this, yet WIF seems a very promising tech; I'd like it to be easy for security newbies like me; my main purpose is applying it to a site providing both MVC controllers and WebApi controllers, to a wide range of consumers (JS code, mobile apps, WinRT apps, the site pages themselves...). Any suggestion?
(1) a GET which gets 307, temporary redirect
GET /wsFederationSTS/Issue?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a7777%2f&wctx=rm%3d0%26id%3d664ff3c2-95b1-40b3-b538-a8357233ea7e%26ru%3dhttp%253a%252f%252flocalhost%253a7777%252f&wct=2013-03-10T13%3a39%3a32Z HTTP/1.1
Host: localhost:14743
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22
Referer: http://localhost:7777/HrdAuthentication/Login?ReturnUrl=%2fHome%2fAbout
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie:
(2) GET with signin request:
GET /wsFederationSTS/Issue/?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a7777%2f&wctx=rm%3d0%26id%3d664ff3c2-95b1-40b3-b538-a8357233ea7e%26ru%3dhttp%253a%252f%252flocalhost%253a7777%252f&wct=2013-03-10T13%3a39%3a32Z HTTP/1.1
Host: localhost:14743
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22
Referer: http://localhost:7777/HrdAuthentication/Login?ReturnUrl=%2fHome%2fAbout
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie:
(3) a POST to the homepage: the respone is of course the homepage content; no cookies set.
POST / HTTP/1.1
Host: localhost:7777
Connection: keep-alive
Content-Length: 7063
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Origin: http://localhost:14743
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:14743/wsFederationSTS/Issue/?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a7777%2f&wctx=rm%3d0%26id%3d664ff3c2-95b1-40b3-b538-a8357233ea7e%26ru%3dhttp%253a%252f%252flocalhost%253a7777%252f&wct=2013-03-10T13%3a39%3a32Z
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie:
A working variation
I found a way for letting it work, maybe this can be useful to someone else: if you follow the above procedure without changing from the local IIS server to the VS development server, it seems it's working and I'm still redirected to the Home page (I wonder why:), but as an authenticated user; at this point, I can click the About link again to effectively enter the page.
I reproduce your steps and everything worked. Chrome debugger show that you must have two steps:
GET http://localhost:12263/wsFederationSTS/Issue/?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a54306%2f&wctx=rm%3d0%26id%3dc6e46b99-417b-49b6-96a0-40efcead898f%26ru%3dhttp%253a%252f%252flocalhost%253a54306%252f&wct=2013-03-10T18%3a14%3a19Z
POST http://localhost:54306/ with wa:wsignin1.0 and wresult:trust:RequestSecurityTokenResponseCollection
Result of POST is Set-Cookie named FedAuth and FedAuth1. Cookie is split because of cookie size limit.
Please check this in debugger.
p.s. Once i saw a same behavior - cookie is not set normally. Problem was in cookie size and solved by switching to ReferenceMode. Don't forget to to register it in Application_Start:
FederatedAuthentication.WSFederationAuthenticationModule.SessionSecurityTokenCreated
+= this.WSFederationAuthenticationModule_SessionSecurityTokenCreated;

Analysis of HTTP header

Hello I want to analyze & understand at first place and then optimize the HTTP header responses of my site. What I get when I fetch as Google from webmasters is:
HTTP/1.1 200 OK
Date: Fri, 26 Oct 2012 17:34:36 GMT // The date and time that the message was sent
Server: Apache // A name for the server
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM" // P3P Does an e-commerse store needs this?
ETag: c4241ffd9627342f5f6f8a4af8cc22ed // Identifies a specific version of a resource
Content-Encoding: gzip // The type of encoding used on the data
X-Content-Encoded-By: Joomla! 1.5 // This is obviously generated by Joomla, there wont be any issue if I just remove it, right?
Expires: Mon, 1 Jan 2001 00:00:00 GMT // Gives the date/time after which the response is considered stale: Since the date is set is already expired, this creates any conflicts?
Cache-Control: post-check=0, pre-check=0 // This means site is not cached? or what?
Pragma: no-cache // any idea?
Set-Cookie: 5d962cb89e7c3329f024e48072fcb9fe=9qdp2q2fk3hdddqev02a9vpqt0; path=/ // Why do I need to set cookie for any page?
Last-Modified: Fri, 26 Oct 2012 17:34:37 GMT
X-Powered-By: PleskLin // Can this be removed?
Cache-Control: max-age=0, must-revalidate // There are 2 cache-controls, this needs to be fixed right? which one is preffected? max-age=0, must-revalidate? post-check=0, pre-check=0?
Keep-Alive: timeout=3, max=100 // Whats that?
Connection: Keep-Alive
Transfer-Encoding: chunked // This shouldnt be deflate or gzip ??
Content-Type: text/html
post-check
Defines an interval in seconds after which an entity must be checked for freshness. The check may happen after the user is shown the resource but ensures that on the next roundtrip the cached copy will be up-to-date.
http://www.rdlt.com/cache-control-post-check-pre-check.html
pre-check
Defines an interval in seconds after which an entity must be checked for freshness prior to showing the user the resource.
Pragma: no-cache header field is an HTTP/1.0 header intended for use in requests. It is a means for the browser to tell the server and any intermediate caches that it wants a fresh version of the resource, not for the server to tell the browser not to cache the resource. Some user agents do pay attention to this header in responses, but the HTTP/1.1 RFC specifically warns against relying on this behavior.
Set-Cookie: When the user browses the same website in the future, the data stored in the cookie can be retrieved by the website to notify the website of the user's previous activity.[1] Cookies were designed to be a reliable mechanism for websites to remember the state of the website or activity the user had taken in the past. This can include clicking particular buttons, logging in, or a record of which pages were visited by the user even months or years ago.
X-Powered-By: specifies the technology (e.g. ASP.NET, PHP, JBoss) supporting the web application.This comes under common non-standard response headers and can be removed.
Keep-Alive It is meant to reduce the number of connections for a website. Instead of creating a new connection for each image/css/javascript in a webpage many requests will be made re-using the same connection.
Transfer-Encoding: The form of encoding used to safely transfer the entity to the user. Currently defined methods are: chunked, compress, deflate, gzip, identity.

How to get a long url from a short url

I would like to determine what the long url of a short url is. I have tried using http HEAD requests, but very few of the returned header fields actually contain any data pertaining to the destination/long url.
Is there:
1. Any way to determine the long url?
2. If so, can it be done without downloading the body of the destination?
Thank you
Issue an HTTP GET request, don't follow the redirect, analyse the Location header. That's where the target of redirection is.
Specifically in Cocoa, use an asynchronous request with a delegate, handle the didReceiveResponse in the delegate. The first response will be the redirection one. Once you extract the URL in the handler, call [cancel] on the connection.
EDIT: depending on the provider, HEAD instead of GET might or might not work. And if you don't follow the redirect, the response data won't be loaded anyway, so there's no transmission overhead to having a GET.
Do a HEAD and look for the Location header.
% telnet bit.ly 80
Trying 168.143.173.13...
Connected to bit.ly.
Escape character is '^]'.
HEAD /cwz5Jd HTTP/1.1
Host: bit.ly
HTTP/1.1 301 Moved
Server: nginx/0.7.42
Date: Fri, 12 Mar 2010 18:37:46 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Set-Cookie: _bit=4b9a89fa-002bd-030af-baa08fa8;domain=.bit.ly;expires=Wed Sep 8 14:37:46 2010;path=/; HttpOnly
Location: http://www.engadget.com/2010/03/12/motorola-milestone-with-android-2-1-hitting-bulgaria-by-march-20/?utm_source=twitterfeed&utm_medium=twitter
MIME-Version: 1.0
Content-Length: 404
LongUrlPlease offers an API which expands short urls.