localhost cookies not set - asp.net-mvc

I'm trying to set a cookie in my application.
Here's the code that sets the cookie:
public HttpResponseMessage LogIn(UserLoginVM user)
{
// Do login stuff
var cookie = new CookieHeaderValue("STUPID-COOKIE", "12345");
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
cookie.HttpOnly = true;
// Get user's profile
HttpResponseMessage res = Request.CreateResponse<UserProfileVM>(HttpStatusCode.OK, profile);
res.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return res;
}
The response from the server is the following:
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
Set-Cookie: STUPID-COOKIE=12345; domain=localhost; path=/; httponly
Access-Control-Allow-Origin: *
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcUFJPSkVDVFNcU2Ftc2tpcC5TZXJ2aWNlV2ViTmV3XFNhbXNraXAuQXV0aEFQSVxTYW1za2lwLkF1dGhBUElcbG9naW4=?=
X-Powered-By: ASP.NET
Date: Wed, 18 Feb 2015 11:58:07 GMT
Content-Length: 8019
Notice the following header:
Set-Cookie: STUPID-COOKIE=12345; domain=localhost; path=/; httponly
However, when I go under "Cookies" in "Resources" tab in Chrome, nothing is set. Also when I send a request to the server no cookie is in the headers.
Here's the code that reads the cookie:
CookieHeaderValue cookie = Request.Headers.GetCookies("STUPID-COOKIE").FirstOrDefault();
cookie variable is always null.
My application is running on http://localhost:53998 and the authentication service is running on http://localhost:60858
My Chrome version is 40.0.2214.111.
Here's a GIF demonstrating the problem:
http://i.imgur.com/q7lkXBz.gif
Edit: This seems to be non-specific to Chrome. This doesn't work on FireFox (v35) either. GIF: http://i.imgur.com/ZewnEtc.gif

I ran into this issue today and Gaui's answer was quite useful to me, bearing in mind ideally you do not want to open up your server to CORS requests from any site. I'm in my dev environment and my server and client are on different origins since they are on different ports on localhost. Also I'm using .net core 3.0
My issue was caused by my server not sending cookies to my client side as my CORS settings were blocking the sending of cookie to my domain this was evident by the server not using the header Access-Control-Allow-Credentials: true. To resolve this I configured my server in Startup.cs to allow requests from my client side to allow credentials (A credential is a cookie's authorization headers or TLS client certificates).
var allowedOrigins = new[] {"localhost:3000"}; // Ideally comes from appsettings
app.UseCors(builder =>
builder.WithOrigins(allowedOrigins).AllowCredentials().AllowAnyMethod().AllowAnyHeader().Build());
For the cookie options; I found that the you do not have to set Domain if you do not want to, Secure works even when the site is not using https.
Google chrome now supports cookies on localhost, I believe it didn't used to as a lot of older SO posts have users who faced that issue.
On the client side, you need to configure it to accept cookies as well, as in Gaui's answer above. I was using fetch, and so had to add the option:
credentials: 'include'
Which tells fetch to retrieve cookies across domains. See the docs here

I highly suspect that localhost is not a valid domain name so Chrome rejects it. If you simply remove 'domain=localhost' from the Set-Cookie then it will work and Chrome will assign the domain to localhost for you.
I would personally create a local domain name like "test.dev" and add it to your Windows hosts file, 127.0.0.1 test.dev

I finally managed to solve this.
In the response from the API I had to add Access-Control-Allow-Credentials: true headers, or by adding the following in the WebApiConfig class:
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
}
Then I had to enable it on the client-side, by setting the withCredentials property in the XMLHTTPRequest object to true. In AngularJS app config function you can do the following:
$httpProvider.defaults.withCredentials = true;
Also, for Chrome, I had to omit the Domain (or set it as null).
Hope this helps others struggling with this.

Related

Asp.Net MVC CORS enabled in Web API but headers no longer being sent

I have two DotNet MVC sites. One accesses a Web API from the other with an AJAX GET call.
This all worked, but has stopped functioning now. I've hardly made any changes on my side, so I'm wondering if my host might have made changes (in IIS, for example) that would stop this from working?
Here's how I initially got it working...
I installed the Microsoft.Aspnet.Cors and Microsoft.Aspnet.WebApi.Cors packages.
I added the following code...
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors();
And in the controller for my API I added...
namespace Webscope.Controllers
{
[EnableCors(origins: "[URL of my other website]", headers: "*", methods: "*")]
public class EventAPIController : ApiController
This used to work, but now get the following error in the console:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https:[my website URL]/EventRead/1-1-2015/12-12-2099. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
In response to #FoggyDay's answer below, I've called the API from Fiddler and got the following headers...
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
X-Frame-Options: AllowAll
X-Powered-By: ASP.NET
Date: Fri, 13 Mar 2020 03:56:39 GMT
Content-Length: 198
So it looks as if CORS headers have not been included in the response. Can anyone tell me why this would be?
UPDATE
I found some extraneous code from a previous attempt to get CORS working. Now that I've removed this code, I am seeing the CORS headers in Fiddler.
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Origin: https://[ calling website's URL ]/
However I'm still getting the following error in my calling site's console...
Access to XMLHttpRequest at
'https://[ destination site URL ]/api/EventRead/1-1-2015/12-12-2099' from
origin '[ calling website's URL ]' has been blocked by CORS
policy: Response to preflight request doesn't pass access control
check: No 'Access-Control-Allow-Origin' header is present on the
requested resource.
SUGGESTIONS:
Back out your "new" changes. It sounds like you've inadvertantly introduced a second header.
Read this: Reason: CORS header 'Access-Control-Allow-Origin' missing
Look at your HTTP traffic, for example in Fiddler. Verify that you're sending the header ... and verify that you're allowing the correct combination of host and port.
If you're still having problems, post back with the exact error message and relevant HTTP headers.

Set-Cookie in response header is not working

I have my backend(Ruby On Rails) running at port number 3000 with login endpoint(http://localhost:3000/login).I also have angular server running on port 4200.So with angular I am hitting login endpoint and upon successful login, response is sent back with Set-cookie option(authentication token is set).But it is not set in the browser.Below is the response header i am receiving:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:POST, GET, OPTIONS
Access-Control-Allow-Origin:http://localhost:4200
Access-Control-Max-Age:1728000
Cache-Control:max-age=0, private, must-revalidate
Content-Type:application/json; charset=utf-8
ETag:W/"9dae161444bc908fd3289f4ed0fb15ed"
Set-Cookie:auth_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJleHAiOjE1MDU4NDM0Nzh9.0E22wlacZWvmazpdJPLC4oRq3QM-8DX-npQu3w-U8Vs; path=/
Transfer-Encoding:chunked
Vary:Origin
X-Request-Id:267cfe1f-e60c-40b5-9a7b-4801d358cfd4
X-Runtime:0.273751
Request Headers
view source
While if I hit that API with Postman then the cookie is saved without problem.

Why isn't my browser storing ASP MVC CORE 2 cookies?

I have an Angular(4) client (localhost:4200) which calls across to an ASP MVC CORE 2 WebApi. One of the calls http://localhost:5000/api/session/resume returns a cookie along with the response.
In the action method I have returned 3 cookies for testing purposes.
[AllowAnonymous, HttpPost, Route("api/session/resume")]
public async Task<AccountSignInResponse> Resume([FromBody]SessionResumeCommand command)
{
AccountSignInResponse apiResponse = await Mediator.Send(command);
if (!apiResponse.HasErrors) {
Response.Cookies.Append("TestCookie", ..., new CookieOptions
{
Domain = "localhost",
Expires = DateTimeOffset.Now.AddDays(100),
HttpOnly = false
});
Response.Cookies.Append("TestCookie4200", ..., new CookieOptions
{
Domain = "localhost:4200",
Expires = DateTimeOffset.Now.AddDays(100),
HttpOnly = false
});
Response.Cookies.Append("TestCookie5000", ..., new CookieOptions
{
Domain = "localhost:5000",
Expires = DateTimeOffset.Now.AddDays(100),
HttpOnly = false
}); }
return apiResponse;
}
The header for this request is
Request URL:http://localhost:5000/api/session/resume
Request Method:POST
Status Code:200 OK
Remote Address:[::1]:5000
Referrer Policy:no-referrer-when-downgrade
And the response headers are
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Vary: Origin
Server: Kestrel
Set-Cookie: TestCookie=XXVtPqCdZ%2BBt9IbhP5Bi7sOLZ%2F%2BELB4fZ0rFArkM%2Be4%3D; expires=Fri, 03 Nov 2017 09:47:28 GMT; domain=localhost; path=/
Set-Cookie: TestCookie4200=XXVtPqCdZ%2BBt9IbhP5Bi7sOLZ%2F%2BELB4fZ0rFArkM%2Be4%3D; expires=Fri, 03 Nov 2017 09:47:28 GMT; domain=localhost:4200; path=/
Set-Cookie: TestCookie5000=XXVtPqCdZ%2BBt9IbhP5Bi7sOLZ%2F%2BELB4fZ0rFArkM%2Be4%3D; expires=Fri, 03 Nov 2017 09:47:28 GMT; domain=localhost:5000; path=/
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
X-SourceFiles: =?UTF-8?B?QzpcZGV2XFhlcnhlc1xYZXJ4ZXMtU2VydmVyXFNlcnZlclxhcGlcc2Vzc2lvblxyZXN1bWU=?=
X-Powered-By: ASP.NET
Date: Wed, 26 Jul 2017 09:47:28 GMT
As you can see, the cookies are being returned from the http://localhost:5000/api/session/resume call, but they are not being stored in my local cookies in either Chrome, Edge, or Firefox. So when further requests are made for images and other resources I am only seeing another cookie (cookieLawSeen), and not this cooked.
When I browse the cookies for localhost in all of these browsers I don't see any SessionTokens in the storage. However, if I look at the request in the F12 developer tools I can click the [Cookies] tab and see ResponseCookies contains all three cookies.
You need to use withCredentials property. It is needed for both sending and receiving cookies:
indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates.
Set it to true each time when you do api call from Angular. Something like the following:
this.http.get('http://...', { withCredentials: true })
I had the same problem and i found out that in .net core 2 the default of session cookie was changed from "Send for: Any kind of connection" to send only to same origin. In my case the server was at a different domain from local host and there for the cookie was not sent to the server.
In order to allow it you need to change the property of the session cookie called SameSite to SameSiteMode.None.
In addition to the above I haven't been able to access a localhost server from the local postman (even-though they have the same origin). the above solved it as well.

Why is action result cached?

I have an action that generates a password reset link and emails it to the user
public ActionResult SendResetPasswordEmail(string userName)
{
var webUser = LoadUser(userName);
if (webUser != null)
{
var token = WebSecurity.GeneratePasswordResetToken(webUser.UserName);
emailSender.SendPasswordResetEmail(webUser, token, resetAction);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "No user found with username: " + userName);
}
The first time I call the action from the browser, I get an HTTP 200 response (and hit my breakpoint in the action).
The second time I call the action from the browser, I get an HTTP 304 response indicating that the content is unchanged.
There are no [OutputCache] attributes anywhere in the source file (not on the class or the action).
What is causing the web server to decide that the content is unchanged and return the HTTP 304?
I'm aware of a work-around
https://stackoverflow.com/a/18620970/141172
I'm interested in understanding the root cause for the HTTP 304 response.
Update
Headers on first request:
Request Headers
Request GET /Companies/SendResetPasswordEmail/?userName=ej HTTP/1.1
X-Requested-With XMLHttpRequest
Accept */*
Referer http://local:6797/Companies
Accept-Language en-US
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host localhost:6797
DNT 1
Connection Keep-Alive
Cookie __RequestVerificationToken=sNOBS6qz32LtnJpLWgHHELhaE44DfIVE1LSMUgjzHjcwsvxlUFa4lOSyA5QeB8keLXYL08Psjg29CRI7W73uHLJy6A81; .ASPXAUTH=DAF8AF47E955F723EE9438866BE1B4BFBF91BA01912EF087824F03581DBCA05A4AECA01373FAF40DF0C4D5C17F17DEFA2F85C1B702988B7E0F750BFE19566FC711C7D6BD81D8F0B0ABD68AF5B3D9BA032286361F; ASP.NET_SessionId=5e2gcvkc2p3rji25z5emyqzd; HelixPlugins1.0=IEPlugin1.0
Response Headers
Response HTTP/1.1 200 OK
Server ASP.NET Development Server/11.0.0.0
Date Thu, 03 Apr 2014 23:29:02 GMT
Cache-Control private, s-maxage=0
Content-Length 0
Connection Close
NOTE: I changed localhost to local in the above because StackOverflow does not allow links containing localhost to be posted :-)
The browser is Internet Explorer 10.
IE caches ajax responses by default, you need to explicitly tell it not to do any ajax caching by setting your ajax object's cache property to false.
Browsers such as Chrome automatically append a random token to your request to make it unique.

ASP MVC 3 cookie losing HttpOnly and Secure flags

I am setting cookies as part of my mvc application:
var cookie = new HttpCookie(CookieName, encryptedData)
{
Path = FormsAuthentication.FormsCookiePath,
Domain = CookieDomain,
Expires = authenticationTicket.Expiration,
HttpOnly = true,
Secure = IsSecure // true
};
response.Cookies.Add(cookie);
Now if I debug I see that its all working fine, no problems and its added and thats fine too. However for some reason when it actually reaches the browser there is no HttpOnly flag or Secure flag set. So im a bit baffled...
I have tried setting the HttpOnly and Secure flags in the cookie web.config entry under System.Web:
<httpCookies httpOnlyCookies="true" requireSSL="true" />
Now here is how the response looks when the browser receives it:
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Max-Age: 10000
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type, x-requested-with, *
Access-Control-Allow-Origin: http://localhost:34567
X-AspNetMvc-Version: 3.0
X-AspNet-Version: 4.0.30319
Set-Cookie: myCookie=53BA8AF84835A81E014B9174329D8543FBB6029B71C463C6FC1305D9F966F28EAA058FE103325C0F10A3012480FB0EF3F6C0BAC4703A6A6B725F383ADA35A5C125A0438FC42CADCB0DAB77953C967E6660E51C4113C6545220A0C2F86230F446D159D523BBE9CA4D9419A67BC44D23B9C4D0974DF2ED66C47EA7308D8E42E1C2280EA6059A23303E3BCBDF28F6BD4A3DFA92FFAB33DDAC8EC05D99310D26FBD6310252156CD28B89386B0D483D6D2E295EF33487E64468655371CC446E0B5DDBF12B3AA8218AF1FA929A98638A1AC729BA60815B86EAD9624ED1787172B585BE4E457C3568AB6EAAF4865E8468D04336FA7340AAC1BA75162FB322D436DC9BF50466F2F0FB3464ECF41C6C1F7001639DFE2AB2AD9CBFB65A292FE5FA42783DF331AA4641432647BA9672FE6D4C15F830E4DF8B38605852BCB15E5B01B862D966E2FD1D620730312982DB8AB4CE5EE0D0E40E6C3F5234DE5EBFA594036D912F07C3798ED429A2552AD6C4B9EC10B90749850CBDEC97F0BF7E2E43CB3991608C5D533B6EA9F8D0A7AD949B42CD3BAA13DEE99C330121B3D868B412A3435FA01C7F223641CFE441A2E07F5DFB8B23F053CBA13F5E1262A07FBFD4EC4BADF9BD5898; expires=Wed, 27-Feb-2013 19:15:24 GMT; path=/
Date: Wed, 27 Feb 2013 18:45:24 GMT
Content-Length: 2
So am I missing something here? or is there something that I am not setting somewhere that I should be? I am also using CORS because this cookie is issued from a webserver as an authentication mechanism. SSL is enabled and is also being used via https for calls. Even if I turn secure cookies off and use http, the HTTPOnly flag is not being set either, so I am baffled.
=== Update ===
Having double checked it appears I misinformed you, the HttpOnly response is sent down from the server correctly on the first time you receive the cookie, HOWEVER! when an ajax call then sends the cookie to the server it seems to not add the httponly flag, which then means the cookie being thrown around is no longer as secure. The secure part of the cookie is not sent down on the first response, but at least this adds a bit more context to it all.
Try this, looks like a similar issue. (How can I set the Secure flag on an ASP.NET Session Cookie?)
In the <system.web> element, add the following element:
<httpCookies requireSSL="true" />
However, if you have a <forms> element in your system.web\authentication block, then this will override the setting in httpCookies, setting it back to the default false.
In that case, you need to add the requireSSL="true" attribute to the forms element as well.
So you will end up with:
<system.web>
<authentication mode="Forms">
<forms requireSSL="true">
/* forms content */
</forms>
</authentication>
</system.web>
It seems like this is all correct behaviour, I wrote another question specifically about the httponly client cookie behaviour, and that led to another post... what a rabbit hole.
What should be the correct behaviour of browser when sending and receiving httponly cookie via ajax?
Anyway that seems to indicate the server needs to keep tampering with the cookie to add the HttpOnly behaviour.
I have made a custom httpmodule which will check for the cookie in question and re-apply the desired behaviour to the cookie (based on configurations from the web.config)

Resources