Успешно отозвал JWT с помощью Redis. Ниже приведен код для того же
redis.ts
import * as redis from 'redis';
import { Application } from './declarations';
import logger from './logger';
export default (app: Application) => {
const { connection } = app.get('redis');
const redisClient: redis.RedisClient = redis.createClient(connection);
redisClient.on('connect', () => {
logger.info('redis connected on %s:%d', connection.host, connection.port);
});
app.set('redisClient', redisClient);
};
redis-authentication.ts
import { promisify } from 'util';
import { AuthenticationService, AuthenticationResult, AuthenticationRequest } from '@feathersjs/authentication';
import { Application } from './declarations';
import { Params } from '@feathersjs/feathers';
import { NotAuthenticated } from '@feathersjs/errors';
import logger from './logger';
export class RedisAuthenticationService extends AuthenticationService {
redis: any;
constructor(app: Application, configKey?: string) {
super(app, configKey);
const redisClient = app.get('redisClient');
// Promise wrapper for Redis client
this.redis = {
redisClient,
get: promisify(redisClient.get.bind(redisClient)),
set: promisify(redisClient.set.bind(redisClient)),
exists: promisify(redisClient.exists.bind(redisClient)),
expire: promisify(redisClient.expire.bind(redisClient))
};
}
async revokeAccessToken(accessToken: any) {
// First make sure the access token is valid
const verified = await this.verifyAccessToken(accessToken);
// Calculate the remaining valid time for the token (in seconds)
const expiry = verified.exp - Math.floor(Date.now() / 1000);
// Add the revoked token to Redis and set expiration
await this.redis.set(accessToken, 'true');
await this.redis.expire(accessToken, expiry);
return verified;
}
async verifyAccessToken(accessToken: any) {
if (await this.redis.exists(accessToken)) {
throw new NotAuthenticated('Token revoked');
}
return super.verifyAccessToken(accessToken);
}
async remove(id: string, params: Params) {
const authResult = await super.remove(id, params);
const { accessToken } = authResult;
if (accessToken) {
// If there is an access token, revoke it
await this.revokeAccessToken(accessToken);
}
return authResult;
}
}
authentication.ts
import { ServiceAddons } from '@feathersjs/feathers';
import { AuthenticationService, JWTStrategy } from '@feathersjs/authentication';
import { LocalStrategy } from '@feathersjs/authentication-local';
import { expressOauth } from '@feathersjs/authentication-oauth';
import { Application } from './declarations';
import { RedisAuthenticationService } from './redis-authentication';
declare module './declarations' {
interface ServiceTypes {
'authentication': AuthenticationService & ServiceAddons<any>;
}
}
export default (app: Application) => {
const authentication = new RedisAuthenticationService(app);
authentication.register('jwt', new JWTStrategy());
authentication.register('local', new LocalStrategy());
app.use('/authentication', authentication);
app.configure(expressOauth());
};