At my localhost, I have a client front end running on port 1841 and a back end on port 9000.
The authentication system I am using involves a simple username/password combination that generates a Json Web Token (jwt).
After the client receives the token, I instruct them to save it in a cookie using JavaScript. However, when the XmlhttpRequest call is made from the client (:1841) to the server (:9000), the request does not contain any cookies. As a result, the server responds with a 401 status code (which is expected behavior). I am aware that this lack of cookie information being sent is due to the SAME-ORIGIN-POLICY.
I am utilizing ExtJS 6 as the client and Node.js as the server.
What steps do I need to configure on both the server side and client side to get this working?
On the server side, I have already enabled CORS requests. I have heard about httpOnly, but I am unsure how to handle it.
Login request from localhost:1841 (ExtJS client):
Ext.Ajax.request({
url: 'http://localhost:9000/api/users/authenticate/',
method: 'POST',
params: params,
success: function(response){
var text = response.responseText;
var data = Ext.decode(text, true);
if(data.access_token){
me.saveToken(data.access_token);
me.createInterface();
} else {
if(data.message){
Ext.Msg.alert("Error", data.message);
} else {
Ext.Msg.alert("Error", "Something went wrong.");
}
}
},
CORS configuration:
cors = require('cors');
...
...
...
var whitelist = ['http://127.0.0.1:9000', 'http://localhost:8080', 'http://localhost:9000', 'http://127.0.0.1:8080', 'http://localhost:1841', 'http://127.0.0.1:1841']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
}else{
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, corsOptions) // callback expects two parameters: error and options
}
...
module.exports = function(app) {
....
app.use(cors(corsOptionsDelegate));
}
Another call from the client:
Ext.ajax.request({
url : 'http://localhost:9000/api/users/'
method : 'POST'
success: function(response){
var text = response.responseText;
var data = Ext.decode(text, true);
...
...
}
},
})
Server-side validation:
function isAuthenticated() {
return compose()
// Validate jwt
.use(function (req, res, next) {
....
....
console.log(req.headers.authorization);
validateJwt(req, res, function (err) {
if (err) {
console.log(err.inner.name);
if (err.inner.name === "TokenExpiredError") {
return next({"error":err.inner.name});
}
}
next();
});
})
.use(function (req, res, next) {
....
});
});
Edit 1:
I have implemented Set-Cookie in node, and Set-Cookie appears in the response headers AND in the preview cookies from DevTools. However, the cookies are not being set in the browser.
exports.authenticate = function(req, res, next){
User.findOne({
fullName: req.body.username
}, function(err, user) {
....
if (!user) {
res.status(401).json({
success: false,
message: 'Authentication failed. User not found.'
});
} else {
// Check if password matches
if(user.authenticate(req.body.password)){
var access_token = jwt.sign(user, config.secrets.session, {
expiresIn: 60 // in seconds
});
res.cookie('access_token',access_token);
res.status(200).json({
"success": true,
"access_token" : access_token
});
}else{
....
}
}
});
}