Sharing a cookie between multiple apps on localhost - node.js

My API (localhost:8080) issues cookies for my frontend (localhost:3000). The cookies domains are set to "NULL" on development mode.
I have another small frontend (localhost:9000) on the side. It will be deployed as a subdomain of the frontend in production, so I shouldn't have issue.
In development, I have found no way to request the API from my small frontend, I have no CORS issues but my API throws 401 because the small frontend isn't sending the cookie. The "Send For" attribute is set to "Any type of connection". The cookie is set to expire in a year. I checked in the browser settings, on both ports the cookie is there with the same settings and content.
On the small frontend I can list the cookies on document.cookie but trying to retrieve any value from the cookie using either
function getCookie(key) {
var keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
return keyValue ? keyValue[2] : null;
}
getCookie('sid');
OR
$.cookie('sid');
Doesn't work.
Setting the cookie domain to NULL doesn't work.
Setting the cookie domain to localhost doesn't do the trick either and it isn't supported by chrome. (see this) It is supported on FF but I have the same issues
I have tried to set the cookies domain to ".app.localhost" and then set in /etc/hosts
127.0.0.1:8080 api.app.localhost
127.0.0.1:9000 app.app.localhost
127.0.0.1:3000 front.app.localhost
But I couldn't access my apps.
I think I missing something big here.
EDIT:
About the /etc/hosts file
After some digging I found out that ports cannot be specified on ips
However, you can set it up this way:
127.0.0.1 api.app.localhost:8080
127.0.0.1 app.app.localhost:3000
127.0.0.1 app2.app.localhost:9000
I can access and login on my app.app.localhost:3000 with the cookie set to .app.localhost, when I go to app.app.localhost:9000 I can see that there is a cookie containing my sessionId setup with .app.localhost as domain and Any kind of connection.
Yet, same issue as explained above.

Related

Response header Set-Cookie doesn't store cookies in browser

I'm setting 2 cookies in response from backend to the browser.
One that is secure HTTPOnly (it's refreshToken) and the other one without those parameters so it's accessible to JavaScript (carrying information about refreshToken is set and when it expires).
Cookies in response:
Neither of those two is set in browser. I studied all about cookies and I'll be honest, I'm lost here and need your help.
At first it was working very well on my localhost environment (backend on localhost:8080, frontend on localhost:3000).
Then I made deploy and there it was NOT working.
I tested again on localhost and I checked "Disable cache" to prevent unwanted behaviour and it is not working even there.
I'll mention that I'm using CORS, not sure if that can may interfere:
I tested this both in Chrome and Firefox.
I FINALY figured it out. Cookies are valid. The answer is to set withCredentials = true both in frontend and backend.
First I thought the parameter withCredentials on frontend is used only when we want to send our credentials hidden in secure HttpOnly cookies to which we don't have access to but browser does.
Apparently it is also used when we want to set cookies from response. Link to docs.
responses from a different domain cannot set cookie values for their own domain unless withCredentials is set to true before making the request
Secondly, we also have to add withCredentials on backend to CorsFilter (in Spring boot) otherwise we get CORS error.
CorsConfiguration()
.apply {
allowedOrigins = listOf(uiUrl)
allowedHeaders = listOf("*")
allowedMethods = listOf("*")
allowCredentials = true
}

SameSite Cookie attribute issue

I have a web application with react in front-end and node in backend.
I am using passport authentication with passport-saml strategy. Since the last browser update i am seeing an issue. Once I try to login I was taken to the authentication page and it returned back to app page again, then auth page and this continues. looks like i was in a redirection loop.
Once I disabled the samesite attribute flag in chrome then the issue got resolved.
I read some articles and realized that the samesite attribute is causing this. (please correct me if i am wrong. Also want to know), where we will be adding this in backend.. I was using node express session module and addded a cookie object as :-
cookie: {sameSite: 'none', secure: true}
Can someone please help me to find a solution for this?
Is you application behind proxy server with ssl enabled?
I had a similar problem with similar setup and similar symptoms, but I've already switched from saml to oauth (without using passport), so I'm not sure if this helps you.
Anyway, there were two things I needed to do to keep a session cookie 'alive' over the requests.
Set 'trust proxy' in your server code: app.set('trust proxy', 1)
Set X-Forwarded-Proto header to proxy server config (mine is nginx):
location / {
proxy_set_header X-Forwarded-Proto $scheme;
...
}
I'm not sure this is your case, but I'm assuming your app is deployed (I haven't faced this issue in localhost, so your problem may be somewhere else) and your session is being set.
After 3 days trying to figure It out. I finally found a way around this issue, It's not a fix, I'm quite sure PassportJS will come with a solution for that eventually, but for now It allowed me to get the user from the authentication.
Since we are not being able to get the user from the cookie, but the information is in the server session, the way to get this information is to add to the 'server.js' a route to get the user directly from the server session:
app.get('/api/getUser', (req, res) => {
res.json(req.session.user);
});
For some reason, I suppose the lack of cookie somehow, using the req.session inside of a router is returning undefined, but If used inside 'server.js' (or your server index file) It gets the session.
If you need the req.user._id or some other sensitive information for other requests, I would recommend returning a jwtToken with this information to the frontend (in res.json), then save the token directly in localStorage and pass the token in the body of your requests, is not the ideal, but It's the safer way I could think to keep the ids safe.

Hostname/IP does not match certificate's altnames: Host: localhost. is not in the cert's altnames: DNS:*.herokuapp.com, DNS:herokuapp.com

I have an api created and hosted on Heroku. I have my web app running on localhost. I am using NextJS for my app. I am able to access all my apis hosted on Heroku via my web app which is running on localhost. I have one api which checks whether a cookie is available or not, I am calling the api in the getInitialProps method of the _app.js file of my NextJS app which is the entry point of the framework. If I comment that api call code then I don't get any error , but I need to check whether cookie is present or not so calling that code gives an error saying
Hostname/IP does not match certificate's altnames: Host: localhost. is not in the cert's altnames: DNS:*.herokuapp.com, DNS:herokuapp.com
Also my cookie is not saved in the browser when I login. It works fine on postman so no problem from my api side and I can see the cookie in the postman.
I did set following in my NodeJS app
app.set("trust proxy", true);
I am using the cookie-session library in my express Nodejs app
in my case https://github.com/ushelp/EasyQRCodeJS-NodeJS/issues/30#issuecomment-1221164642 i always manual on create systemd file but i got same issue when tried using pm2.
i have an issue from my ecosystem.config.js where thats handle of env ( process.env.any )
something your value to pointing / save / load online its still on localhost or an ipaddress instead of your custom domain on VPS server these issue when u are using certbot instead of buying ssl.
these random error, in my case you can check on the above link for more detail but in short its just because you are using ipaddress or localhost in your code.
try to change your hardcode everything that point to correct env
but in your case you are using heroku thats mean you need to define
on reveal vars because heroku is not using an env file
here more for you
( put all your env to ) heroku --> setting --> Config Vars --> Reveal Config Vars
Read this article:
https://devcenter.heroku.com/articles/ssl
It's about installing certificates.
For me it looks that just the certificate is signed for localhost. The browser will reject it, because you access the site by another domain name.
So you have to self-sign a certificate and upload it, or buy a trusted certificate.

Cookies not sent on redirect

I am building a react web application with a separate back-end express api that manages all the calls, including passporting and setting cookies. Let's call the back-end service 'api.com' and the front-end service 'react.com'. I'm using passporting with an existing provider (spotify) and after the authorization succeeds, a cookie is set on api.com. The idea is that the user interacts with react.com and requests are made to api.com via a proxy.
If I'm just testing in my browser and I make a call to api.com/resource, the cookie is automatically set. I know this because I've added a bit of logging and also because the requests that require authorization are succeeding via the cookie.
However, when I make calls to api.com from react.com via the proxy, the cookie is not set. Is this expected behavior when proxying? It seems odd that the cookie is set when I call api.com directly, but it is not set when it is redirected. Is there a way around this? My thought would be to communicate the cookie from api.com to react.com, save it there, and send it on all subsequent requests, but that seems overkill. I'm also wondering if maybe I should be setting the cookie on react.com instead of api.com.
I've tried in both Firefox and Chrome, and if it makes a difference, I'm using axios for the requests on react.com.
const request = axios({
method:'get',
url:'/api/resource'
});
This gets proxied as follows (still on react.com), using express-http-proxy:
app.use('/', proxy('api.com', {
filter: (req) => {
return (req.path.indexOf('/api') === 0);
}
}));
But once this hits api.com, any authentication fails, because the cookie is not present.
Any help is appreciated
As far as I have understood your question, I think you're not considering that cookies are set to host name.
So in the first case the hostname is same and its okay, but in the second case the browser's cookies are not set for react.com
So trying to set the cookie on react.com should work.
I would have asked for a clarification using a comment but I don't have enough reputation for that yet.

angular universal https problems

I have an angular universal app set up. I do POST requests on the server-side using localhost to pre-render my app and this works fine.
An example working url would be http://localhost:8000/api/get-info.
I've now put the app into production on an external url (apache server). I'm also using ssl.
Now when I try to do a POST request on the server-side to pre-render my app, I get back a response with status: 0, url: null (I'm assuming this means the connection was refused).
An example non-working url would be https://mywebsite.com/api/get-info.
What really stumps me is that when the app loads on the client, all HTTPS requests start working. So the problem is I cannot get the express server to send POST requests to my external url.
I've tested a post request on the server-side to a different website (twitter), and that seems to work fine as well. So i'm not entirely sure where I've gone wrong.
I already have CORS set to '*' as well.
Try using
http://localhost:8000/api/get-info
in production as well. Since your Angular app is rendered on the same server as your API is running, using localhost should just work fine. It doesn't matter if you are on an external URL.
I do something similar (its a GET but that shouldn't matter) with my translations:
if ( this.isServer ) {
translateLoader.setUrl( 'http://localhost:4000/assets/localization/' );
} else {
translateLoader.setUrl( 'assets/localization/' );
}
It works locally and in production (both server and client).
I just encountered this problem myself for two days. Please take a look at my comment on https://github.com/angular/universal/issues/856#issuecomment-426254727.
Basically what I did was I did a conditional check in Angular to see if the APP is running in browser or in server (rendered by Angular Universal), and change my API endpoint to actual IP in https or localhost in http accordingly. Also in my Nginx setting, I only redirect incoming request from browser to https by checking if the server_name is localhost.
Hope it helps!

Resources