@w3lcome/feathers-refresh-token
Version:
Refresh token hooks for @feathers/authentication
137 lines • 4.91 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.lookupRefreshToken = exports.lookupRefreshTokenId = exports.loadConfig = void 0;
const debug_1 = __importDefault(require("debug"));
const core_1 = require("./core");
const debug = debug_1.default('feathers-refresh-token');
let refreshTokenOptions = null;
/*
* Return refresh-tokens all depending options
*/
exports.loadConfig = (app) => {
// refresn token options already loaded, simply return
if (refreshTokenOptions) {
return refreshTokenOptions;
}
// get default authentication key
const defaultAuthKey = app.get('defaultAuthentication');
const { entity: userEntity, // The name of the field that will contain the entity after successful authentication
entityId: userEntityId, //T he id property of an entity object
service: userService, // The path of the entity service
'refresh-token': config } = app.get(defaultAuthKey);
if (!userEntity || !defaultAuthKey || !app.service(userService)) {
throw new Error(`Invalid authentication service configuration!`);
}
debug(`Default authentication key and config:`, defaultAuthKey, app.get(defaultAuthKey));
// merge default options and options loaded from config
const finalOptions = {
...core_1.defaultOptions,
authService: defaultAuthKey,
userEntityId: userEntityId ? userEntityId : app.service(userService).id,
userEntity,
...config
};
debug(`Returning final options for refresh token`, finalOptions);
if (!app.service(finalOptions.service)) {
throw new Error(`Missing refresh-token entity service. Make sure refresh-tokens servie is configured properly.`);
}
refreshTokenOptions = finalOptions;
return finalOptions;
};
/*
*
* Return an existing refresh-token
* context: Hook context
* config: Refresh-token config options
* params: query conditions
*/
exports.lookupRefreshTokenId = async (context, config, params) => {
const { existingToken } = await exports.lookupRefreshToken(context, config, params);
if (!existingToken) {
return null;
}
debug('Find existing refresh token result', existingToken);
const { entityId, service } = config;
// ! this is refresh token ID in database, not user ID
const tokenEntityId = entityId
? entityId
: context.app.service(service).id;
debug(`tokenEntityId: ${tokenEntityId}`);
const { [tokenEntityId]: tokenId } = existingToken;
// tokenId could be 0
if (tokenId === null || tokenId === undefined) {
throw new Error('Invalid refresh token!');
}
debug('refresh-token Id', tokenId);
// set context ID to refresh token ID to delete it from DB
return tokenId;
};
/*
*
* Return an valid existing refresh-token
* context: Hook context
* config: Refresh-token config options
* params: query conditions
*/
exports.lookupRefreshToken = async (context, config, params) => {
const { app } = context;
const { userId, deviceId, isValid, refreshToken } = params;
if (!userId) {
throw new Error(`userId is mandatory for querying refresh-token`);
}
const { service, authService, jwtOptions, secret } = config;
let query = {
userId: `${userId}`,
isValid: isValid ? isValid : true
};
if (refreshToken) {
query = {
...query,
refreshToken
};
}
if (deviceId) {
query = {
...query,
deviceId
};
}
const existingToken = await app.service(service).find({
query
});
debug(`Refresh token lookup result: `, existingToken);
let data = null;
if (Array.isArray(existingToken) && existingToken.length > 0) {
data = existingToken[0];
}
else if (existingToken && existingToken.total > 0 && existingToken.data) {
data = existingToken.data[0];
}
else {
data = existingToken;
}
if (!data || !data.refreshToken) {
return { existingToken: null, verifyResult: null };
}
// ! verify refresh-token before returning
try {
const verifyResult = await app.service(authService).verifyAccessToken(data.refreshToken, jwtOptions, // refresh token options
secret // refresh token secret, should be different than access token
);
if (!verifyResult) {
throw new Error('Invalid refresh-token!');
}
return { existingToken: data, verifyResult };
}
catch (error) {
// refresh token is invalid
await app.service(service).patch(data.id, {
isValid: false
});
return { existingToken: null, verifyResult: null };
}
};
//# sourceMappingURL=common.js.map
;