Cookies not saved when using npm request library - javascript

I have a local environment and I'm trying to login to a service. I'm using the 'request' library in the client and Express and express-session in the service.
I'm using Chrome and when I login to the service I get the following response headers:
FROM: http://app.dev:3000
TO: http://app.dev:4000/login/local
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://app.dev:3000
Vary: Origin, X-HTTP-Method-Override
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
Content-Length: 304
ETag: W/"130-fdQBs605dSVTeEqXEuXrvdcQTLk"
set-cookie: auth=TOKEN; Path=/; Expires=Sun, 25 Jun 2017 01:48:41 GMT
Date: Sat, 24 Jun 2017 13:48:41 GMT
Connection: keep-alive
When I login with Postman the cookie gets stored correctly. Subsequent requests through Postman include the cookie and everything is working fine.
But doing the same request with the npm request library it won't save the cookie and subsequent requests to the backend do not include cookies. Example request to the service after logging in. No cookie sent.

The request library documentation doesn't mention the withCredentials option but setting it to true fixes the issue. The cookie now gets saved and is being sent on subsequent requests.
const requestBase = request.defaults({
baseUrl: 'http://app.dev:4000/',
withCredentials: true,
});

Related

"SharedArrayBuffer is not defined" error in cloud server but working in localhost

I have enable SharedArrayBuffer and was working in my localhost but once i pushed it to testing environment it is not working.
I added these cors headers to enable SharedArrayBuffer
Cross-Origin-Opener-Policy: 'same-origin'
Cross-Origin-Embedder-Policy: 'require-corp'
Our testing env does not use Nginx or any other loadbalancer, I am also adding curl -I results of both my localhost and server. Both are same BTW.
localhost:
X-Powered-By: Express
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Content-Type: text/html; charset=utf-8
Content-Length: 6293
ETag: W/"1895-PaoXXUQuEWUDQDGVTFEVesWjsgU"
Vary: Accept-Encoding
Date: Wed, 30 Nov 2022 07:00:32 GMT
Connection: keep-alive
Keep-Alive: timeout=5
cloud server:
X-Powered-By: Express
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Content-Type: text/html; charset=utf-8
Content-Length: 6293
ETag: W/"1895-NZTN58jpvKWWO2z5SgAnAyNn4Tk"
Vary: Accept-Encoding
Date: Wed, 30 Nov 2022 06:59:55 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Is there anything i need to add in cloud provider(Azure) or anywhere.
PS: I am trying to use ffmpeg.wasm and tested using Firefox, chrome and edge.
Tried adding Cross-Origin-Resource-Policy: cross-origin but it is not related to that.
The issue is Https. SharedArrayBuffer will not work on http after adding https it worked. Not removing this question it might help someone in future.

How to render 404 page when a user is unauthenticated in nextjs

I am using next-auth to authenticate users. When I navigate to api routes that don't exist on my NextJS server, I get a 404 response and an error page. I would like to emulate this behaviour when an unauthenticated user navigates to one of my api routes. My current test route looks something like this:
// api/test.js
import { getSession } from 'next-auth/client'
export default async (req, res) => {
const session = await getSession({ req });
if (session) {
// Signed in
res.json(JSON.stringify(session, null, 2));
} else {
// Not Signed in
res.status(404);
}
res.end();
}
Unfortunately, this results in a blank page. Ideally, I would like if an unauthenticated user could not tell the difference between a page that doesn't exist and a blocked api route. I also noticed that when I curl a non-existing route, e.g. curl -i http://localhost:3000/api, I get the following response (as well as all of the html for the error page):
HTTP/1.1 404 Not Found
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
Content-Type: text/html; charset=utf-8
Content-Length: 2427
Vary: Accept-Encoding
Date: Thu, 20 May 2021 10:45:45 GMT
Connection: keep-alive
Keep-Alive: timeout=5
When I run curl -i http://localhost:3000/api/test to hit the above code I get the following response:
HTTP/1.1 404 Not Found
Date: Thu, 20 May 2021 10:44:57 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked
How do I modify the response when the user is not authenticated to look (and return the same headers) as the default NextJS 404 error response?

Error when GET HTTPS from REST API in Angular

I have an Angular app running which uses an external api to get countries ISOs.
This API uses https and it's giving me an error.
The thing is: when I use a proxy in my angular local environment, mapping /iso-api/ to the real url it works ok.
"/iso-api/*": {
"target": "https://www...",
"pathRewrite": { "^/iso-api": "" },
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
}
But I want this to work in production, so I want to use the real url.
In my server I am returning the Access-Control-Allow-Origin: * header already.
I've tried to run the angular server with ssl (as the external api uses https), but I receive the same error.
I know a solution would be to implement the proxy in the server, but I believe this should not be done and there may be a way to retrieve this data from the frontend.
Help please.
Response
This is the network error in Chrome:
In Firefox, the request ends with 200 OK and returns data, but CORS error is thrown and I cannot access the data from the app: CORS header 'Access-Control-Allow-Origin' missing
General
Request URL: https://www...
Referrer Policy: no-referrer-when-downgrade
Request headers
:method: GET
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: es-ES,es;q=0.9,en;q=0.8
origin: http://localhost:4200
referer: http://localhost:4200/app/login
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
Response headers
accept-ranges: bytes
cache-control: max-age=0
content-encoding: gzip
content-language: en-US
content-length: 68356
content-type: application/json
date: Mon, 27 Apr 2020 14:49:30 GMT
expires: Mon, 27 Apr 2020 14:49:30 GMT
referrer-policy: strict-origin-when-cross-origin
server-timing: cdn-cache; desc=HIT
server-timing: edge; dur=1
server-timing: ACTT;dur=0,ACRTT;dur=88
set-cookie: ... expires=Mon, 27 Apr 2020 16:49:30 GMT; max-age=7200; path=/; domain=...; HttpOnly
set-cookie: ... Domain=...; Path=/; Expires=Mon, 27 Apr 2020 18:49:30 GMT; Max-Age=14400; HttpOnly
set-cookie: ... Domain=...; Path=/; Expires=Tue, 27 Apr 2021 14:49:30 GMT; Max-Age=31536000; Secure
status: 200
vary: Accept-Encoding
UPDATE
Angular service code
import { HttpClient } from '#angular/common/http';
...
constructor(
private _http: HttpClient,
private _errorUtil: ErrorUtilService,
private _converter: StoreConverter
) {}
...
getCountries(): Observable<CountryWithLanguages[]> {
return this._http.get<GetStoresResponse>(API.storeUrl).pipe(
catchError(this._errorUtil.handle),
map(result => result.stores),
switchMap(stores => stores),
filter(this._isActiveStore),
map(store => this._converter.toView(store)),
toArray()
);
}
To serve the app I use angular dev server, I do not add the 'Access-Control-Allow-Origin' header manually but, in the browser, I see that it is being added.
angular.json
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "push-web-app:build",
"proxyConfig": "src/proxy-local.conf.json"
},
}
You can't request a resource from another domain. This would be a security hole. You can read more here: Same-origin policy
Sending Access-Control-Allow-Origin: * from your server won't give you access to the aforementioned API. The provider of this API needs to give you permission to access the API, you can't give yourself this permission.
The error you posted states that the Access-Control-Allow-Origin header is missing. It means that the API isn't sending this header.
There might be two reasons why this API isn't sending Access-Control-Allow-Origin header.
A misconfiguration on the side of this API. In this case you have to ask the provider of this API to fix this issue.
The API provider is restricting access to the API on purpose. In this case you have to ask the provider of this API to give you access from your domain.
You can also proxy the request through your server. The core difference when using proxy is that your server reads the resource from the API and not the client browser. See David's response on how to configure proxy with nginx.
You cannot bypass CORS browser side. If you are not able to modify the server side, your only solution is to use a proxy.
For development purposes, you can use angular's built-in proxy server, but not for production.
Here is a basic nginx config to do this
server {
listen 80;
server_name yourdomain.com; #domain where your angular code is deployed
location /iso-api{
RewriteRule ^/iso-api/(.*)$ /$1 break;
proxy_pass https://thirdpartyapidomain.com; #url of the API you are trying to access
}
location
{
#Your normal angular location
#try_files ...
}
}
This will redirects requests like
http://yourdomain.com/iso-api/countriesList to https://thirdpartyapidomain.com/countriesList;
Since now client and server API calls are on the same domain, you should not have CORS issues
Use this site to resolve the CORS error:
https://cors-anywhere.herokuapp.com/
Use Exemple
https://cors-anywhere.herokuapp.com/https://freegeoip.app/json
this._http.get('https://cors-anywhere.herokuapp.com/https://freegeoip.app/json')
It's just a workaround but it works. Use it even just to understand if the error is related to CORS or something else.
Try the .get call with option withCredentials: true:
return this._http.get<GetStoresResponse>(API.storeUrl, { withCredentials: true }).pipe();
...and/or making sure your browsers are up to date.

Serving pre-flight request using ExpressJS

I created a simple route in express using the code below.
const express = require("express");
const app = express();
app.get('/route1', (req, res) => {
res.send({ data: "Route 1" });
});
app.listen(3000);
When I run curl -X GET http://localhost:3000/route1, I am getting {"data":"Route 1"} as response.
However, I tried running curl -X OPTIONS http://localhost:3000/route1 to simulate a CORS pre-flight request. I received GET,HEAD as the response.
I was not able to find any documentation supporting this behaviour. Why did the above route respond to OPTIONS request?
(NOTE: I haven't used any other packages like CORS)
EDIT
Based on Quentin's answer, I tried issuing another OPTIONS request with relevant headers and with display headers flag in curl.
curl -i -X OPTIONS http://localhost:3000/route1 \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: content-type,x-requested-with'
HTTP/1.1 200 OK
X-Powered-By: Express
Allow: GET,HEAD
Content-Type: text/html; charset=utf-8
Content-Length: 8
ETag: W/"8-ZRAf8oNBS3Bjb/SU2GYZCmbtmXg"
Date: Wed, 03 Jul 2019 11:14:07 GMT
Connection: keep-alive
GET,HEAD
OPTIONS is a standard HTTP method with standard behaviour that has built-in support in Express.
The CORS spec layers additional semantics over the top of a regular OPTIONS request.
curl -X OPTIONS http://localhost:3000/route1 makes an OPTIONS request, but it isn't simulating a prefight request (as it is missing a bunch of request headers that are required by the CORS specification). The response you get to that request doesn't include any CORS response headers either.
Re edit:
I tried issuing another OPTIONS request with relevant headers
You missed out the Origin header, but as you can see, since you didn't set up CORS support in the Express app, the response still doesn't include any CORS response headers.

Setting a cookie with a webpack-dev-server client and hapi API

I have a ReactJS client running webpack-dev-server on localhost:3000. It connects to a Hapi API server on localhost:8080 and I'm trying to provide a basic cookie using hapi-auth-jwt2 (I've also tried hapi-auth-cookie with equal results).
I can see the response header provides a valid set-cookie header and everything looks okay, but all my browser tests ignore it and the cookie is never set (verified by checking document.cookie and using the browser tools like Chrome's Application tab). When I connect directly to the API server with Postman, it picks up the set-cookie header correctly and stores it so I think it's just some kind of domain/port/host configuration issue.
As a simple test, I tried deploying to our ec2 environment but that didn't help. The ec2 environment is similar, with one instance serving the client and another instance serving the API. I've also tried modifying my local hosts file to redirect a domain like 127.0.0.1 example.com and providing the domain=.example.com field in the cookie, but that also didn't help.
I think I'm just missing something basic but I don't know what it is. See below for response/request headers on login.
Request Headers
POST /login HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 47
Accept: application/json, text/plain, */*
Origin: http://localhost:3000
Authorization: undefined
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
Content-Type: application/json
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Response Headers
HTTP/1.1 200 OK
authorization: <jwt token>
vary: origin,accept-encoding
access-control-allow-origin: http://localhost:3000
access-control-allow-credentials: true
access-control-expose-headers: WWW-Authenticate,Server-Authorization
content-type: application/json; charset=utf-8
set-cookie: cookie=token; Max-Age=604800; Expires=Wed, 16 May 2018 21:11:23 GMT; SameSite=Lax; Path=/
cache-control: no-cache
content-encoding: gzip
Date: Wed, 09 May 2018 21:11:23 GMT
Connection: keep-alive
Transfer-Encoding: chunked
http-proxy-middleware, which webpack-dev-server uses, has options for cookie domain/path rewrites.
You should see if those satisfy your needs. Otherwise you can also manually parse and reset cookies in the onProxyRes callback. Here is an example.

Categories

Resources