I am facing an issue where my backend API is returning a CORS error in Safari but works fine in Chrome and Postman. The specific error in Safari is:
Access to XMLHttpRequest at ‘https://backendServer/users/login?email=email&password=password’
from origin ‘https://url’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
When looking in the network tab, I see there is no Response headers.
I have configured CORS in my backend using the following middleware in
**Express.js**:
const cors = require('cors');
const corsOptions = {
origin: process.env.WebPageUrl, // Allow only requests from this origin
credentials: true, // Allow cookies to be sent with the requests
allowedHeaders: ["Content-Type", "Authorization"], // Ensure headers are allowed
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], // Specify allowed methods
};
const app = express();
app.use(cors(corsOptions)); // Apply CORS middleware
// Additional middleware for handling CORS preflight requests
app.options('*', cors(corsOptions)); // Handles OPTIONS pre-flight requests app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', process.env.WebPageUrl); // Allow only requests from this origin
res.header('Access-Control-Allow-Credentials', 'true'); // Allow cookies
res.header('Access-Control-Expose-Headers', 'Access-Control-Allow-Origin, Content-Type, Authorization'); // Expose specific headers
res.setHeader('Cache-Control', 'no-store'); // Prevent caching
next();
});
When setting the JWT cookie, I am using the following options:
const cookieOptions = {
expires: new Date(Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000),
httpOnly: true,
sameSite: 'None', // For cross-origin requests
secure: true // Cookies must be sent over HTTPS
};
res.cookie('jwt', token, cookieOptions);
On the frontend I’m using axios to do the following
async login(credentials) {
const url = `users/login`;
const {email,password} = credentials;
var response = "";
await http
.get(url, {
params:{
email:email,
password:password
},
cache: false,
withCredentials:true
})
.then(responseData => {
console.log(responseData)
response = responseData.data;
})
.catch(error => {
response = error.response;
throw new Error(`HTTP error! status: ${response.status}`);
});
return response;
}
I have configured CORS in the serverless.yaml
for my API:
functions:
app:
handler: server.handler
events:
- http:
path: /api/v1/users/login
method: GET
cors:
origin:
- "https://url" # Web app
allowCredentials: true
headers:
- Content-Type
- Authorization
Kind of at a lose as to why this is failing