How to set header in nodejs? - node.js

I am working on authentication in nodeJs.I have created successfully login API and it works well on the postman.I stuck on client side.It does not set token on headers.I am using the passport,jwt for authentication.My code is
app.post('/login', (req, res, next) => {
var name = {
name: req.body.name,
password: req.body.password
}
// let m = '';
// console.log(name)
request({
url: "http://localhost:3000/api/login",
method: "POST",
json: true, // <--Very important!!!
body: name
}, function (error, response) {
if (response.body.error == true) {
req.flash('errorMsg', response.body.message);
res.redirect('/');
}
else {
// localStorage.setItem('token', response.body.token);
// console.log(localStorage.getItem('token'))
// req.headers['authorization'] = response.body.token;
// res.setHeader('authorization', response.body.token);
// req.session['token'] = response.body.token;
// console.log(req.session['token'])
// res.set({
// 'Content-Type': 'text/plain',
// 'authorization':response.body.token
// });
// res.setHeader('authorization', response.body.token);
// req.headers['authorization'] = response.body.token;
res.redirect('/secret');
next();
}
});
// console.log(m);
});
and my middleware is:
app.use((req, res, next) => {
var token = req.body.token || req.session['token'] || req.query.token || req.headers['x-access-token'] || localStorage.getItem('token');
req.headers['authorization'] = token;
console.log(req.session['token'], token)
console.log(req.headers['authorization'], config.jwtSecret);
if (token) {
jwt.verify(token, config.jwtSecret, (err, decoded) => {
if (err) {
res.json({
'message': 'Failed to authenticate user'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
// logger.warn('Unauthorized');
return res.sendStatus(401);
}
console.log(req.headers['authorization'])
});
I have tried all possible to set the token in headers but it didn't work well.If I get my token on app.use middleware then I can verify token easily but it didn't allow to set my token.
How can I do this??

have you tried setting headers for request module like
request({ url: "http://localhost:3000/api/login", method: "POST", json: true, // <--Very important!!! body: name ,
headers: {'x-access-token':token}}

Related

Set-Cookie not sended on HTTP response header

i´m creating a Authentication page with React and Express. I'm using JWT too.
I´ve made this route in the back:
server.js
...
app.use(
cookieSession({
name: "prode_session",
secret: "MIOURI_PRODE_SECRET", //add to .env variable
httpOnly: false,
})
);
app.use(cors());
...
auth.routes.js
app.post("/signin", controller.signin);
user.routes.js
app.get(
"/user",
[authJwt.verifyToken],
(req, res) => res.send(true)
)
auth.controller.js
exports.signin = async (req, res) => {
const user = await Users.findOne({
where: { email: req.body.email },
});
try {
if (!user) {
return res.status(404).send({ message: "User Not found." });
}
const passwordIsValid = bcrypt.compareSync(
req.body.password,
user.password
);
if (!passwordIsValid) {
return res.status(401).send({
message: "Invalid Password!",
});
}
const token = jwt.sign({ id: user.id }, config.secret, {
expiresIn: 84000, //24hours
});
req.session.token = token;
console.log(req.session);
return res.status(200).send({
isLogged: true,
id: user.id,
email: user.email,
suscripcion: user.suscripcion,
preference_id: user.preference_id,
token,
});
} catch (error) {
console.log(error);
}
};
authJWT.js
verifyToken = async (req, res, next) => {
let token = req.session.token;
console.log(`THIS IS THE TOKEN: ${token}`);
if (!token) {
return res.status(403).send({
message: "No token provided",
});
}
jwt.verify(token, config.secret, (err, decoded) => {
if (err) {
console.log(err);
return res.status(401).send({
message: "Unauthorized!",
});
}
req.id = decoded.id;
next();
});
};
const authJwt = { verifyToken };
module.exports = authJwt;
When I test this with POSTMAN, it works Ok, I mean, if first I try to make the GET request, the response is "No token provided", but if I signin first, generate the token and then make the GET request, I get true.
The problem is when I try to implement this in the front.
I have this Login component in React in which I make a POST request with the credentials:
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch("http://localhost:3000/signin", {
method: "POST",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: JSON.stringify({
email,
password,
}),
});
const data = await response.json();
console.log(data);
if (data.isLogged && data.suscripcion === true && data.token) {
await tokenAvailable()
//navigate(`/masthead/${email}&${data.isLogged}&${data.id}`);
} else if (data.isLogged && data.suscripcion === false) {
navigate("/suscripcion", {
state: { preference_id: data.preference_id },
});
} else {
window.alert("Invalid Login");
}
} catch (error) {
console.log(error);
}
};
async function tokenAvailable() {
const user = await fetch("http://localhost:3000/user", {
method: "GET",
mode: "cors",
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
});
const response = await user.json();
setUser(await response);
console.log(await response);
return response;
}
When I make the POST, the GET request is executed (tokenAvailable function) after receiving the response, but I receive "No token Provided" while I expect to receive "true" as in Postman.
From what I debug, the authJWT.js file, is not receiving nothing from the req.session.token.
When I compare the headers from postman and the browser, in postan the SET-cookie key appears, but in the browser not.
postman:
browser:
I need some help here. I´ve been strugling with this for almost 3 days.
I found a solution for this. Apparently, the HttpOnly Cookie approach works if the React app and the back-end server hosted in same domain. So we need to use http-proxy-middleware for local development.
I´ve tried to install the http-proxy-middleware but a lot of errors came, so I decided to store de JWT in the localstorage.

How to send cookies with fetch and fix 404 post error?

How to send cookies with fetch and fix 404 post error?
Hello. I'm trying to send a post to a server that uses a jwt token for authorization, but I get a post 404.
Here is the logic for setting the token and the user:
app.use((req, res, next)=>{
const jwtToken = req.cookies.JWT_TOKEN;
if(!jwtToken) {
next();
return;
}
jwt.verify(jwtToken, SECRET, (err, decoded)=>{
if(err) {
next(err);
return;
}
const sessionData = decoded.data;
let userId;
if (sessionData['modx.user.contextTokens']) {
if (sessionData['modx.user.contextTokens']['web'] > 0) {
userId = sessionData['modx.user.contextTokens']['web'];
}else if($dataarr['modx.user.contextTokens']['mgr'] > 0) {
userId = sessionData['modx.user.contextTokens']['mgr'];
} else {
return redirect('/signin');
}
}
req.user = {userId};
next();
});
});
app.use((req, res, next)=>{
if (!req.user || !req.user.userId) {
next(new Error('Access Denied'));
} else {
next();
}
});
Here is the get request that was already here and it works:
app.get("/:id?", function(req, res){
const room = {id:parseInt(req.params.id||0)};
const userid = req.user.userId;
console.log('USEEEEEEEEEEEEEEEEEEEEEEEEEER ID', userid);
pool.query("SELECT * FROM modx_user_attributes WHERE id = ?", [userid], function(err, [userData]) {
if(err) return console.log(err);
//console.log('userData', userData);
const token = jwt.sign({
data: {userId: userid},
}, SECRET);
res.render("index.hbs", {
appdata: {token, room, user: userData},
final scripts,
});
});
});
And here is my point, but I can't reach it:
app.post('/writeVideo', (req, res) => {
req.video.mv('test.wav', (err) => {
if (err) {
res.send(err);
} else {
res.send({
success: 'file write'
})
}
});
})
And here I am trying to knock on the point:
fetch('/writeVideo', {
method: 'POST',
credentials: "same-origin",
headers: {
'Content-type': 'application/json',
},
body: {
user: {
userId: 8
},
video: audioBlob
}
}).then(data => data.json()).then(data => console.log(data));
I read a little, they advise just using credentials: 'same-origin' || 'include', however it didn't work for me, I tried setting Cookie headers: 'JWT_TOKEN=token' in different ways - didn't work. Please tell me how should I proceed.
Thank you.

How to send Refresh Token for new Access Token to Microsoft Graph (Passport-Azure-AD OIDCStrategy)

I'm having trouble understanding how to send back a refresh token to get a new access token.
I've looked at this documentation: https://developer.microsoft.com/en-us/graph/docs/concepts/nodejs and I basically need help with Authenticate User- step4 but they don't seem to go into more details.
I tried using passport-oauth2-refresh but I think because I'm using Azure AD, I kept getting Error: Cannot register: not an OAuth2 strategy. So I've decided to try to manually check the expiry instead.
I am able to retrieve a refresh token (POST /token with req.user.refreshToken) along with my access token and I store it in json but I don't know how to send it back.
Here is my index.js:
const express = require('express');
const router = express.Router();
const graphHelper = require('../utils/graphHelper.js');
const passport = require('passport');
const request = require('request');
const SERVER = process.env.SERVER;
let user_id = null;
router.get('/', (req, res) => {
if (!req.isAuthenticated()) {
res.render('login');
} else {
renderBotPage(req, res);
}
});
router.get('/login',
passport.authenticate('azuread-openidconnect', {failureRedirect: '/'}),
(req, res) => {
res.redirect('/');
});
router.get('/token',
function (req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res, // required
failureRedirect: '/'
}
)
},
function (req, res) {
const options = {
headers: {
'content-type' : 'application/json'
},
method: 'POST',
url: SERVER,
json: {
'accessToken': req.user.accessToken,
'refreshToken': req.user.refreshToken
}
};
request(options,
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body)
}
}
);
console.log('We received a return from AzureAD get token.');
res.redirect('/');
});
router.post('/token',
function (req, res, next) {
passport.authenticate('azuread-openidconnect',
{
response: res, // required
failureRedirect: '/'
}
)(req, res, next);
},
function (req, res) {
console.log('res after first token function', res);
const options = {
headers: {
'content-type' : 'application/json'
},
method: 'POST',
url: SERVER,
json: {
'accessToken': req.user.accessToken,
'refreshToken': req.user.refreshToken
}
};
request(options,
function (error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body)
}
}
);
res.redirect('/');
});
function renderBotPage(req, res) {
graphHelper.getUserData(req.user.accessToken, (err, user) => {
if (!err) {
res.render('chatbotOn', {
display_name: user.body.displayName,
user_id:user.body.id
});
} else {
// Catch of Expired token error
if (hasAccessTokenExpired(err)) {
req.session.destroy(() => {
req.logOut();
res.clearCookie('graphNodeCookie');
res.status(200);
res.redirect('/');
});
}
renderError(err, res);
res.render('chatbotOn', {
display_name: "Random User"
});
}
});
}
router.get('/disconnect', (req, res) => {
req.session.destroy(() => {
req.logOut();
res.clearCookie('graphNodeCookie');
res.status(200);
res.redirect('/');
});
});
function hasAccessTokenExpired(e) {
let expired;
if (!e.innerError) {
expired = false;
} else {
expired = e.forbidden &&
e.message === 'InvalidAuthenticationToken' &&
e.response.error.message === "Le token d'accès a expiré.";
}
return expired;
}
function renderError(e, res) {
e.innerError = (e.response) ? e.response.text : '';
res.render('error', {
error: e
});
}
module.exports = router;
My app.js
const callback = (iss, sub, profile, accessToken, refreshToken, done) => {
done(null, {
profile,
accessToken,
refreshToken
});
};
passport.use(new OIDCStrategy(config.creds, callback));
And here is my graphHelper.js:
const request = require('superagent');
function getUserData(accessToken, callback) {
request
.get('https://graph.microsoft.com/beta/me')
.set('Authorization', 'Bearer ' + accessToken)
.end((err, res) => {
callback(err, res);
});
}
exports.getUserData = getUserData;
here is my config.js:
module.exports = {
creds: {
redirectUrl: 'http://localhost:3000/token',
clientID: 'xxxxx', // regular
clientSecret: 'xxxxx', // regular
identityMetadata:
'xxxxxx',
allowHttpForRedirectUrl: true, // For development only
responseType: 'code id_token',
validateIssuer: false, // For development only
responseMode: 'form_post',
scope: ['openid', 'offline_access', 'Contacts.Read',
'Calendars.ReadWrite'
]
},
};

How to set headers in api call om nodeJs?

I am working on authentication in nodeJs. I have created successfully login API and it works well on the postman. I'm stuck on client side. It does not set token on headers. I am using the passport, jwt for authentication.
My code is:
app.post('/login', (req, res, next) => {
var name = {
name: req.body.name,
password: req.body.password
}
// let m = '';
// console.log(name)
request({
url: "http://localhost:3000/api/login",
method: "POST",
json: true, // <--Very important!!!
body: name
}, function (error, response) {
if (response.body.error == true) {
req.flash('errorMsg', response.body.message);
res.redirect('/');
}
else {
// localStorage.setItem('token', response.body.token);
// console.log(localStorage.getItem('token'))
// req.headers['authorization'] = response.body.token;
// res.setHeader('authorization', response.body.token);
// req.session['token'] = response.body.token;
// console.log(req.session['token'])
// res.set({
// 'Content-Type': 'text/plain',
// 'authorization':response.body.token
// });
// res.setHeader('authorization', response.body.token);
// req.headers['authorization'] = response.body.token;
res.redirect('/secret');
next();
}
});
// console.log(m);
});
and my middleware is:
app.use((req, res, next) => {
var token = req.body.token || req.session['token'] || req.query.token || req.headers['x-access-token'] || localStorage.getItem('token');
req.headers['authorization'] = token;
console.log(req.session['token'], token)
console.log(req.headers['authorization'], config.jwtSecret);
if (token) {
jwt.verify(token, config.jwtSecret, (err, decoded) => {
if (err) {
res.json({
'message': 'Failed to authenticate user'
});
} else {
req.decoded = decoded;
next();
}
});
} else {
// logger.warn('Unauthorized');
return res.sendStatus(401);
}
console.log(req.headers['authorization'])
});
I have tried all possible to set the token in headers but it didn't work well. If I get my token on app.use middleware then I can verify token easily but it didn't allow to set my token.
How can I do this??
Best way!
router.get('/your-route', async (req, res) => {
//...
res.setHeader('your-key', 'your-value');
//..
})
You can see output in header tab in browser or postman
your-key: your-value

ExpressJS: How to mock request handler next function with mocha

I have an handler
public ensureAuthenticated(req: express.Request, res: express.Response, next: Function) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.param('token') || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secret, function(err, decoded) {
if (err) {
return res.status(404).json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
next();
}
});
} else {
// if there is no token
// return an error
return res.status(403).send({
success: false,
message: 'No token provided.'
});
}
}
And here the route
app.post('/api/article/create', AuthenticationHelper.ensureAuthenticated, this.create);
In unit test, how can I mock the ensureAuthenticated to make sure it is authenticated.
sinon.stub(AuthenticationHelper, 'ensureAuthenticated').returns(true);
I will give you an example where I test it without using sinon.
This is my authentication-helper.js:
'use strict';
module.exports = function(jwt, config) {
return {
ensureAuthenticated: function (req, res, next) {
var token = req.body.token ||
req.param('token') ||
req.headers['x-access-token'];
if (token) {
jwt.verify(
token,
config.secret,
function(err, decoded) {
if (err) {
res
.status(404)
.json({
success: false,
message: 'Failed to auth.'
});
} else {
next();
}
}
);
} else {
res
.status(403)
.send({
success: false,
message: 'No token provided.'
});
}
}
};
}
And this is my test file:
'use strict';
var jwt = {};
jwt.verify = function (token, secret, fn) {
fn(null, 'something');
};
var config = {};
config.secret = 'shh';
var req = {};
req.body = {};
req.body.token = 'mytoken';
var res = {};
var AuthenticationHelper = require('./authentication-helper.js')(jwt, config);
describe('Test Express Middleware', function() {
it('should call next on middlware', function(done) {
var next = function () {
console.log('next was called');
done();
};
AuthenticationHelper.ensureAuthenticated(req, res, next);
});
});

Resources