
Security News
Crates.io Implements Trusted Publishing Support
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
users-session-manager
Advanced tools
A simple Node.js library to manage users sessions on a web application or any kind of JS apps
A simple Node.js module to manage users sessions on a web application or any kind of JS apps It uses a Singleton pattern to ensure that only one instance of the module is running at a time. SessionManager is a singleton class that can be used to manage users sessions. For every user that logs in, a new session is created and stored in the database. Every session has a unique ID that is generated by the system. Every session has a setTimeout that expires after a certain time (setSessionTimeout). When a user logs out, the session is deleted from the class. Every action fires an event that can be used to listen to the session manager.
Install with:
npm i users-session-manager
Example of usage:
// Import module with ES6 syntax
import { SessionManager } from 'users-session-manager'
// or
// const SessionManager = require('users-session-manager')
// Create a new instance of the SessionManager class
const SM = new SessionManager()
// Change session Expiration time:
SM.setSessionTimeOut(6)
// Call this to initialize a new user session
SM.loadNewSession("Luca")
SM.loadNewSession("Fabio")
// You can listen to events emitted from this library through eventEmitter object exported
SM.on("activeUserDeleted", (key) => {
console.log(`User ${key} has been deleted`)
})
setInterval(() => {
console.log(SM.getLoggedUsers())
}, 5000)
// Frontend
let session_key = ""
/**
* Function to call try_login API
*
* @param {*} user username text
* @param {*} pwd password text
* @return {*} false if wrong login or the user table ROW of the selected user JSON format
*/
async function TryLogin(user, pwd) {
//console.log(ENDPOINT)
let credentials = {
"username": user,
"password": md5(pwd)
}
const rawResponse = await fetch(ENDPOINT + API_ROUTE, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'api_name': 'try_login'
},
body: JSON.stringify(credentials)
})
const user_data = await rawResponse.json()
if (user_data.length > 0)
session_key = user_data[0].session_key // save session key to the global variable.
//console.log("user_data: ", user_data)
return user_data
}
// And on the next calls, you can use the session_key to call the API
/**
* Function to call get_table_data API
*
* @param {*} siteid number
* @return {*} JSON object
*/
async function GetTableData(page) {
let body = {
page
}
const rawResponse = await fetch(ENDPOINT + API_ROUTE, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'session_key': session_key,
'api_name': 'get_table_data'
},
body: JSON.stringify(body)
})
const sectors = await rawResponse.json()
if (sectors.logout) Logout()
//console.log("sectors: ", sectors)
return sectors
}
// Backend
// API.js route (cutted from the original file)
...
case 'try_login':
response = {
accepted: false,
message: '',
user_data: {}
}
if (typeof(req.body) === 'object') {
try {
const body = req.body
const db_response = await db.tryLogin(body.username, body.password, true) // true to get the session key
if (db_response !== false) {
response.accepted = true
response.message = 'Welcome! 😘'
response.user_data = db_response
response.user_data.session_key = loadNewSession(body.username) // generate a new session key
} else {
response.accepted = false
response.message = 'Wrong username or password... Are you a f**ing HACKER? 💩💩💩'
}
} catch (error) {
response.accepted = false
response.message = 'Error in API call!'
response.user_data = null
} finally {
res.send(JSON.stringify(response))
}
}
break
case 'get_table_data':
response = {
accepted: false,
message: '',
table_data: {}
}
if (typeof(req.body) === 'object') {
try {
const body = req.body
if (await db.validateApiRequest(req.headers.session_key, "get_data")) {
const dbResponse = await db.getTableData(body.table)
if (dbResponse !== false) {
response.accepted = true
response.message = 'OK'
response.table_data = dbResponse
} else {
response.accepted = false
response.message = 'Error in API call!'
response.table_data = null
}
} else {
response.accepted = false
response.message = 'Action not allowed!'
console.warn('Action not allowed! api_name:', api_name)
}
} catch (error) {
response.accepted = false
response.message = 'Error in API call!'
response.analytics = null
} finally {
res.send(JSON.stringify(response))
}
}
break
...
// In file db.js (cutted from the original file)
...
/**
* @async
* @description Validate the session key
* @param {string} sessionKey Session key
* @param {string} action Action to validate
* @throws Will throw if query to DB will fail
* @returns {Promise<boolean>} Return true if session key is valid, false otherwise
*/
async function validateApiRequest(sessionKey, action = undefined) {
const username = getUsernameFromSessionKey(sessionKey)
if (username) {
let user_data = undefined
const query_user_id = {
text: 'SELECT users_management, dataset_management ' +
'FROM users WHERE username = $1;',
values: [username]
}
try {
const userIdRes = await pool.query(query_user_id)
// console.log('[getUserProfilePic]', userProfilePicPathRes.rows)
if (!userIdRes.rows.length) {
user_data = undefined
return false
} else {
/* This may be a string or null */
user_data = userIdRes.rows[0]
}
} catch (err) {
console.error(err)
throw err.message
}
switch (action) {
case "get_data":
{
// check data validity here
}
break
default:
return true
}
}
return false
}
...
// Import module with ES6 syntax
import { SessionManager } from '../index.js';
const http = require('http')
// Create a new instance of the SessionManager class
const SM = new SessionManager();
/**
* Create and start an ioSocket server
* @param {*} app
* "Express" handle
* @param {*} port
* Port the server should listen on
* @returns {SocketIO.Server}
* The newly created server
*/
function startServer(app, port) {
// Create an http server
const server = http.createServer(app)
server.listen(port)
server.on('error', function(error) { onError(error, port) })
server.on('listening', function() { onListening(server) })
// Create the socketIO server
const ENDPOINT = `localhost:3000`;
const { Server } = require("socket.io");
const io = new Server(server, {
cors: {
origin: ENDPOINT,
methods: ["GET", "POST"]
}
});
io.on('connection', (sk) => {
console.log('Browser Connected!')
sk.on('session_key', async function(data) {
const key = data.session_key
console.log(`User ${data.user} joined key ${key}`)
sk.join(key)
})
})
return io
}
SM.initSocketReferences(startServer(app, port)) // Initialize the socket references
SM.on("notifyClientToLogout", (io, key) => { // When a user logs out, notify the client
console.debug(`Session is expired for key ${key}... Logging out now!`)
io.in(key).emit('logout') // Emit the logout event to the client
})
eventEmitter
:
Node.js Event Emitter object, is extended by the class. It fires the following events:
const io = require('@pm2/io') // Initialize the pm2 io module
// The PM2 IO metrics to monitor the number of connected users
const realtimeUser = io.counter({
name: 'Realtime Users',
id: 'app/realtime/users',
})
SM.on("sessionCreated", (key) => { // When a user logs out, notify the client
realtimeUser.inc() // Increment the number of active users
})
SM.on("sessionDeleted", (key) => { // When a user logs out, notify the client
realtimeUser.dec() // Decrement the number of active users
})
EventEmitter
SessionManager is a class that manages the sessions of the users.
Object
The sessions of the users.
number
The minimum session timeout.
Object
The settings of the session manager.
void
Logs a message to the console if the debug flag is set to true in the config.
EventEmitter
SessionManager is a class that manages the sessions of the users.
Kind: global class
Extends: EventEmitter
EventEmitter
boolean
number
array
boolean
SocketIO.Server
string
boolean
object
boolean
object
| boolean
boolean
boolean
boolean
NodeJS.Timeout
boolean
string
boolean
This function is used to set the session timeout
Kind: instance method of SessionManager
Returns: boolean
- true or false: true if ok
Param | Type | Description |
---|---|---|
sessionTimeout | number | The session timeout in seconds |
Example
setSessionTimeOut(3000) // Returns true or false
number
This function is used to get the session timeout
Kind: instance method of SessionManager
Returns: number
- The session timeout in seconds
Example
getSessionTimeOut() // Returns 3000
array
This function is used to get the list of logged users
Kind: instance method of SessionManager
Returns: array
- The list of logged users
Example
getLoggedUsers() // Returns ['Gino', 'Gino2']
boolean
Function to copy the Socket IO http server reference
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
Param | Type |
---|---|
ioRef | * |
SocketIO.Server
Function to get the socket reference
Kind: instance method of SessionManager
Returns: SocketIO.Server
- The socket reference
string
Function to add users sessions in this module. Use it at login
Kind: instance method of SessionManager
Returns: string
- user unique key
Param | Type | Description |
---|---|---|
username | string | The username provided on successful login |
Example
addSession('Gino') // Returns 'session_key'
boolean
Function to set the property 'data' of a session. Use it for example to store something in the session, like the user actions history, etc.
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
Throws:
Error
If the session_key is not foundParam | Type | Description |
---|---|---|
key | string | The session_key provided on successful login |
data | object | The data to be stored in the session |
Example
setSessionData('session_key', {'actions': ["logged in", ...]}) // Returns true or false
object
Function to get the property 'data' of a session. Use it for example to get the user actions history, etc.
Kind: instance method of SessionManager
Returns: object
- The data stored in the session
Throws:
Error
If the session_key is not foundParam | Type | Description |
---|---|---|
key | string | The session_key provided on successful login |
Example
getSessionData('session_key') // Returns {'actions': ["logged in", ...]}
boolean
Function that restart the session timer. Use it after an API call to keep the session alive.
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
Throws:
Error
If the session key is not foundParam | Type | Description |
---|---|---|
key | string | The session_key |
Example
restartSessionTimer('session_key') // Returns true or false
object
| boolean
Function to get details of a session. Use it to get the username, the creation date and the data.
Kind: instance method of SessionManager
Returns: object
| boolean
- The session details or false if not found
Throws:
Error
If the session key is not foundParam | Type | Description |
---|---|---|
key | string | The session_key |
Example
getSessionDetails('session_key') // Returns {'username': 'Gino', 'createdAt': 1523456789, 'data': {'actions': ["logged in", ...]}}
boolean
Function to delete users sessions in this module. Use it at client logout
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
Throws:
Error
If the session_key is not foundParam | Type | Description |
---|---|---|
key | string | The session_key provided on successful login |
Example
deleteSession('session_key') // Returns true or false
boolean
Function to delete all sessions
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
boolean
Use this to notify the client to logout with WebSocket
Kind: instance method of SessionManager
Returns: boolean
- true or false, true if ok
Param | Type | Description |
---|---|---|
key | string | The session_key |
Example
sendLogoutMessage('session_key') // Returns true or false
NodeJS.Timeout
Function to return a new setTimeout object and start it.
Kind: instance method of SessionManager
Param | Type | Description |
---|---|---|
key | string | The session_key |
username | string | The username, only for logging features |
Example
createNewSessionTimer('session_key', 'username') // Returns a new setTimeout object
boolean
Use this before every API.js function execution.n the stored collection
Kind: instance method of SessionManager
Returns: boolean
- true or false: true if session is active
Throws:
Error
if the session is not validError
if the session is expiredParam | Type | Description |
---|---|---|
key | string | the user key generated at login |
Example
checkSessionStatus('my_session_key') // true or false
string
Function to get the username from a session key
Kind: instance method of SessionManager
Returns: string
- The username or false if not found
Param | Type | Description |
---|---|---|
key | string | The session key |
Example
getUsernameFromSessionKey('123456789_123456789') // 'username'
Object
The sessions of the users.
number
The minimum session timeout.
Object
The settings of the session manager.
void
Logs a message to the console if the debug flag is set to true in the config.
Kind: global function
Param | Type |
---|---|
msg | string |
FAQs
A simple Node.js library to manage users sessions on a web application or any kind of JS apps
The npm package users-session-manager receives a total of 3 weekly downloads. As such, users-session-manager popularity was classified as not popular.
We found that users-session-manager demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Crates.io adds Trusted Publishing support, enabling secure GitHub Actions-based crate releases without long-lived API tokens.
Research
/Security News
Undocumented protestware found in 28 npm packages disrupts UI for Russian-language users visiting Russian and Belarusian domains.
Research
/Security News
North Korean threat actors deploy 67 malicious npm packages using the newly discovered XORIndex malware loader.