Home > Back-end >  prevent multiple login from same user in React Node App
prevent multiple login from same user in React Node App

Time:05-19

I am unable to understand what should I do to prevent multiple login of same user. I am using google login with firebase in my React Node App with JWT token. How to make user logged out if login from other browser or other device. Is there any library that handle this or any way I can achieve this? I have checked many links but thee is no specific way of doing this.

Middleware auth

const auth = async (req, res, next) => {
  try {
    const token = req.headers.authorization.split(" ")[1];
    let decodedData = verifyToken(token);
    req.userId = decodedData?.id;
    next();
  } catch (error) {
    console.log(error);
    throw new Error()
  }
};

This is how I am verfying the token

export const verifyIdToken = async (idToken) => {
    try {
        return await admin.auth().verifyIdToken(idToken);
    } catch (e) {
        console.log(e);
        throw new Error(e)
    }
}

Controller auth.js

export const signin = async (req, res) => {
  try {
    const code = req.body.code;
    
    let profile = await verifyIdToken(code);
    const newUser = {
      uid: profile.uid,
      name: profile.name,
      email: profile.email,
    
    };
    let user = await db.aggregate('USER', query);
    user = user[0];
    if (!user) {
      user = await db.create('USER', newUser);
    }
    const token = generateToken(user);
    res.status(200).json({ user, token });
  } catch (err) {
    console.log(err)
    res.status(500).json({ message: "Something went wrong" });
  }
};

export const refreshToken = async (req, res) => {
  try {
   
    let user = await db.aggregate('USER', query);
    user = user[0];
    const token = generateToken(user);
    res.status(200).json({ user, token });
  } catch (err) {
    console.log(err)
    res.status(500).json({ message: "Something went wrong" });
  }
};

CodePudding user response:

  1. Install Firebase Admin SDK to your server. Follow this link: https://firebase.google.com/docs/admin/setup?hl=en
  2. Create API can receive uid of user then revokes current sessions. See more: https://firebase.google.com/docs/auth/admin/manage-sessions?hl=en

getAuth()
  .revokeRefreshTokens(uid)
  .then(() => {
   return getAuth().getUser(uid);
    })
     .then((userRecord) => {
      return new Date(userRecord.tokensValidAfterTime).getTime() / 1000;
      })
       .then((timestamp) => {
        console.log(`Tokens revoked at: ${timestamp}`);
         });

Then other user will have invalid Token, so closely logout.

  1. Check idToken revocation: https://firebase.google.com/docs/auth/admin/manage-sessions?hl=en#detect_id_token_revocation_in_the_sdk

// Verify the ID token while checking if the token is revoked by passing
// checkRevoked true.
    let checkRevoked = true;
    getAuth()
      .verifyIdToken(idToken, checkRevoked)
      .then((payload) => {
        // Token is valid.
      })
      .catch((error) => {
        if (error.code == 'auth/id-token-revoked') {
          // Token has been revoked. Inform the user to reauthenticate or signOut() the user.
        } else {
          // Token is invalid.
        }
      });

I hope above infomation to help you.

CodePudding user response:

There might be different ways of doing this but i think, this way will also work.

First adding two more field to your users database

isLogedIn: (which should be false initially)

And another field

userBrowser: ( set to null initially)

Then when authenticating the user, after checking for username and password, you also check whether isLogerIn is false or true, if its true you can return a message to the user. But if false you can set it to true after authentication. And you can you get brower info with

req.headers["user-agent"]

And set it to userBrowser after authenticating the user. So when authenticating you check for isLogedIn and if true, you can send a message like

error: user already logger in, with (the brower nane already in database: userBrowser)
  • Related