Handling multiple devices for a single user in a token-based authentication system (like JWT or OAuth2)

 

1. Use Refresh Tokens with Access Tokens

  • Access tokens should be short-lived (e.g., 15 minutes).

  • Refresh tokens should be long-lived and tied to a specific device.

  • This prevents all sessions from being compromised if one token leaks.


2. Store Tokens Securely Per Device

  • Mobile apps: Use Secure Storage (e.g., Keychain on iOS, Keystore on Android).

  • Web apps: Prefer HTTP-only cookies for refresh tokens (avoid localStorage).


3. Track Devices with Unique Identifiers

  • Assign a device ID for each device upon login/registration.

  • Store it alongside the refresh token in your DB (e.g., { userId, deviceId, refreshToken, lastSeen, ipAddress }).


4. Allow Session Management

  • Provide users a “manage devices” interface.

  • Let them revoke sessions from specific devices.


5. Token Revocation Strategy

  • Use a server-side token store or blacklist mechanism to invalidate compromised tokens.

  • Maintain a list of valid refresh tokens per user/device.


6. Notify on New Device Logins

  • Alert users when a new device logs in or an existing session is reused from a different IP or location.


7. Rate Limiting & Device Limits

  • Optionally limit how many devices a user can log in to simultaneously.

  • Prevent abuse by rate-limiting login attempts.


Here's a practical example of handling multiple devices using token-based authentication (with access/refresh tokens and device tracking) using Node.js + Express + JWT + MongoDB.


1. Database Schema (MongoDB + Mongoose)

js

const mongoose = require('mongoose'); const RefreshTokenSchema = new mongoose.Schema({ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, deviceId: { type: String, required: true }, refreshToken: { type: String, required: true }, userAgent: String, ip: String, lastUsed: { type: Date, default: Date.now }, }); module.exports = mongoose.model('RefreshToken', RefreshTokenSchema);

2. Login Route (Issuing Tokens Per Device)

js

const jwt = require('jsonwebtoken'); const RefreshToken = require('./models/RefreshToken'); app.post('/login', async (req, res) => { const { email, password, deviceId } = req.body; const user = await User.findOne({ email }); if (!user || !(await user.comparePassword(password))) { return res.status(401).send('Invalid credentials'); } const accessToken = jwt.sign({ userId: user._id }, 'ACCESS_SECRET', { expiresIn: '15m' }); const refreshToken = jwt.sign({ userId: user._id, deviceId }, 'REFRESH_SECRET', { expiresIn: '7d' }); await RefreshToken.findOneAndUpdate( { userId: user._id, deviceId }, { refreshToken, ip: req.ip, userAgent: req.headers['user-agent'], lastUsed: new Date() }, { upsert: true } ); res.json({ accessToken, refreshToken }); });

3. Refresh Token Route (Per Device)

js

app.post('/token', async (req, res) => { const { refreshToken, deviceId } = req.body; if (!refreshToken) return res.status(401).send('Missing token'); try { const payload = jwt.verify(refreshToken, 'REFRESH_SECRET'); const storedToken = await RefreshToken.findOne({ userId: payload.userId, deviceId, refreshToken }); if (!storedToken) return res.status(403).send('Invalid session'); const newAccessToken = jwt.sign({ userId: payload.userId }, 'ACCESS_SECRET', { expiresIn: '15m' }); storedToken.lastUsed = new Date(); await storedToken.save(); res.json({ accessToken: newAccessToken }); } catch (err) { return res.status(403).send('Token expired or invalid'); } });

4. Logout from a Specific Device

js

app.post('/logout', async (req, res) => { const { deviceId } = req.body; const userId = req.user.userId; // from middleware await RefreshToken.deleteOne({ userId, deviceId }); res.send('Logged out from device'); });

5. Optional: Get All Logged-in Devices

js

app.get('/devices', async (req, res) => { const userId = req.user.userId; const devices = await RefreshToken.find({ userId }).select('-refreshToken'); res.json(devices); });

This structure supports:

  • Multiple devices per user.

  • Secure refresh token handling per device.

  • Manual session management (logout specific device, list devices).

  • Optional device fingerprinting or IP tracking.

No comments:

Post a Comment

Best for you