const validateUser = await this.authService.validateUser(email, password);
const jwt = await this.authService.login(validateUser);
const cookie = response.cookie('jwt', jwt.access_token, { httpOnly: true });
Environment :
Nuxt.js host on Netlify
Nest.js host on Heroku
I'm using cookies in local development to make request after being loged.
But when I'm trying to host the front and back into Netlify and Heroku, the cookies do not be set (with the same configuration)
Is there a config needed to make it work ?
Edit :
response.cookie('jwt', jwt.access_token, {
httpOnly: true,
sameSite: 'none',
secure: true,
});
Google chrome need this configuration to make cookies working
Related
Express-Session is working in development environment, as it sets the "connect.sid" cookie in my browser. However, in production it's not storing the cookie, and instead of using the same session - it creates a new one every time. I believe that the issue would be fixed if I can somehow save third party cookies, as my app was deployed using Heroku. Lastly, I have also used express-cors to avoid the CORS issue (don't know if this has anything to do with the cookie issue). I have set {credentials: true} in cors, {withCredentials: true} in Axios, as well.
Heroku uses reverse proxy. It offers https endpoints but then forwards unencrypted traffic to the website.
Try something like
app.enable('trust proxy')
And check out
https://expressjs.com/en/guide/behind-proxies.html
Issue Solved! -> Add sameSite: 'none'
Full Cookie config (express-session) for production:
cookie: {
httpOnly: true,
secure: true,
maxAge: 1000 * 60 * 60 * 48,
sameSite: 'none'
}
Adding a "name" attribute to the session config worked for me:
{
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
proxy: true, // Required for Heroku & Digital Ocean (regarding X-Forwarded-For)
name: 'MyCoolWebAppCookieName', // This needs to be unique per-host.
cookie: {
secure: true, // required for cookies to work on HTTPS
httpOnly: false,
sameSite: 'none'
}
}
i am having a https create-react-app application(https://xyz.site.com), i am proxing a server which is a different domain, when i am loading the application the api is giving the web html data as a response, there is no hit happened in the server,
i have tried using HTTPS=true in .env file, still i am not able to get the server response
setupProxy.js
module.exports = (app) => {
app.use(
'/api',
createProxyMiddleware({
target: process.env.REACT_APP_API_URL, // https://xxx-alb-23333.us-west-2.elb.amazonaws.com
changeOrigin: true,
}),
);
};
I have a series of serverless next.js apps running on AWS that I am serving at subdomains, and I want to proxy them to subdirectories on my main domain. So, for example, the app at foo.example.com/foo/ should appear at www.example.com/foo/.
I've accomplished this by using http-proxy and express. I have a fairly simple express server that runs in its own serverless app, like so:
const serverless = require('serverless-http');
const httpProxy = require('http-proxy');
const express = require('express');
const app = express();
const proxy = httpProxy.createProxyServer();
app.get('/', (req, res) => {
res.send('Hello, you are at index.');
});
app.get('/:project/*', (req, res) => {
const project = req.params.project;
const rest = req.params[0];
const url = `https://${project}.example.com/${project}/`;
req.url = `/${rest}`;
req.headers['X-Projects-Router-Proxy'] = true;
req.body = undefined;
proxy.web(req, res, {
target: url,
xfwd: false,
toProxy: true,
changeOrigin: true,
secure: true,
});
});
module.exports.handler = serverless(app);
This works quite well on its own, which is great. However, when I try to put this behind CloudFront, the index page works fine, but anything that touches the proxy returns a 403 error:
403 ERROR
The request could not be satisfied.
Bad request.
Generated by cloudfront (CloudFront)
What might be going wrong here, and how can I configure http-proxy so that it will cooperate with CloudFront?
You need to add *.example.com into CloudFront CNAME/Alternative name filed and also in DNS to point it to CloudFront, when url changes as {project}.example.com, CloudFront finds the distribution based on the host header and if it can't find, it'll give you 403 error.
I have frontend client running on custom Next.js server that is fetching data with apollo client.
My backend is graphql-yoga with prisma utilizing express-session.
I have problem with picking correct CORS settings for my client and backend so cookie would be properly set in the browser, especially on heroku.
Currently I am sending graphql request from client with apollo-client having option
credentials: "include" but also have tried "same-origin" with no better result.
I can see cookie client in response from my backend in Set-Cookie header, and in devTools/application/cookies. But this cookie is transparent to browser and is lost on refresh.
With this said I also tried to implement some afterware to apollo client as apolloLink that would intercept cookie from response.headers but it is empty.
So far now I'm thinking about pursuing those two paths of resolving the issue.
(I'm only implementing CORS because browser prevents fetching data without it.)
CLIENT
ApolloClient config for client-side:
const httpLink = new HttpLink({
credentials: "include",
uri: BACKEND_ENDPOINT,
});
Client CORS usage and config:
app
.prepare()
.then(() => {
const server = express()
.use(cors(corsOptions))
.options("*", cors(corsOptions))
.set("trust proxy", 1);
...here goes rest of implementation
const corsOptions = {
origin: [process.env.BACKEND_ENDPOINT, process.env.HEROKU_CORS_URL],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie", '*'],
methods: "GET,POST",
optionsSuccessStatus: 200
};
My atempt to get headers from response in apolloClient(but headers are empty and data is not fetched afterwards):
const middlewareLink = new ApolloLink((operation, forward) => {
return forward(operation).map(response => {
const context = operation.getContext();
const {response: {headers}} = context;
if (headers) {
const cookie = response.headers.get("set-cookie");
if (cookie) {
//set cookie here
}
}
return response;
});
});
BACKEND
CORS implementaion (remeber that is gql-yoga so I need first to expose express from it)
server.express
.use(cors(corsOptions))
.options("*", cors())
.set("trust proxy", 1);
...here goes rest of implementation
const corsOptions = {
origin: [process.env.CLIENT_URL_DEV, process.env.CLIENT_URL_PROD, process.env.HEROKU_CORS_URL],
credentials: true,
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie"],
exposedHeaders: ["Content-Type", "Authorization", "X-Requested-With", "X-Forwarded-Proto", "Cookie", "Set-Cookie"],
methods: "GET,HEAD,PUT,PATCH,POST,OPTIONS",
optionsSuccessStatus: 200
};
Session settings, store is connect-redis
server.express
.use(
session({
store: store,
genid: () => uuidv4(v4options),
name: process.env.SESSION_NAME,
secret: process.env.SESSION_SECRET,
resave: true,
rolling: true,
saveUninitialized: false,
sameSite: false,
proxy: STAGE,
unset: "destroy",
cookie: {
httpOnly: true,
path: "/",
secure: STAGE,
maxAge: STAGE ? TTL_PROD : TTL_DEV
}
})
)
I am expecting session cookie to be set on the client after authentication.
Actual result:
Cookie is visible only in Set-Cookie response header but is transparent to browser and not persistent nor set (lost on refresh or page change). Funny enough I can still make authenticated requests for data.
This may not be a CORS issue, it looks like a third-party cookie problem.
Behaviour could be different across browsers so I recommend testing several ones. Firefox (as of version 77) seems to be less restrictive. In Chrome (as of version 83) there is an indicator on the far right of the URL bar when a third party cookie has been blocked. You can confirm whether third party cookies is the cause of the problem by creating an exception for the current website.
Assuming your current setup is as follows:
frontend.com
backend.herokuapp.com
Using a custom domain for your backend that is a subdomain of your frontend would solve your problem:
frontend.com
api.frontend.com
The following setup wouldn't work because herokuapp.com is included in the Mozilla Foundation’s Public Suffix List:
frontend.herokuapp.com
backend.herokuapp.com
More details on Heroku.
I have an MVC site deployed to mysite.mydomain.co that authenticates against ADFS and creates an auth cookie:
public partial class Startup
{
public void ConfigureUserAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(WsFederationAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions()
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
MetadataAddress = ConfigurationManager.AppSettings["adsfs.MetadataAddress"],
Wtrealm = ConfigurationManager.AppSettings["adsfs.Wtrealm"]
});
}
}
There is also a WebAPI site deployed on "myapi.mydomain.com" with CORS enabled:
GlobalConfiguration.Configuration.EnableCors(new EnableCorsAttribute("https://mysite.mydomain.com", "*", "*") { SupportsCredentials = true });
The the user goes to mysite.mydomain.com. The MVC site authenticates against ADFS and I see the auth cookie being set with no problem.
My application is mostly an SPA, so from javascript there's a AJAX calls to myapi.mydomain.com using jQuery, setting the withCredentials option to true:
$.ajaxSetup({
xhrFields: { withCredentials: true }
});
That options is supposed to send security credentials (cookies) to the API. At runtime I don't see the cookies being set to the API and I get a 401 (unauthorized) error as expected.
If I run the same code on localhost (except for changing the origins to localhost of course) I see the cookie flowing to the API with no problem. My best guess is it works because it's the same subdomain (localhost) whereas on my servers is "mysite" vs "myapi".
Any ideas?