const UserError = require('vn-loopback/util/user-error'); const {models} = require('vn-loopback/server/server'); const handlePromiseLogout = (Self, {id}, courtesyTime) => { new Promise(res => { setTimeout(() => { res(Self.logout(id)); } , courtesyTime * 1000); }); }; module.exports = Self => { Self.remoteMethodCtx('renewToken', { description: 'Checks if the token has more than renewPeriod seconds to live and if so, renews it', accessType: 'WRITE', accepts: [], returns: { type: 'Object', root: true }, http: { path: `/renewToken`, verb: 'POST' } }); Self.renewToken = async function(ctx) { const {accessToken: token} = ctx.req; // Check if current token is valid const isValid = await validateToken(token); if (isValid) return token; const {courtesyTime} = await models.AccessTokenConfig.findOne({fields: ['courtesyTime']}); // Schedule to remove current token handlePromiseLogout(Self, token, courtesyTime); // Create new accessToken const user = await Self.findById(token.userId); const accessToken = await user.createAccessToken(); return {id: accessToken.id, ttl: accessToken.ttl}; }; async function validateToken(token) { const accessTokenConfig = await models.AccessTokenConfig.findOne({fields: ['renewPeriod', 'courtesyTime']}); const now = Date.now(); const differenceMilliseconds = now - token.created; const differenceSeconds = Math.floor(differenceMilliseconds / 1000); const isValid = differenceSeconds < accessTokenConfig.renewPeriod - accessTokenConfig.courtesyTime; return isValid; } };