Express/Node js api SameSite=None and Secure for cookies ,warning being shown when trying to access the api - node.js

I have the following api created using express/node but when i try to access it from the browser "Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use." this warning was shown in console and no data was retrieved ,the api is as follows
let express = require("express");
let app = express();
let bodyparser = require("body-parser")
let jwt = require("jsonwebtoken");
const student = require('./student')
app.use(bodyparser.json)
//used to authenticate the user and create the token
app.get("/auth",(req,res)=>{
console.log("sdsdsds")
var token = jwt.sign({email: user.email}, 'hubDemo', {expiresIn: '1h'});
res.send({token})
})
//fetches the student data and returns
app.get("/student",(req,res)=>{
console.log("tst");
return res.status(200).json({
ok: true,
data: student
});
});
app.listen(3000,()=>{console.log("listening")})
what should i change to make it work?

So in your given scenario, no cookies are being signed our utilized with your express api. However, in the case of your tokens, I would highly recommend looking into http-only cookies rather than localStorage. This prevents any clientside adjustment of the token, while localStorage is more prone to attacks. But depending on your origin-url, just indicating the SameSite property when creating the cookie should solve the warning.

Related

Feathers Authentication via POST works but socket doesn't

Here is a repo showing my latest progress, and here is my configuration. As it stands that repo now doesn't even authenticate with REST - although I think something is wrong with socket auth that needs to be looked at.
I configured feathers, was able to create a user REST-fully with Postman, and even get an auth token (I can post to /authenticate to get a token, and then verify that token - yay postman! yay REST api!).
But in the browser the story ain't so happy. I can use find to get data back, but authenticate just gives me errors.
In my googling I found this post and updated my client javascript to be this. I have also tried doing jwt auth with the token from postman, but that gives the same Missing Credentials error. Halp!
Code incoming...
app.js (only the configuration part to show order)
app.configure(configuration(path.join(__dirname, '..')))
.use(cors())
.use(helmet()) // best security practices
.use(compress())
.use(favicon(path.join(app.get('public'), 'favicon.ico')))
.use('/', feathers.static(app.get('public')))
.configure(socketio())
.configure(rest())
.configure(hooks())
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
.configure(services) // pull in all services from services/index.js
.configure(middleware) // middleware from middleware/index.js
.hooks(appHooks)
Within services, I first add authentication, which is in its own file and that looks like this
authentication.js
const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const local = require('feathers-authentication-local');
const authManagement = require('feathers-authentication-management');
module.exports = function () {
const app = this;
const config = app.get('authentication');
// Set up authentication with the secret
app.configure(authentication(config));
app.configure(authManagement(config));
app.configure(jwt());
app.configure(local(config.local));
// The `authentication` service is used to create a JWT.
// The before `create` hook registers strategies that can be used
// to create a new valid JWT (e.g. local or oauth2)
app.service('authentication').hooks({
before: {
create: [
authentication.hooks.authenticate(config.strategies)
],
remove: [
authentication.hooks.authenticate('jwt')
]
}
});
};
index.html (mostly stripped, just showing relevant script)
let url = location.protocol + '//' + location.hostname +
(location.port
? ':' + location.port
: '');
const socket = io(url);
const feathersClient = feathers()
.configure(feathers.socketio(socket))
.configure(feathers.hooks())
.configure(feathers.authentication({ storage: window.localStorage }));
Here's a screen shot showing some requests in chrome debugger and postman.
When default.json is set to use 'username' as the usernameField it outputs my Windows username, 'Matt'. This is because feathers-configuration checks to see if a value is a part of the OS environment.
https://github.com/feathersjs/feathers-configuration/blob/master/src/index.js#L26
Workaround
Manually set this configuration in authentication.js, for example:
// Set up authentication with the secret
const localConfig = {
'entity': 'users',
'service': 'users',
'usernameField': 'username',
'passwordField': 'password'
};
app.configure(authentication(config));
app.configure(local(localConfig));

How to authenticate socket.io connection without underlying useragent to keep the cookies and persist the session

I'm trying to test an app's socket.io which uses passport.socketio to authenticate the socket connection
var socket = require('socket.io-client')('http://localhost:' + app.PORT);
This does not work because there's no accompanying cookie.
Even if I get the cookie from a persisted superagent session
var cookie;
var agent = request.agent(app);
agent.post('/login').send('credentials').end(function(err, res) {
cookie = res.req._headers.cookie;
});
where/how do I use it ?
I found that there are already quite a few requests for socket.io-client to add cookie support
http://github.com/LearnBoost/socket.io-client/issues/450
http://github.com/LearnBoost/socket.io-client/pull/439
http://github.com/LearnBoost/socket.io-client/issues/344
but I don't see them going anywhere.
Is there any other solution to use persistent cookie session with socket while testing?
Cookie data could be passed using querystring
agent.post('/login').send('credentials').end(function(err, res) {
cookie = res.req._headers.cookie.replace(/=/g, '%3D'); //escape '='
});
socket = require('socket.io-client')('http://localhost' + '/?cookie=' + cookie);
It becomes available in the server socket
io.set('authorization', function(handshakeData, callback){
handshakeData._query.cookie;
});
And so it can be used to perform authorization. Since I was using passport.socketio, it plays nicely with a little change to check this query string instead of headers.

How to handle client-sessions in socket.io

I use client-sessions, not the express sessions. How could I get session data. Session stores on the client, not on a server.
I use client-session module https://github.com/mozilla/node-client-sessions
I found the right answer, to get session from cookie, first you should parse the cookie
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
Than you have to decode the cookie, I used the original function from client-session module
var clientSessions = require('./node_modules/client-sessions/lib/client-sessions')
var opts = {
cookieName: 'yourSessionName'
, secret: 'secret'
}
var decoded = clientSessions.util.decode(opts, handshakeData.cookie['yourSessionName'])
decoded object holds your session data
If you want the session data on the client, you could just use the module's built-in features. If you need it on the server, then you could get the information on client-side and then emit it with socket.io, something like socket.emit('sendSocketData', dataToSend);

NodeJS - Framework for stateless sessions?

Is there a framework to support fully client-managed sessions? In other words, instead of storing just the signed pid in the cookie (as Express does), store all context... so that you can manage state across clusters without the requirement to persist.
There is express middleware which supports this:
https://github.com/expressjs/cookie-session
cookieSession()
Provides cookie-based sessions, and populates req.session. This middleware takes the following options:
name - cookie name defaulting to "session"
keys - list of secret keys to prevent tampering
secret - used as single key if keys are not specified
options - additional options such as secure, httpOnly, maxAge, etc.
Middleware:
var cookieSession = require('cookie-session')
...
app.use(cookieSession({
name: "my_session_cookie",
secret: "dont_tell_anybody_the_secret_and_change_it_often",
options: { ... }
));
app.use((req, res, next) => {
// set options on req.session before your response goes out
req.session.viewCount = (req.session.viewCount || 0) + 1;
res.end(`You viewed the page ${req.session.viewCount} times.`);
});
To clear a cookie simply assign the session to null before responding:
req.session = null

Not cookie based session management in node.js

I am looking for a non-cookie based session management in node.js, something like pass a parameter in the URL like &session_id=. It will know that a session has expired when a request comes with an session_id. I've looked at connect library, but it looks that it is cookie based only.
Warning
Passing the session id as a GET parameter is considered bad practice. Why? It is dangerous because people don't usually care about session id and they will probably publish/share links with their session ids inside.
It's also a problem because when a user clicks an external link on your web, and goes to another site, that new site will be able to see the session_id in the referrer link.
So I don't think it is a good idea. Cookies are more secure.
Have a look at: Session Hijacking
For every request you receive, you will get all of the client cookies accordingly.
You can also set client cookies in the response HTTP headers using "Set-Cookie."
Using a GET parameter is unsafe. Any user could accidently share their session ID, but if you want 100% security, I'd share session IDs via cookies, and I would use HTTPS to prevent snoopers from stealing cookies.
You can use localstorage or sessionStorage..
almost same as cookie
not a cookie
better than a cookie!
More info: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
It's very -very- easy to use... in Js for example:
<script>
// check if Storage is avaible
if(typeof(Storage)!=="undefined") {
// Save data to local storage (no exiparion date)
localStorage.setItem("name_always", "bxx");
// Save data to the current session (removes when the tab is closed)
sessionStorage.setItem("name_now", "bxx");
} else {
// No Storage support...
}
// Access to stored data
alert( "For only now, my name is: " + sessionStorage.getItem("name_now"));
alert( "Every day, my name is: " + localStorage.getItem("name_always"));
</script>
Tags: javascript html5 local-storage session-storage
You can use sessions with a store in node.js. For example, you have express application and want to use session like system in your webapp. You can use connect-mongo module for this. This will let you store your session in db. In your app.js
var express = require('express'),
, mongoStore = require('connect-mongo')(express);
var app = express();
app.configure('all', function () {
app.use(express.session({
secret: "terces",
cookie: { maxAge: 24 * 60 * 60 * 1000 },
store: new mongoStore({
url: your_db_url
})
}));
app.use(function(req, res, next) {
res.locals.session = req.session;
next();
});
});
With basic code above, you have session in express that you can use it in your controllers and views directly. In your controller;
app.post('/blog/create/?', function(req, res, next) {
if (!req.session.user) {
next("You need to login in order to create blog!");
}
});
In your view, you can use session.user in order to generate profile menu for example.

Resources