Skip to content

Instantly share code, notes, and snippets.

@TyrfingMjolnir
Forked from yoitsro/gist:8693021
Last active April 21, 2018 14:26
Show Gist options
  • Select an option

  • Save TyrfingMjolnir/5db92a46d6bac41d545a0251e1c079bb to your computer and use it in GitHub Desktop.

Select an option

Save TyrfingMjolnir/5db92a46d6bac41d545a0251e1c079bb to your computer and use it in GitHub Desktop.
Node + Restify + Passport + Sessions + WebSockets
#!/usr/bin/env node
const restify = require( 'restify' );
// Authentication
const passport = require( 'passport' );
const LocalStrategy = require( 'passport-local' ).Strategy;
const sessions = require( 'client-sessions' );
const server = restify.createServer();
server.use( restify.queryParser() );
server.use( restify.bodyParser() );
server.use( sessions({
// cookie name dictates the key name added to the request object
cookieName: `session`,
// should be a large unguessable string
secret: `yoursecret`,
// how long the session will stay valid in ms
duration: 365 * 24 * 60 * 60 * 1000
}));
// Initialize passport
server.use( passport.initialize() );
// Set up the passport session
server.use( passport.session() );
// This is how a user gets serialized
passport.serializeUser( ( user, done ) => {
done( null, user.id );
});
// This is how a user gets deserialized
passport.deserializeUser( ( id, done ) => {
// Look the user up in the database and return the user object
// For this demo, return a static user
return done( null, {
id: 123456,
username:`john`
});
});
// Lookup a user in our database
const lookupUser = ( username, password, done ) => {
if( username === `john` && password === `johnspassword` ) {
return done( null, {
id: 123456,
username: `john` } );
}
return done( null, false, {
error: `Incorrect username or password.` });
};
passport.use( new LocalStrategy( {
usernameField: `username`,
session: true
}, lookupUser ) );
// POST /login
const loginRoute = ( req, res, next ) => {
// The local login strategy
passport.authenticate( 'local', ( err, user ) => {
if( err ) {
return next( err );
}
// Technically, the user should exist at this point, but if not, check
if( ! user ) {
return next( new restify.InvalidCredentialsError( `Please check your details and try again.` ) );
}
// Log the user in!
req.logIn( user, ( err ) => {
if( err ) {
return next( err );
}
console.log( req.isAuthenticated() );
req.session.user_id = req.user.id;
if( user.username ) {
res.json( { success: `Welcome ${user.username}!`});
return next();
}
res.json({ success: `Welcome!`});
return next();
});
})( req, res, next );
};
// GET /hello
const helloRoute = ( req, res, next ) => {
console.log( req.isAuthenticated() );
if( req.user ) {
res.send( `Hello ${req.user.username}` );
} else {
res.send( `Hello unauthenticated user` );
}
return next();
};
server.post( { url: `/login` }, loginRoute );
server.get( { url: `/hello` }, helloRoute );
const io = require('socket.io').listen(server);
/// Parse the given cookie header string into an object
/// The object has the constious cookies as keys(names) => values
/// @param {String} str
/// @return {Object}
const parseCookie = ( str, opt ) => {
opt = opt || {};
const obj = {}
const pairs = str.split(/[;,] */);
const dec = opt.decode || decodeURIComponent;
pairs.forEach( ( pair ) => {
const eq_idx = pair.indexOf(`=`)
// skip things that don't look like key=value
if( eq_idx < 0 ) {
return;
}
const key = pair.substr( 0, eq_idx ).trim()
const val = pair.substr( ++eq_idx, pair.length ).trim();
// quoted values
if( '"' == val[0] ) {
val = val.slice( 1, -1 );
}
// only assign once
if( undefined == obj[key] ) {
try {
obj[key] = dec( val );
} catch( e ) {
obj[key] = val;
}
}
});
return obj;
};
io.set( 'authorization', ( handshakeData, accept ) => {
// Check that the cookie header is present
if( ! handshakeData.headers.cookie ) {
return accept( 'No cookie transmitted.', false );
}
// Get all the cookie objects
const cookie = parseCookie( handshakeData.headers.cookie );
// Pull out the user from the cookie by using the decode function
handshakeData.sessionID = sessions.util.decode({
cookieName: 'session',
secret:'yoursecret'
},
cookie['session']);
accept( null, true );
});
io.on( 'connection', ( socket ) => {
// Get the first key of the handshake data
const firstKey = Object.keys(socket.manager.handshaken)[0];
const userId = socket.manager.handshaken[firstKey].sessionID.content.user_id;
// Send a hello message with the user's id
socket.emit( `message`, `Hey ${userId}` );
});
// Launch the server
server.listen( 5000, () => {
console.log( `Server running at port 5000` );
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment