ASP.NET MVC Website Partial SSL Authentication cookie not submitted in request - asp.net

I'm trying to make a POC of which is possible to have a website that uses http and https. So i have a control in my master page that needs info if the user is authenticated or not. For this I want to use HttpContext.Current.User.Identity.IsAuthenticated. If is authenticated shows info for authenticated users, if not appear the login control.
To authenticate the control make an AJAX POST request to the Login action that has the [RequireHttps] attribute. The URL used in the AJAX request is:
$.ajax({
type: 'POST',
url: '#Url.Action("ModalLogIn", "Authentication", null, "https", Request.Url.Host + ":44300")',
By the way I'm using VS2013 IIS express with SSL enabled.
As you can see in my AJAX request i'm using the HTTPS in action url.
The request is made to the server using SSL and the response is made with success.
The problem is that in the subsequent requests the ASPXAUTH cookie is not passed in the request header. So the server does not get the user authentication info. The subsequent requests are made with no SSL, are simple HTTP requests.
I know that in security terms the authentication is still insecure because i'm expecting to pass the ASPXAUTH through HTTP, but like I said is a POC and I want to see if it is possible to make a simple authentication request using HTTPS and all the others using HTTP.
As requested this is the Response Headers:
Access-Control-Allow-Orig... *
Cache-Control private
Content-Length 15
Content-Type application/json; charset=utf-8
Date Sat, 26 Oct 2013 18:57:55 GMT
Server Microsoft-IIS/8.0
Set-Cookie ASP.NET_SessionId=j2a53htev0fjp1qq4bnoeo0l; path=/; HttpOnly
ASP.NET_SessionId=j2a53htev0fjp1qq4bnoeo0l; path=/; HttpOnly
IAC.CurrentLanguage=en; expires=Sun, 26-Oct-2014 19:57:55 GMT; path=/
.ASPXAUTH=730DEDBFD2DF873A5F2BD581AA0E25B685CAD12C26AEA63AD82484C932E26B617687A05BB403216CC5EFCF799970810059F9CA2CF829F953580AF81FF48102003C0129AB04424F0D011A733CAAF1DE00688E5A4C93DEA97338DD2B5E7EE752F3761A470D52449BEBCA74098912DE37AA8C1E293B1C5D44EB1F9E9384DAAEF289; path=/; HttpOnly
X-AspNet-Version 4.0.30319
X-AspNetMvc-Version 3.0
X-Powered-By ASP.NET
X-SourceFiles =?UTF-8?B?QzpcTXkgRGF0YVxCaXRidWNrZXRcaWFjLXdlYnNpdGVcaW1wbGVtZW50YXRpb25cZG90bmV0XElBQy5XZWJcQXV0aGVudGljYXRpb25cTW9kYWxMb2dJbg==?=

It might be that when you set the auth cookie, it is marked as "Secure".
Using the Chrome Developer Tools, click on 'Resources', then cookies. Under the 'Secure' column check if the cookie is marked. If it is, then this means that the browser will not send the auth cookie using a non-secure connection.

Just a shot in the dark, but try setting the ASPXAUTH cookie with an expiration date.
It's possible that the browser, upon receiving a session cookie, will only present the session cookie on connections using the same protocol (https) as when it was set. I know for sure that persistent cookies do not have this limitation.
Also, investigate whether port could be the issue. If your AJAX goes over 44300 and your web goes over 80 or 443, it's possible the cookie is lost because the browser considers secure cookies to be port-specific. The W3C spec doesn't say whether cookies are private with respect to port; browsers vary.

All things work perfect like that ajax request in HTTPS manner by JS. Related respond works correctly too. But it seems that you have not prepared Login page in SSL too! My meaning is :
[RequireHttps]
public ActionResult Login()
{
return View();
}
Then Send request to HttpPost enabled Action. I believe that will work correctly. Unless you had some lack of requirements like MicrosoftMvcAjax.js and MicrosoftAjax.js in situations that you are using formal Microsoft ajax form by your ViewEngine (Perhaps by Razor). I think studying this Article can help you more.
Good Luck.

Related

Removing hash from URL on HTTP redirect

I just added a feature on a website to allow users to log in with Facebook. As part of the authentication workflow Facebook forwards the user to a callback URL on my site such as below.
https://127.0.0.1?facebook-login-callback?code.....#_=_
Note the trailing #_=_ (which is not part of the authentication data, Facebook appears to add this for no clear reason)
Upon receiving the request in the backend I validate the credentials, create a session for the user, then forward them to the main site using a Location header in the HTTP response.
I've inspected the HTTP response via my browser developer tools and confirmed I have set the location header as.
Location: https://127.0.0.1/
The issue is that the URL that appears in the browser address bar after forwarding is https://127.0.0.1/#_=_
I don't want the user to see this trailing string. How can I ensure it is removed when redirecting the user to a new URL?
The issue happens in all browsers I have tested. Chrome, Firefox, Safari and a few others
I know a similar question has been answered in other threads however there is no jquery or javascript in this workflow as in the other threads. All the processing of the login callback happens in backend code exlusively.
EDIT
Adding a bounty. This has been driving up the wall for some time. I have no explanation and don't even have a guess as to what's going on. So I'm going to share some of my hard earned Stackbux with whoever can help me.
Just To be clear on a few points
There is no Javascript in this authentication workflow whatsoever
I have implemented my own Facebook login workflow without using their Javascript libraries or other third party tools, it directly interacts with the Facebook REST API using my own Python code in the backend exclusively.
Below are excerpts from the raw HTTP requests as obtained from Firefox inspect console.
1 User connects to mike.local/facebook-login and is forwarded to Facebook's authentication page
HTTP/1.1 302 Found
Server: nginx/1.19.0
Date: Sun, 28 Nov 2021 10:44:30 GMT
Content-Type: text/plain; charset="UTF-8"
Content-Length: 0
Connection: keep-alive
Location: https://www.facebook.com/v12.0/dialog/oauth?client_id=XXX&redirect_uri=https%3A%2F%2Fmike.local%2Ffacebook-login-callback&state=XXXX
2 User accepts and Facebook redirects them to mike.local/facebook-login-callback
HTTP/3 302 Found
location: https://mike.local/facebook-login-callback?code=XXX&state=XXX#_=_
...
Requested truncated here. Note the offending #_=_ in the tail of the Location
3 Backend processes the tokens Facebook provides via the user forwarding, and creates a session for the user then forwards them to mike.local. I do not add #_=_ to the Location HTTP header as seen below.
HTTP/1.1 302 Found
Server: nginx/1.19.0
Date: Sun, 28 Nov 2021 10:44:31 GMT
Content-Type: text/plain; charset="UTF-8"
Content-Length: 0
Connection: keep-alive
Location: https://mike.local/
Set-Cookie: s=XXX; Path=/; Expires=Fri, 01 Jan 2038 00:00:00 GMT; SameSite=None; Secure;
Set-Cookie: p=XXX; Path=/; Expires=Fri, 01 Jan 2038 00:00:00 GMT; SameSite=Strict; Secure;
4 User arrives at mike.local and sees a trailing #_=_ in the URL. I have observed this in Firefox, Chrome, Safari and Edge.
I have confirmed via the Firefox inspect console there are no other HTTP requests being sent. In other words I can confirm 3 is the final HTTP response sent to the user from my site.
According to RFC 7231 §7.1.2:
If the Location value provided in a 3xx (Redirection) response does
not have a fragment component, a user agent MUST process the
redirection as if the value inherits the fragment component of the
URI reference used to generate the request target (i.e., the
redirection inherits the original reference's fragment, if any).
If you get redirected by Facebook to an URI with a fragment identifier, that fragment identifier will be attached to the target of your redirect. (Not a design I agree with much; it would make sense semantically for HTTP 303 redirects, which is what would logically fit in this workflow better, to ignore the fragment identifier of the originator. It is what it is, though.)
The best you can do is clean up the fragment identifier with a JavaScript snippet on the target page:
<script async defer type="text/javascript">
if (location.hash === '#_=_') {
if (typeof history !== 'undefined' &&
history.replaceState &&
typeof URL !== 'undefined')
{
var u = new URL(location);
u.hash = '';
history.replaceState(null, '', u);
} else {
location.hash = '';
}
}
</script>
Alternatively, you can use meta refresh/the Refresh HTTP header, as that method of redirecting does not preserve the fragment identifier:
<meta http-equiv="Refresh" content="0; url=/">
Presumably you should also include a manual link to the target page, for the sake of clients that do not implement Refresh.
But if you ask me what I’d personally do: leave the poor thing alone. A useless fragment identifier is pretty harmless anyway, and this kind of silly micromanagement is not worth turning the whole slate of Internet standards upside-down (using a more fragile, non-standard method of redirection; shoving yet another piece of superfluous JavaScript the user’s way) just for the sake of pretty minor address bar aesthetics. Like The House of God says: ‘The delivery of good medical care is to do as much nothing as possible’.
Not a complete answer but a couple of wider architectural points for future reference, to add to the above answer which I upvoted.
AUTHORIZATION SERVER
If you enabled an AS to manage the connection to Facebook for you, your apps would not need to deal with this problem.
An AS can deal with many deep authentication concerns to externalize complexity from apps.
SPAs
An SPA would have better control over processing login responses, as in this code of mine which uses history.replaceState.
SECURITY
An SPA can be just as secure as a website with the correct architecture design - see this article.

Set Cookies in SOAP header

I have a requirement where i need to invoke a SOAP Webservice operation for login and get the cookie from the SOAP response and use the cookie to invoke another SOAP operation to retrieve some data. The Login operation response has a cookie(Set-Cookie) which looks like ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax
Now how do i map this cookie to the retrieve operation. Do i map ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb; path=/; HttpOnly; SameSite=Lax fully or just ASP.NET_SessionId=vqjucdxcxrgg5swr0f3z0peb or just vqjucdxcxrgg5swr0f3z0peb. I tried all three options and i am getting java.lang.IllegalArgumentException: Port may not be negative error when i invoke the retrieve operation. Please let me know if i am doing anything wrong. I am using Tibco BW to invoke the SOAP operations.
Found the answer to my question in the link https://en.wikipedia.org/wiki/HTTP_cookie .Please read below
Setting a cookie
Cookies are set using the Set-Cookie HTTP header, sent in an HTTP response from the web server. This header instructs the web browser to store the cookie and send it back in future requests to the server (the browser will ignore this header if it does not support cookies or has disabled cookies).
As an example, the browser sends its first request for the homepage of the www.example.org website:
GET /index.html HTTP/1.1
Host: www.example.org
...
The server responds with two Set-Cookie headers:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
...
The server's HTTP response contains the contents of the website's homepage. But it also instructs the browser to set two cookies. The first, "theme", is considered to be a session cookie since it does not have an Expires or Max-Age attribute. Session cookies are intended to be deleted by the browser when the browser closes. The second, "sessionToken", is considered to be a persistent cookie since it contains an Expires attribute, which instructs the browser to delete the cookie at a specific date and time.
Next, the browser sends another request to visit the spec.html page on the website. This request contains a Cookie HTTP header, which contains the two cookies that the server instructed the browser to set:
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
…
This way, the server knows that this request is related to the previous one. The server would answer by sending the requested page, possibly including more Set-Cookie headers in the response in order to add new cookies, modify existing cookies, or delete cookies.
The value of a cookie can be modified by the server by including a Set-Cookie header in response to a page request. The browser then replaces the old value with the new value.
Cookie attributes
In addition to a name and value, cookies can also have one or more attributes. Browsers do not include cookie attributes in requests to the server—they only send the cookie's name and value. Cookie attributes are used by browsers to determine when to delete a cookie, block a cookie or whether to send a cookie to the server.

Session Cookie secure/httponly

I was searching the internet quite a time but I didn't find a satisfying answer to my question.
I have to get a json object from a certain http site. I do this with a get-request over http (site is available only over http). The site responds with a session cookie:
Set-Cookie: session_id=95656983e1feaff45a000aa7f2f9093a1ea4b1c3; expires=Fri, 20 Apr 2018 14:00:51 GMT; httponly; Max-Age=3600; Path=/; secure
My first question is why the cookie is sent over http when httponly & secure flag are set??
After I get the json object I have to do some fancy stuff and send a json object back to an other site of the same domain. Also this site is available only via http. (I do the requests in python with python-requests and use requests.session() for dealing with the cookies so no problem there). When I look through the header of my request with mitmproxy I see that no cookie is set and the page responds with "WHERE'S MY COOKIE??"
I think the problem is with httponly & sercur flag. I just don't know how to deal with it because the page is only available over http and not https?
Secure attribute instructs the client/browser to only return the cookie when using a secure channel, but such a cookie can be set by the application/server on to the client/browser over normal HTTP. You are correct the secure flag is causing the problem and AFAIK there is no way to work around it

Is there any Http Caching for ASP.Net Web Forms?

I have an ASP.Net Web Forms application. The blog post "CacheCow Series - Part 0: Getting started and caching basics" mentions that Output Caching uses HttpRuntime.Cache behind the scene -hence not HTTP caching. The request reaches the server and cached response is sent from the server (when the valid cached output is avaialble on the server). So the entire content is sent across the wire.
Is there any HTTP Caching available for ASP.Net Web Forms (where response content is not sent from the server, if cache is valid; but the client takes it from it's HTTP Cache after getting validity information (only) from the server)?
REFERENCES
Is page output cache stored in ASP.NET cache object?
Things Caches Do - Ryan Tomayko - 2ndscale.com/
Actually the OutputCache directive is used for both Client as Server side caching. When you set the Location of that directive to Any, Client, Downstream or ServerAndClient, proper cache response headers are set such that browsers or proxies won't request the same page again and serve the cached version of your page. But keep in mind that those clients are free to request those pages again.
Location options with their Cache-Control headers after setting directive:
<%# OutputCache Location="XXX" Duration="60" VaryByParam="none" %>
Client: private, max-age=60
Downstream: public, max-age=60
Any: public
ServerAndClient: private, max-age=60
Server: no-cache
No output directive: private

Is it possible to set a cookie during a redirect in ASP.NET?

I am using ASP.NET. I either add or set a cookie (depending on whether the HttpRequest contains a cookie with specified key), and immediately afterward call Response.Redirect. The cookie is not set. Is this correct behavior? Is there something mutually exclusive about setting a cookie during an http response with a 302 status code?
Here's the source:
if (context.HttpContext.Request.Browser.Cookies)
{
var cookies = context.HttpContext.Request.Cookies;
var stateCookie = new HttpCookie(SR.session, clientState.SessionId.ToString());
if (cookies.AllKeys.Contains(SR.session))
{
context.HttpContext.Response.Cookies.Set(stateCookie);
}
else
{
context.HttpContext.Response.Cookies.Add(stateCookie);
}
}
Here are the Response headers
X-AspNetMvc-Version - 2.0
Connection - Close
Cache-Control - private
Content-Type - text/html
Date - Sun, 20 Mar 2011 03:48:04 GMT
Location - http://localhost:3599/Home/Redirected
Server - ASP.NET Development Server/9.0.0.0
X-AspNet-Version - 2.0.50727
After googling a bit it seems that yes, there can be problems with setting the cookie in the redirect response as it may be ignored by a few browsers. (It may make some sense, as the response is really telling the client to ignore the resource and get some other resource instead).
This has been discussed here already: Sending browser cookies during a 302 redirect
So I would change the architecture in a way that allows the page being redirected to to set the cookie.

Resources