fix: Invalidate access tokens on password change

pull/279/head
Simon Tagne 3 years ago
parent e9a65bb641
commit 266a762641
No known key found for this signature in database
GPG Key ID: 1567DE3ADB69D589

@ -5,6 +5,7 @@ import request from '../request';
import selectors from '../../../selectors';
import actions from '../../../actions';
import api from '../../../api';
import { setAccessToken } from '../../../utils/access-token-storage';
export function* createUser(data) {
yield put(actions.createUser(data));
@ -109,13 +110,18 @@ export function* updateUserPassword(id, data) {
yield put(actions.updateUserPassword(id, data));
let user;
let accessToken;
try {
({ item: user } = yield call(request, api.updateUserPassword, id, data));
({ item: user, accessToken } = yield call(request, api.updateUserPassword, id, data));
} catch (error) {
yield put(actions.updateUserPassword.failure(id, error));
return;
}
if (accessToken !== undefined) {
yield call(setAccessToken, accessToken);
}
yield put(actions.updateUserPassword.success(user));
}

@ -1,6 +1,7 @@
import Cookies from 'js-cookie';
import Config from '../constants/Config';
import socket from '../api/socket';
export const setAccessToken = (accessToken) => {
Cookies.set(Config.ACCESS_TOKEN_KEY, accessToken, {
@ -11,6 +12,8 @@ export const setAccessToken = (accessToken) => {
Cookies.set(Config.ACCESS_TOKEN_VERSION_KEY, Config.ACCESS_TOKEN_VERSION, {
expires: Config.ACCESS_TOKEN_EXPIRES,
});
socket.headers = { Cookie: document.cookie };
};
export const getAccessToken = () => {

@ -66,6 +66,27 @@ module.exports = {
throw Errors.USER_NOT_FOUND;
}
// Disconnect all sockets from this user except the current one
const tempRoom = `temp:${user.id}`;
sails.sockets.addRoomMembersToRooms(`user:${user.id}`, tempRoom, () => {
if (currentUser.id === user.id && this.req.isSocket) {
sails.sockets.leave(this.req, tempRoom, () => {
sails.sockets.leaveAll(tempRoom);
});
} else {
sails.sockets.leaveAll(tempRoom);
}
});
if (currentUser.id === user.id) {
const accessToken = sails.helpers.utils.signToken(user.id);
return {
accessToken,
item: user,
};
}
return {
item: user,
};

@ -56,6 +56,8 @@ module.exports = {
if (!_.isUndefined(inputs.values.password)) {
// eslint-disable-next-line no-param-reassign
inputs.values.password = bcrypt.hashSync(inputs.values.password, 10);
// eslint-disable-next-line no-param-reassign
inputs.values.passwordChangedAt = new Date();
if (Object.keys(inputs.values).length === 1) {
isOnlyPasswordChange = true;

@ -11,6 +11,6 @@ module.exports = {
},
fn(inputs) {
return jwt.sign(inputs.payload, sails.config.session.secret);
return jwt.sign({ sub: inputs.payload }, sails.config.session.secret);
},
};

@ -11,14 +11,27 @@ module.exports = function defineCurrentUserHook(sails) {
const getUser = async (accessToken) => {
let id;
let iat;
let decodedToken;
try {
id = sails.helpers.utils.verifyToken(accessToken);
decodedToken = sails.helpers.utils.verifyToken(accessToken);
} catch (error) {
return null;
}
return sails.helpers.users.getOne(id);
if (_.isString(decodedToken)) {
id = decodedToken;
iat = 1;
} else {
id = decodedToken.sub;
iat = decodedToken.iat;
}
return sails.helpers.users.getOne({
id,
passwordChangedAt: { '<=': new Date((iat + 1) * 1000) },
});
};
return {

@ -67,6 +67,11 @@ module.exports = {
type: 'ref',
columnName: 'deleted_at',
},
passwordChangedAt: {
type: 'ref',
columnName: 'password_changed_at',
defaultsTo: new Date(0).toUTCString(),
},
// ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗
// ║╣ ║║║╠╩╗║╣ ║║╚═╗

@ -0,0 +1,11 @@
module.exports.up = async (knex) =>
knex.schema.table('user_account', (table) => {
/* Columns */
table.timestamp('password_changed_at', true).defaultsTo(new Date(0).toUTCString());
});
module.exports.down = async (knex) =>
knex.schema.table('user_account', (table) => {
table.dropColumn('password_changed_at');
});
Loading…
Cancel
Save