Set cookie in request and response - node.js

I am facing an issue of cookies.
when I hit the /products request from the browser, the node-express server responds with a cookie and for further requests the same cookie is used to maintain the session.
When I hit the same request /products from ionic app, the server is returning the cookie parameter (developer tool) but for further request the ionic app does not set the cookie in request.
How can I set the cookie in ionic app?

The actual issue was due to CORS. I have added following code on server side and everything worked fine for me.
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:8100");
res.setHeader("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
next();
});
Now the server return the cookie and this cookie is stored and further automatically used in upcomming requests.

Store that cookie in localstorage of the ionic application. Read that cookie from localstorage before sending every request, and then attach your http request.

Related

Cookies not being passed from response to next request

I'm trying to build my first Web app and I am using cookies for authentication.
Basically, my React client sends the auth credentials to my REST API which verifies it and generates a token if the credentials are valid.
When I inspect the network activity on chrome, the token is set on the response header of the /login POST request, but when I try to access a protected route after this, I get a 401 and inspecting the request reveals that the cookie was not present on the header.
How do I combat this? I thought this was a CORS issue at first but I just cannot seem to solve it.
Response of the login call:
Cookie missing on the next request:
How I've handled the CORS issue:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:8080");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Set-Cookie");
next();
});
Thanks in advance.
Your next POST request to protected route doesn't contain the cookie, because by default it doesn't send the cookies.
If you're using axios.
set withCredentials: true
axios.get(`api_url`, { withCredentials: true })
By setting { withCredentials: true } you may encounter cross-origin issue. To solve that you need to use
expressApp.use(cors({ credentials: true, origin: "http://localhost:8080" })); //Your REACT ADDRESS
Read more about withCredentials here https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
The issue must be because of Set-cookie attribute SameSite=strict. SameSite attribute works in following way.
SameSite= samesite-value
Strict: The browser sends the cookie only for same-site requests (that is, requests originating from the same site that set the cookie). If the request originated from a different URL than the current one, no cookies with the SameSite=Strict attribute are sent.
Lax: The cookie is withheld on cross-site subrequests, such as calls to load images or frames, but is sent when a user navigates to the URL from an external site, such as by following a link.
None: The browser sends the cookie with both cross-site and same-site requests.
In your case subsequent request is also cross origin so browser doesn't attach cookie in the header. It should work if SameSite=None

post request to Express.js api from another computer

I have a server running on localhost:3000, and I set my app.js to use the angular router when I try to access localhost:3000 in my browser
(example :app.use('/', express.static(path.join(__dirname, '/dist/Client')));)
When I make a post request to my api I do:
const headers = new Headers({
'Content-Type': 'application/json'
});
const options = new RequestOptions({
headers: headers
});
this.http.post('http://localhost:3000/api/someAction',{body},options)
.toPromise()
.then(//function)
Untill now everything is correct, but how can I make my server accessible from another computer. For example if another computer on the same network knows the private IP address of the server I want him to be able to access my app when he navigate to for example 192.168.1.10:3000. Right now I can access but all my http requests fail and I have the following error
Access to XMLHttpRequest at 'http://localhost:3000/api/someFunction'
from origin 'http://192.168.1.10:3000' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: It does not
have HTTP ok status.
In app.js I have the following:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
});
This is a CORS error message you're getting.
You can use the Express CORS middleware to allow calls from other origins to your server. Make sure to choose the right options to allow calls from your other PC.
https://expressjs.com/en/resources/middleware/cors.html
And also make sure to place the CORS middleware at the top of your application definition.
const app = express();
app.use(cors({ origin: "*" })); // Do this first
//... the rest of your routes and handlers and middlewares
From your local machine where things seem to work correctly, open your Chrome Dev Tools, and make sure OPTION calls are being made and fulfilled successfully, and that proper headers are being returned.
Lastly, from a security perspective, remove or restrict the CORS options as much as possible for your production environment. Only use flexible CORS policy during development and testing.

Interacting with expressjs on another server throwing Access-Control-Allow-Headers errors

I am trying to implement Spika web chat ([http://spikaapp.com/][1]) on my Amazon server. I have my website code on one server instance and Spika chat server on another server instance. Spika chat server is up and running. Now when I try to interact with the server on my website I get this error :
XMLHttpRequest cannot load http://example.com:8000/spika/v1/user/list/Boom?_=1468157726669.
Request header field access-token is not allowed by Access-Control-Allow-Headers
in preflight response.
Earlier I had the CORS error I resolved it referring this : http://enable-cors.org/server_expressjs.html
Now I can login but my client but soon after login I get the above error. My current expressjs API handler code for enabling CORS :
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
next();
});
Thanks in advance for the help.
The server (that the POST request is sent to) needs to include the Access-Control-Allow-Headers header (etc) in its response. Putting them in your request from the client has no effect.
This is because it is up to the server to specify that it accepts cross-origin requests (and that it permits the Content-Type request header, and so on) – the client cannot decide for itself that a given server should allow CORS.
When you start playing around with custom request headers you will get a CORS preflight. This is a request that uses the HTTP OPTIONS verb and includes several headers, one of which being Access-Control-Request-Headers listing the headers the client wants to include in the request.
You need to reply to that CORS preflight with the appropriate CORS headers to make this work. One of which is indeed Access-Control-Allow-Headers. That header needs to contain the same values the Access-Control-Request-Headers header contained (or more).
https://fetch.spec.whatwg.org/#http-cors-protocol explains this setup in more detail.
I solved it using https://www.npmjs.com/package/cors. Thanks for all your help guys :)

req.headers.origin is undefined

Fairly new to Node and Express. I have a sails.js app that relies on knowing the origin of a request as I need to authenticate the request is coming from a domain that is registered.
I've seen in the logs that the origin is empty occasionally, why would this be happening? Is it not a good idea to rely on the origin property, is there another option?
Thanks
The origin may be hidden if the user comes from an ssl encrypted website.
Also: Some browser extensions remove origin and referer from the http-request headers, and therefore the origin property will be empty.
You might want to create some sort of authentication token and pass it as a parameter, instead on relying on request headers. Especially since the headers can be faked/manipulated.
Try with this:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", req.header('origin'));
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials","true");
next();
});
If you want to get the url from which your client is requesting then use
req.headers.referer can help you out. for example I want am calling an abcd.com API from xyz.com then at abcd.com the referer will print xyz.com as it is the url from which you are requesting.
Try this
var host = req.headers.host;
OR
var host = req.get('host');

AngularJS cross domain request to separate ExpressJS App hosted on Heroku

I have a stand-alone ExpressJS API that I have built that should be able to service mobile apps and web apps. I'm trying to test the API using a simple AngularJS client app that I have built. The API service runs fine when I host it locally.
I'm getting Cross Domain Request errors when trying to make a GET call to the API hosted on my external server. I'm using Chrome v39
EDIT: my error turns out to be an incorrect URL reference to my heroku API. Please see my answer, below.
XMLHttpRequest cannot load http://myservice.heroku.com/some-api-endpoint?request-parameter=value. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin http://localhost:5001 is therefore not allowed access.
After reading and scanning numerous articles, I've tried the following:
CORS Code on the API
Added to app.js
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Max-Age", "1728000");
res.header("Access-Control-Expose-Headers", "Cache-Control, Pragma, Origin, X-Requested-With, Content-Type, Accept");
if (req.method === 'OPTIONS') {
res.statusCode = 204;
return res.end();
} else {
return next();
}
});
CORS Code on the API (Attempt 2)
Using the CORS node_module instead of the above, yields the same errors
Added to Package.json
"cors" : "~2.5.2"
Added to app.js
var cors = require('cors');
app.use(cors());
Client Code (Attempt 1)
$http({
url: 'http://myservice.heroku.com/some-api-endpoint?request-parameter=value',
method: 'GET',
headers : {
"Origin" : "myclient.heroku.com",
"Access-Control-Expose-Headers": "X-Requested-With",
"Access-Control-Request-Method" : "GET",
"Access-Control-Request-Headers" : "Origin, X-Requested-With, Content-Type, Accept"
}
})
Errors in the chrome dev console:
Refused to set unsafe header "Origin" angular.js:9625
Refused to set unsafe header "Access-Control-Request-Method" angular.js:9625
Refused to set unsafe header "Access-Control-Request-Headers" angular.js:9625
XMLHttpRequest cannot load http://myservice.heroku.com/some-api-endpoint?request-parameter=value, which is disallowed for cross-origin requests that require preflight. (index):1
Client Code (Attempt 2)
thePath = 'http://myservice.heroku.com/some-api-endpoint?request-parameter=value'
+'&callback=JSON_CALLBACK';
$http.jsonp(thePath)
.success(function(data){
console.log(data);
});
Errors received in the Chrome Dev Console:
Uncaught SyntaxError: Unexpected token : endpoint?request-parameter=value&callback=angular.callbacks_0:1
This has been stumping me for two days. Any help is appreciated!
The error turned out to be the reference to applications hosted on Heroku. I was attempting to make my get requests to myapp.heroku.com and not myapp.herokuapp.com. This is a subtle difference that caused there error.
Using cURL or typing in the request into the browser's address bar for myapp.heroku.com will redirect your request to myapp.herokuapp.com and complete the request successfully. However, made from Angular.js $http() function resulted in the Cross Domain error.
The simplest problems seem to cause the most confusion.
You are taking a convoluted route for CORS. Use nodejs CORS middleware to do your stuff....
add,
"cors": "^2.5.1",
to your dependencies in package.json & in app module,
var cors = require('cors');
//add cors to do the cross site requests
app.use(cors());

Resources