I have a basic SPA (react) <-> API (net core 2.2) setup, with 2 environments: dev and prod (small project). There is an authentication mechanism on the API
side that checks the presence of a httponly
cookie in every request containing a JWT.
On the dev environment, it works okey-dokey: allowCredentials()
is set in the API and withCredentials = true
in the react app as well. Both run on a different port of my localhost.
But in a production environment (separate Heroku dynos), it just WON'T set the httponly
cookie: I can login using my credentials, the response-headers contain the cookie with the jwt, but every other request i'll make will NOT contain the cookie header at all in request-headers !
I then get a 401 Unauthorized ...
error (which is logical). It drives me nuts as I spent hours trying about everything.
My simple authentication XHR (vanilla) call:
var request = new XMLHttpRequest()
request.open('POST', apiAuthenticateUser, true)
request.setRequestHeader('Content-type', 'application/json')
request.withCredentials = true
request.send(postData)
my Startup.cs
config in the .net core api :
public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
if (env.IsDevelopment()) {
app.UseDeveloperExceptionPage();
IdentityModelEventSource.ShowPII = true;
} else {
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors(
options => options.WithOrigins(
"https://localhost:3000",
"*productionEnvUrl*").AllowAnyMethod().AllowCredentials().AllowAnyHeader()
);
app.UseMvc(routes => {
routes.MapRoute("MainRoute", "api/{controller}/{action}");
});
app.UseAuthentication();
}
and thats how i set my httponly cookie containing the jwt in the api controller action response :
Response.Cookies.Append("jwt", jwt, new CookieOptions { HttpOnly = true, Secure = true });
The code is the same on both environments, they just yield different results. In both cases the api sends me the right cookie in authentication response-headers, but in production environment my react app just won't keep it and send it back in other api calls ....
here is the cookie received from the API and that is never sent back from the web app:
Access-Control-Allow-Credentials :true
Access-Control-Allow-Origin :https://xxxxxxxxxx.com
Connection :keep-alive
Content-Type :application/json; charset=utf-8
Date :Mon, 09 Sep 2019 22:32:54 GMT
Server :Kestrel
Set-Cookie :jwt=xxxxxxxx; path=/; secure; samesite=lax; httponly
Transfer-Encoding :chunked
Vary :Origin
Via :1.1 vegur
If anyone has any clue i'll be forever grateful.
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
- In particular, where it rewrites all cookies to beHttpOnly
? – JeanajeanbaptisteSecure
flag makes it have to be over https. TheHttpOnly
makes it to where only the server can access the cookie. So e.g. if your server is initially writing the cookie with this flag, and you attempt to read/write to it client-side, it won't let you. – JeanajeanbaptisteHttpOnly
column to see if it's checked. (p.s. HttpOnly) – JeanajeanbaptisteSet-Cookie :jwt=xxxxxxxx secure; samesite=lax; httponly
so I do see thehttponly
flag on your cookie. So your client-side (js) code cannot read/write to that cookie. – Jeanajeanbaptistehttponly
is to only allow the server to read/write to the cookie. This makes your cookie more secure, yes. But the point is that your client-side code cannot read/write to a cookie with this flag, which is what you are trying to do. Are you sure your dev environment includes this flag? Because there's no way your client-side code could be reading/writing to a cookie with this flag. – Jeanajeanbaptistehttponly
is a flag you set while setting a cookie, same as any other cookie setting (e.g. secure, domain, path, expire, etc.). The issue isn't with the flag, itself. It sounds like you have an issue with your server code and/or server config in (not) setting it. Your code may even be the same and behaving the same on dev vs. prod and your prod server may separately have a server directive that rewrites all cookies to include it. But this is just one speculation. I don't have full view into all your stuff. But it sounds like you at least have something to investigate now. – Jeanajeanbaptistehttponly
flag (not) being set. And that sounds like an issue with your code/server config on dev vs. prod. But in general, again, if you are making use of this flag on your cookie, you can't use client-side code to read/write to the cookie, which sounds like is a problem for you. So your options are to a) refactor your code to not have to read/write the cookie client-side, or b) Do not make use ofhttponly
flag on the cookie. – Jeanajeanbaptiste