UNPKG

@adonisjs/auth

Version:

Official authentication provider for Adonis framework

130 lines (129 loc) 4.08 kB
"use strict"; /* * @adonisjs/auth * * (c) Harminder Virk <virk@adonisjs.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.TokenRedisProvider = void 0; const utils_1 = require("@poppinss/utils"); const helpers_1 = require("@poppinss/utils/build/helpers"); const ProviderToken_1 = require("../../Tokens/ProviderToken"); /** * Redis backed tokens provider. */ class TokenRedisProvider { constructor(config, redis) { this.config = config; this.redis = redis; /** * The foreign key column */ this.foreignKey = this.config.foreignKey || 'user_id'; } /** * Returns the singleton instance of the redis connection */ getRedisConnection() { /** * Use custom connection if defined */ if (this.connection) { return typeof this.connection === 'string' ? this.redis.connection(this.connection) : this.connection; } /** * Config must have a connection defined */ if (!this.config.redisConnection) { throw new utils_1.Exception('Missing "redisConnection" property for auth redis provider inside "config/auth" file', 500, 'E_INVALID_AUTH_REDIS_CONFIG'); } return this.redis.connection(this.config.redisConnection); } /** * Parse the stringified redis token value to an object */ parseToken(token) { if (!token) { return null; } try { const tokenRow = JSON.parse(token); if (!tokenRow.token || !tokenRow.name || !tokenRow[this.foreignKey]) { return null; } return tokenRow; } catch { return null; } } /** * Define custom connection */ setConnection(connection) { this.connection = connection; return this; } /** * Reads the token using the lookup token id */ async read(tokenId, tokenHash, tokenType) { /** * Find token using id */ const tokenRow = this.parseToken(await this.getRedisConnection().get(`${tokenType}:${tokenId}`)); if (!tokenRow) { return null; } /** * Ensure hash of the user provided value is same as the one inside * the database */ if (!(0, helpers_1.safeEqual)(tokenRow.token, tokenHash)) { return null; } const { name, [this.foreignKey]: userId, token: value, ...meta } = tokenRow; const token = new ProviderToken_1.ProviderToken(name, value, userId, tokenType); token.meta = meta; return token; } /** * Saves the token and returns the persisted token lookup id, which * is a cuid. */ async write(token) { /** * Payload to save to the database */ const payload = { [this.foreignKey]: token.userId, name: token.name, token: token.tokenHash, ...token.meta, }; const ttl = token.expiresAt ? Math.ceil(token.expiresAt.diffNow('seconds').seconds) : 0; const tokenId = (0, helpers_1.cuid)(); if (token.expiresAt && ttl <= 0) { throw new utils_1.Exception('The expiry date/time should be in the future', 500, 'E_INVALID_TOKEN_EXPIRY'); } if (token.expiresAt) { await this.getRedisConnection().setex(`${token.type}:${tokenId}`, ttl, JSON.stringify(payload)); } else { await this.getRedisConnection().set(`${token.type}:${tokenId}`, JSON.stringify(payload)); } return tokenId; } /** * Removes a given token */ async destroy(tokenId, tokenType) { await this.getRedisConnection().del(`${tokenType}:${tokenId}`); } } exports.TokenRedisProvider = TokenRedisProvider;