I'm using a NestJS backend with a NextJS frontend, both hosted seperately.
NestJS Backend
I enabled CORS in the backend as follows:
app.enableCors({ credentials: true, origin: process.env.FRONTEND_URL });
When using cors-test.codehappy.dev to check the CORS headers everything looks good. All headers are present and the access-control-allow-origin header points to the right domain where the front-end is hosted on.
NextJS Frontend
On the NextJS frontend I'm using Axios to make request to the backend (the exact same url as used above).However, when creating a request the preflight request in Chrome is missing all CORS headers. The Axios instance below is imported when a HTTP request is needed.
import Axios from 'axios';
const api = Axios.create({
baseURL: process.env.BACKENDURL,
withCredentials: true
});
export default api;
The error in the console:
The preflight request:
in next.config.js
module.exports = {
//avoiding CORS error, more here: https://vercel.com/support/articles/how-to-enable-cors
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
{ key: "Access-Control-Allow-Methods", value: "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
]
}
]
},
}
Related
Have a front end nextJs running on a different port to the backend nestjs.
Within the nextJs session-cookie I have 2 JWT tokens access and refresh.
I can extract the access token from the next-auth session-token but axios will not send to nestjs.
If I use the { withCredentials: true } the whole next-auth token is sent but if I use the headers object nothing is received
const data = await axios.post(
process.env.NEXT_PUBLIC_SH_API_BASEURL + '/blog',
{ formData },
//{ withCredentials: true }
{
headers: {
Cookie:
'Authentication=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEzNTQ1N2FiLWI4MGUtNDU2OC1hY2RiLWNiODZmYTJlNGQxMyIsImlhdCI6MTY1MzU0NjM0NiwiZXhwIjoxNjU0NDQ2MzQ2fQ.fvnRXYwheuIOHvlTZRGqBiVR98JxdT7UqZbc6SAvcAk; Path=/; HttpOnly;'
},
}
);
nestJS - log when using with credentials
{
'next-auth.csrf-token': '493deccd24c0165f8afe08db04352415c46c7a6f150f9c51320aea0d5444589d|51953c1c056c986b799afb9dcea8c94469d35b4aab291b02ee343057fa80a70e',
'next-auth.callback-url': 'http://localhost:3000/auth/signin?callbackUrl=http://localhost:3000/',
'next-auth.session-token': 'eyJhbGc
}
But if use the headers I get
[Object: null prototype] {}
The nestJs logging is done using:
jwtFromRequest: ExtractJwt.fromExtractors([
(request: Request) => {
console.log('JWT strategy auth cookie');
console.log(request?.cookies);
return request?.cookies?.Authentication;
},
]),
If I make a call from postman there is no issue with processing the header cookie.
Could you let me know how to get axios to send the header cookie only?
Thanks
After days of searching and trying, I'm here now.
I deployed the React Application in Netlify and the Node.js backend in Heroku. Everything works fine in localhost environment. But after deploying, cookies are not sent in request header.
CORS:(Backend Node.js)
app.use(cors({
origin: CORS_ORIGIN,
credentials: true,
allowedHeaders: "Content-Type,Accept,User-Agent,Accept-Language,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,cache-control"
}));
Axios:
import axios from "axios";
axios.defaults.withCredentials = true;
export default axios.create({
baseURL: process.env.REACT_APP_BACKEND + "/api",
headers: {
"Content-type": "application/json",
"Access-Control-Allow-Origin": process.env.REACT_APP_BACKEND,
},
});
Fetching Data(Mutation): apiClient is imported from above Axios.js and cookies is handled by react-cookies
apiClient.post("/auth/login",{ email: "name#mail.com", password: "pawspaws" })
.then((res) => {
setCookie("jwt", res.data.accessToken, { path: process.env.REACT_APP_PATH || "/", domain: process.env.REACT_APP_DOMAIN, maxAge: 26000, secure: true, sameSite: 'None' });
setCookie("refresh", res.data.refreshToken, { path: process.env.REACT_APP_PATH || "/", domain: process.env.REACT_APP_DOMAIN, maxAge: 2600000, secure: true, sameSite: 'None' });
setCookie("user", res.data.user, { path: process.env.REACT_APP_PATH || "/", domain: process.env.REACT_APP_DOMAIN, maxAge: 26000, secure: true, sameSite: 'None' });
}).catch((err) => console.log(err.response))
Above code sets the cookies.. and it's working.
Now, below is the request I'm sending which doesn't send the Cookies along with the request:
apiClient.get("/posts/timeline", { params: { email: "name#mail.com" } })
.then((res) => { console.log(res.data); })
.catch((err) => { console.log(err.response) });
Well, it returns unauthorized since the Cookie is not sent at all..
Ok, i found my own solution.. It was pretty easy.. It was setting up proxy
Just added line below to package.json in frontend:
"proxy":"https://random.name.herokuapp.com",
FYI, for Netlify, we need additional _redirects file in public folder.
_redirects
/api/* https://random.name.herokuapp.com/api/:splat 200
/* /index.html 200
In my case I had hardcoded my front end api calls to the herokubackend
axios.get("https://infinite-ocean-8435679.herokuapp.com/api/user")
First removed the hrokupart from the request like this
axios.get("/api/loguserin")
Then added the proxy value to the bottom of the package.json
"proxy":"https://infinite-ocean-8435679.herokuapp.com",
Next added a file called _redirects inside the react public folder.(_redirects is the file name and it has no extension such as .txt so don't add _redirects.txt )
Add the following inside _redirects file
/api/* https://infinite-ocean-8435679.herokuapp.com/api/:splat 200
/* /index.html 200
inside _redirects file formatting will be weird just add above code replacing heroku part with your backend url.
React automatically add all the files inside the public folder to its build folder once created.
deploy the site to Netlify
Here is the Error message i am receiving:
Access to XMLHttpRequest at 'http://192.168.0.4:50001/b1s/v1/Orders(334738)' from origin 'http://192.168.0.4:8000' has been blocked by CORS policy: Request header field b1s-replacecollectionsonpatch is not allowed by Access-Control-Allow-Headers in preflight response.
$.ajax({
url: GlobalLink + "Orders("+DocEntry+")",
xhrFields: { withCredentials: true },
headers: { 'B1S-ReplaceCollectionsOnPatch' :true } ,
data: jdata,
type: "PATCH",
dataType : "json",
You have to configure Service Layer to allow this header in CORS requests. It can be done through the web interface "ServiceLayerController":
Just add your header "b1s-replacecollectionsonpatch" here separated by a comma.
I'm trying to make api calls locally in a react app using axios.
I've already added django-cors-headers and followed the documentation, but it does not seem to be working.
I always get the error:
localhost/:1 Access to XMLHttpRequest at 'http://127.0.0.1:8000/api/todos/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
my base.py:
INSTALLED_APPS = [
# ...
"corsheaders",
"rest_framework",
"todo",
"api",
]
MIDDLEWARE = [
# ...
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
# ...
]
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = False
In my react app:
const [todos, setTodos] = useState({})
useEffect(
() => {
axios.get(
api_url, {
headers: {
"Access-Control-Allow-Origin": "*",
}
}
).then(
res => {
setTodos(res.data);
console.log(res.data)
}
).catch(
err => {
console.log(err)
}
)
}, []
)
Note, even without configuring a whitelist and reverting the CORS settings to:
CORS_ORIGIN_ALLOW_ALL = False
CORS_ALLOW_CREDENTIALS = True
I still manage to get the data in a get call using httpie, just running http + url.
Note 2: When the axios tries to get the data, I get this on the terminal running the Django app:
[04/Jun/2019 18:15:29] "OPTIONS /api/todos/ HTTP/1.1" 200 0
IMPORTANT EDIT:
The problem does not seem to be with my server, I used fetch instead of Axios and everything occurred normally. With Axios, my server was getting an OPTIONS method, and, I do not know why, I was giving this problem with CORS.
This https://aws-amplify.github.io/docs/js/api#signing-request-with-iam says AWS Amplify provides the ability to sign requests automatically ..is this the same with API gateway REST requests that are restricted by Cognito?
auth.currentSession().then(token => {
console.log('>>>>', token.getIdToken().getJwtToken());
authToken = token.getIdToken().getJwtToken();
const myInit = { // OPTIONAL
headers: {
Authorization: authToken
},
response: true,
};
api.get(apiName, path, myInit).then(response => {
// Add your code here
console.log(response);
}).catch(error => {
console.log(error.response);
});
}
);
but I get Authorization header requires 'Credential' parameter. Authorization header requires 'Signature'
But in angular this does not work as Auth.currentSession() does not compile
endpoints: [
{
name: 'test',
endpoint: 'https://xyz.execute-api.us-west-2.amazonaws.com/test',
custom_header: async () => {
// Alternatively, with Cognito User Pools use this:
return {Authorization: (await Auth.currentSession()).idToken.jwtToken};
}
}
]
}
Resolved had typo with the request url it had to be /items/:test where test was the partition name in dynamo, also the
headers: {
Authorization: token
},
is not required:
https://github.com/aws-amplify/amplify-js/issues/2810#issuecomment-470213459