Socket.io authorization is still persistent although user is logged out on the website - node.js

I'm using the express-socket.io-session on my app. I've integrated it and it works properly. There is only one case though.
Have a look at the following code:
io.use(...);
io.sockets.on("connection", function (socket) {
socket.onVerify = (msg, fn) => {
socket.on(msg, (data) => {
console.log(socket.handshake.session.passport);
if (typeof socket.handshake.session.passport === "undefined") {
socket.emit("auth failed emit", {
msg: "Please login via the website"
});
return false;
}
fn(data, socket.handshake.session);
});
}
socket.onVerify("chat message", function (req, session) {
Chat.publish(session.email, req.msg);
});
});
Basically, on each socket request, I verify socket.handshake.session.passport being defined, which means user is logged in.
It works in this case:
I open a browser tab, login with my credentials, get redirected to /game endpoint where my game loads and connects to socket.io
I click on "logout" button, get redirected to /game endpoint, game tells me "I need to authorize."
However, it doesn't work in this case:
I open a browser tab, login with my credentials, get redirected to /game endpoint where my game loads and connects to socket.io
I click on "logout" button ON A NEW TAB, and logout in that tab.
I switch back to main tab, and game is still online.
I added a debug in my code (console.log(socket.handshake.session.passport)) and it shows { user: 1 } although I logged out already so it must be undefined
For some reason, socket.io handshake/session doesn't recognize it, so I probably need to refresh it on certain cases.
Is there any way to do it with socket.io?

This is just a try to resolve your issue, i'm not really sure it would work. But you could try something like that :
app.get("/logout", function(req,res){
//do other logging out stuff
sockets.disconnectUser(req.session.user_id);
}
// Disconnect User function
sockets.disconnectUser = function(user_id){
sockets.socket(users[user_id]).disconnect();
}
Like described here : Destroying a handshake after logout. socket.io

Related

load last viewed page on chrome extension startup

I'm developing my first chrome extension and I'm stuck with a "session restore" problem. At the begging of the developement when a user log in to my extension and close the popup, when he open the plugin again he had to login again.
I've used chrome.storage.sync to be able to save the session infomation to make the user to be still logged in and if he close the plugin, and his session is still active he will be redirected to the welcome page. But how can I check at the extension's startup in what page of the plugin the user was and bring him back to that page?
For example, if a user is logged and was on the "choose a book" section, how can i make the plugin open at "choose a book" section and not in "welcome" section?
Angular 2 for client side
NodeJs for server side
Consider that the session object is something like:
{
logged: true,
last_section: 'books'
}
When the user visits the books section, save it.
// this code goes inside some listener for visiting a section
chrome.storage.sync.get('session', function (items) {
const session = items.session || {}
session.last_section = 'books'
chrome.storage.sync.set({ session })
})
At the beginning of the popup script, you can simply call chrome.storage.sync.get to get the last session object state.
chrome.storage.sync.get('session', function (items) {
const session = items.session
if (session && session.logged) {
if (session.last_section === 'books') {
// render books section
}
if (session.last_section === 'welcome') {
// render welcome section
}
}
})

Firebase Auth Web: Logout with page reload

I use Firebase with VueJS. Sign-up, sign-in works fine so far but as soon as I reload the page with F5 or load a page with writing to the browsers address bar directly then the auth session is killed, the user isn't signed-in anymore. It works fine as long as I don't reload the page, even if I click route links or get redirected to other pages, the user session keeps alive. It doesn't matter where I reload the page btw.
My login method:
firebase.auth().signInWithEmailAndPassword(this.username, this.password).then(
(user) => {
if (user.emailVerified === false) {
firebase.auth().signOut()
} else {
// redirect to lobby page if user is verified and signed in
this.$router.push('/lobby')
}
},
function(err) {
console.log(err.message)
}
)
You need to call firebase.auth().onAuthStateChanged in order to detect whether a user is logged in.
This method gets invoked in the UI thread on changes in the authentication state:
Right after the listener has been registered
When a user is signed in
When the current user is signed out
When the current user changes
Source
Example usage can be like this:
firebase.auth().onAuthStateChanged(user => {
if (user) {
if (user.emailVerified === false) {
firebase.auth().signOut()
} else {
this.$router.push('/lobby')
}
} else {
// will get to here from a logout event
// this.$router.push('/login')
}
}
Use this in your main.js file:
firebase.auth().onAuthStateChanged(() => {
if (!app) {
app = createApp(App).use(store).use(router).mount('#app')
}})
Firebase will run before Vue app is created.

Socket.io+SailsJS: Chat application-How to check whether the client is shut down,and make the user offline?

I am creating a multi-user chat application in node-web kit and SailJs and I was trying to implement login status of the users. User comes online when they open the application. The cases for the user to go offline are:
User clicks logout button
User closes the application window.
User turns his/her system off.
The logout status doesn't work when the user turns off their system. Here is a part of my code which I have written:
UserSocket.find({
companyId: user.companyId
}, function (err, sockets) {
if (!err && sockets != undefined && sockets.length > 0) {
socketList = _.pluck(sockets, "socketId");
sails.sockets.emit(socketList, 'userOffline', {
previous: user
});
}
});
Please help me in figuring out this issue. Thanks in advance.
Have you tried to use the onDisconnect method in the config/sockets.js ?
module.exports.sockets = {
onDisconnect: function(session, socket) {
//do your stuff here
}
}

(Token-based A&A): send the token on every request to the server

I am debugging a token-based A&A module in node.js + angularJS. In this approach, server authenticates the user and responds with a token. This token is saved in a local memory (client side) and user sends the token on every request to the server using the attached code.
However, I face a weird situation:
I login to www.test.com
Then I can see my dashboard: www.test.com/dashboard
Next, I logout from my dashboard
Afterwards, I open a new tab and type "www.test.com/dashboard" in the address bar of the browser. I expected the user directly go to the login page. However, for 1-2 seconds I see my dashboard (e.g., www.test.com/dashboard) and then it goes to login page !!!! I dont understand why it shows my dashboard for 1-2 seconds !!!
I guess the reason is that developers did not attached the token to GET request! any suggestion to remove the problem?
btw, where is the best location (for both angularJS and EJS) to save the token to be able to send it with all requests to server (ajax, GET, ..., websocket) ?
app.factory('AuthInterceptor', function ($window, $q) {
return {
request: function(config) {
config.headers = config.headers || {};
if ($window.sessionStorage.getItem('token')) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.getItem('token');
}
return config || $q.when(config);
},
response: function(response) {
if (response.status === 401) {
// TODO: Redirect user to login page.
}
return response || $q.when(response);
}
};
});
// Register the previously created AuthInterceptor.
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');

How do you do "remember me" functionality in AngularJS?

I have a simple app I'm building using Play + AngularJS that requires authentication before most routes can be accessed. The login flow includes a "remember me" feature that stores a session ID in to the browser local storage and gets mapped to a valid authorized database session entry on the server side any time a user returns to the app.
The problem I'm having is that I do the session checking (extract cookie & compare against server) in the run() function of the module:
.run(function ($rootScope, $http, $cookieStore, $location) {
// <snip>
// check if there is already a session?
var sessionId = window.localStorage["session.id"];
if (sessionId == null) {
sessionId = $cookieStore.get("session.id");
}
if (sessionId != null) {
$http.get("/sessions/" + sessionId)
.success(function (data) {
$http.defaults.headers.common['X-Session-ID'] = data.id;
$cookieStore.put("session.id", data.id);
$rootScope.user = data.user;
})
.error(function () {
// remove the cookie, since it's dead
$cookieStore.remove("session.id");
window.localStorage.removeItem("session.id");
$location.path("/login");
});
} else {
if ($location.path() != "/login" && $location.path() != "/signup") {
$location.path("/login");
}
}
});
The problem is that this function executes an AJAX call and I don't know if the session is valid until it completes. However, the controller that loads (via the route selected by $routeProvider) can fire away another AJAX call that often kicks off before the other one finishes, resulting in a race condition and the initial request getting a 401 response code.
So my question is: how can I force run (with its associated $http call) to complete before any other part of the app runs? I have tried using $q/promise here and it doesn't seem to make a difference (perhaps run functions don't honor promises). I've been advisor to use resolve feature in $routeProvider but I don't know exactly what to do and I'm not super execited about having to put that in for every route anyway.
I assume this is a pretty common use case and it gets solved every day. Hopefully someone can give me some direction with my code, or share their approaches for "remember me" and AngularJS.
You need to manual bootstrap your app after you get session from server.It's easy if you use jQuery for example you can do, or even without jQuery you can use injector to access $http before bootstrapping
$.get(server,function(){
//success , set variable.
}).fail(function (){
//failed :( redirect to login or set session to false etc... null
})
.always(function(){
//alwyas bootstrap in both case and set result as a constant or variable Angular.module('app').variable('session',sessionResult);
});
I'm on phone right now, but this should give u the idea

Resources