React & Node.js fetch basic authorization - node.js

I am using fetch api to make request from reactjs to node.js backend with Basic Authorization with the code below...
React
fetch(baseUrl, {
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: 'Basic ' + secret,
},
}).then((res) => {
if (res.ok) {
return res.json();
} else {
return Promise.reject(res.statusText);
}
})
.then((resBody) => {
//
})
.catch((error) => {
console.error(error);
});
Node.js
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Credentials', true);
return next();
});
app.use((req, res, next) => {
const base64Credentials = (req.headers.authorization || '').split(' ')[1] || '';
const [username, password] = Buffer.from(base64Credentials, 'base64').toString().split(':');
const auth = { username: 'username', password: '123456' }
console.log(username, password, auth.username, auth.password);
// comment below
if (username === auth.username && password === auth.password) {
return next();
} else {
res.status(401).send('Authentication required.'); // custom message
}
});
The following error is occur when I try to make the request.
Access to fetch at 'http://127.0.0.1:5000/' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: It does not have
HTTP ok status.
However, when I comment the comparison part in the second middleware if (username === auth.username && password === auth.password) it works fine. I have tried using Postman to send request it also no problem happen. The problem only occur when I make the request from react app. Anyone know what is the reason? Thanks a lot

it seems that the CORS npm is no installed npm i cors and write this code:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
more information about CORS npm

Related

Node.js Api throwing CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status

i am getting below error while consuming node.js function from my vue.js application.
Access to XMLHttpRequest at 'http://0.0.0.0:1081/sendsecondarysalesreport' from origin 'http://0.0.0.0:1050' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Here is my Node.js code.
const cors = require('cors');
const router = express.Router()
router.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PATCH, PUT, DELETE, OPTIONS"
);
next();
});
var corsOptions = {
"origin": "http://0.0.0.0:1050",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 200
}
router.use(cors(corsOptions));
router.options('/*', (_, res) => {
res.sendStatus(200);
});
router.options('/sendsecondarysalesreport', cors(corsOptions));
router.post('/sendsecondarysalesreport', cors(corsOptions), (req, res, next) => {
try {
if (req.body.CustomerCode != "") {
SendSecondarySalesReport(req.body)
res.json([{ "CustomerCode": req.body.CustomerCode }]);
} else {
res.send({ "Status": false, "Error": "Not Found" })
}
} catch (error) {
console.log("error", error);
res.status(500)
res.send(error.message)
}
});
module.exports = router ;
Here is my client side code
this.$http.post(helper.URL() + 'sendsecondarysalesreport', formData, {
headers: {
'Content-Type': 'application/json'
}
}).then((response) => {
if (response.status == "200") {
}
Please help me solve the issue.
I have tried many solutions available here and every time the result is same. Its working fine in my development server but after hosting in iis this issue is coming.

cors request failed on vue/express

I'm running a vue app on an apache server on a virtual server. Express is started with nodemon.
When trying to login I'm getting a
Cannot read property 'status' of undefined xhr.js:160
POST https://143.93.46.35:60702/user/login net::ERR_TIMED_OUT
on chrome and
Cross-source (cross-origin) request blocked: The same source rule prohibits reading the external
resource on https://143.93.46.35:60702/user/login. (Reason: CORS request failed)
on firefox.
In vue my axios baseURL looks like (node is running on port 60702):
const apiClient = axios.create({
baseURL: `https://pvapp.umwelt-campus.de:60702`,
withCredentials: false, // This is the default
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
export default{
loginUser (user) {
return apiClient.post(`/user/login`, user)
},
...
}
And the user route on express is:
router.post('/login', async (req, res) => {
let compareUser = await db.query('SELECT * FROM app_users WHERE username=? LIMIT 1', [req.body.username]); // use db.query() to retrieve the password
if (compareUser.length < 1) // compareUser is an array with at most one item
res.sendStatus(403);
let valid = bcrypt.compareSync(req.body.password, compareUser[0].password);
if (!valid)
res.sendStatus(403);
let user = new User(compareUser[0]);
const token = jwt.sign({ user }, nconf.get('jwtToken'), { expiresIn: '14d' });
Object.assign(user, { token });
res.json(user);
});
In app.js cors is enabled like:
app.use(cors());
You need to res.setHeader('Access-Control-Allow-Origin', YourOrigin); in a middlewar before app.use(cors()); in order to allow the client.
EDIT :
You can do something like this :
router.use(function (req, res, next) {
let origin = req.headers.origin;
if (allowedOriginsTab.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});

CORS issue with Restify

I have created a ReactJs app with a Node Api which uses Restify, but whatever I do I always have the error for POST method :
405 (Method Not Allowed)
Access to fetch at 'http://localhost:3001/api/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have tried everything I saw on Internet but I always have this issue.
To call the API, here is my code :
const request = new Request(url + 'login', {
method: 'POST',
body: JSON.stringify({ 'username' : username, 'password' : password }),
headers: new Headers({ 'Content-Type': 'application/json' })
})
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(({ token }) => {
localStorage.setItem('token', token);
});
And I configure Restify like this :
const config = require('./config'),
restify = require('restify'),
errs = require('restify-errors');
var connection = config.db.get
const server = restify.createServer({
name: config.name,
version: config.version,
url: config.hostname
});
server.use(restify.plugins.acceptParser(server.acceptable));
server.use(restify.plugins.queryParser());
server.use(restify.plugins.bodyParser());
server.use(
function crossOrigin(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, OPTIONS, DELETE');
res.header('Access-Control-Allow-Credentials', false);
return next();
}
);
server.listen(3001, function () {
console.log('%s listening at %s', server.name, server.url);
});
server.post("/api/login", function (req, res) {
res.send(200);
});
So I expect to receive a validation (code 200) after calling the Api, but I always have CORS issue.
Is there anything else to configure ?
Thanks for your help !!! :D
You have to use corsMiddleware to avoid cors issue....write this code in your app.js file ...it should be work fine
var restify = require('restify');
var corsMiddleware = require('restify-cors-middleware');
var cors = corsMiddleware({
preflightMaxAge: 5,
origins: ['*'],
allowHeaders:['X-App-Version'],
exposeHeaders:[]
});
/**
* Initialize Server
*/
var server = restify.createServer();
server.pre(cors.preflight);
server.use(cors.actual);

How to set cookies express, react.js

I am building a login system using express for node.js and react.js. In my back-end when a user logs in, it creates a cookie. When I go to Network > Login I can see this:
Set-Cookie:
user_id=s%3A1.E%2FWVGXrIgyXaM4crLOoxO%2Fur0tdjeN6ldABcYOgpOPk; Path=/; HttpOnly; Secure
But when I go to Application > Cookies > http://localhost:3000, there is nothing there. I believe that is because I am not allowing credentials to go through correctly when I do a post request from the client side. How do I go about this? Please, let me know if I can improve my question in any way.
//Login back-end
router.post('/login', (req, res, next) => {
if(validUser(req.body)) {
User
.getOneByEmail(req.body.email)
.then(user => {
if(user) {
bcrypt
.compare(req.body.password_digest, user.password_digest)
.then((result) => {
if(result) {
const isSecure = process.env.NODE_ENV != 'development';
res.cookie('user_id', user.id, {
httpOnly: true,
secure: isSecure,
signed: true
})
res.json({
message: 'Logged in'
});
} else {
next(new Error('Invalid Login'))
}
});
} else {
next(new Error('Invalid Login'))
}
});
} else {
next(new Error('Invalid Login'))
}
});
//Allow CORS index.js
app.use(
cors({
origin: "http://localhost:3000",
credentials: true
})
);
//Login client side (React.js)
loginUser(e, loginEmail, password) {
e.preventDefault();
let email = loginEmail;
let password_digest = password;
let body = JSON.stringify({ email, password_digest });
fetch("http://localhost:5656/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
credentials: "include",
body
})
.then(response => response.json())
.then(user => {
console.log(user);
});
}
You should be secure of set "credentials" in the server and in app.
Try to set on you index.js or app.js server side this:
app.use(function(req, res, next) {
res.header('Content-Type', 'application/json;charset=UTF-8')
res.header('Access-Control-Allow-Credentials', true)
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
)
next()
})
and in you client site add options like this:
let axiosConfig = {
withCredentials: true,
}
export async function loginUser(data) {
try {
const res = await axios.post(
`${URL}:${PORT}/${API}/signin`,
data,
axiosConfig
)
return res
} catch (error) {
console.log(error)
}
}
Edit
To set "credentials" in server we need this line:
res.header('Access-Control-Allow-Credentials', true)
This would let you handle credentials includes in headers.
You also have to tell to axios to set credentials in headers with:
withCredentials: true
Do not forget to adjust cors middleware.
Your node.js express code
const express = require("express");
const cors = require('cors')
const app = express();
app.use(cors(
{
origin: 'http://localhost:3000',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
));
app.use(function(req, res, next) {
res.header('Content-Type', 'application/json;charset=UTF-8')
res.header('Access-Control-Allow-Credentials', true)
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
)
next()
})
app.get("/auth", function(req, res){
res.cookie('token', 'someauthtoken')
res.json({id: 2});
});
app.listen(3030);
Your front-end code
import React, { useEffect } from 'react';
import axios from 'axios';
async function loginUser() {
try {
const res = await axios.get(
'http://localhost:3030/auth',
{
withCredentials: true,
}
)
return res
} catch (error) {
console.log(error)
}
}
function App() {
useEffect(() => {
loginUser();
}, [])
return (
<div>
</div>
);
}
export default App;
It is because you set httpOnly: true.
This will block the visibility to client side, like reading from javaScript document.cookie().
You can solve this by turn it off.
If you can't see your cookie in the browser, I think it is because you're setting hhtpOnly to true in the cookie's options.
cookie.httpOnly
Specifies the boolean value for the HttpOnly Set-Cookie attribute. When truthy, the HttpOnly attribute is set, otherwise it is not. By default, the HttpOnly attribute is set.
Note: be careful when setting this to true, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie
res.cookie('user_id', user.id, {
httpOnly: false, // try this
secure: isSecure,
signed: true
})
You need to configure cors in your backend server first.
First, install cors using npm i cors then in your express server add this line of code:
app.use(cors({
origin: "YOUR FRONTEND SITE URL HERE",
credentials: true,
}));
Then, in your frontend app where you are sending GET/POST requests to your backend, make sure to add in your request
If you've used fetch:
const res = await fetch('BACKEND SERVER URL', {
credentials: "include",
// other objects
});
If axios is used:
const res = await axios.post('BACKEND SERVER URL',
{ withCredentials: true },
// other objects,
);
This will solve the problem of storing cookies in frontend sent from backend.

Preflight failing while adding Authorization header - React + Nodejs

I am trying to communicate with the nodejs server , "Preflight" getting failed while adding Authorization header , with out header i am able to connect with server. Screen shot for request header from browser development tool is added below
CORS added to the server.js
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Content-Type,Authorization");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
});
React JS - Axios Code
let params = {
"userId": userName,
"password": password,
"random": event.target.name,
"grant_type": "password"
};
var config = {
headers: {
'Authorization': 'Basic YXBwbGljYXRpb246c2VjcmV0',
'Content-Type': 'application/x-www-form-urlencoded'
}
}
[Axios.post('/oauth/token', params, config).then((response) => {
if (response.status === 200) {
if (response.data.querySuccess) {
console.log(response);
}
).catch((error) => {
console.log(error);
alert.error('Oops some error occured please check the data you have submitted');
});
}][1]

Resources