Перья js Отзыв JWT с использованием Redis - PullRequest
1 голос
/ 02 февраля 2020

Перья js Отзыв JWT с использованием Redis

Используя приведенный пример, не удалось достичь ожидаемого результата, токен не был отозван, он был повторно аутентифицирован, не смог выяснить чего не хватало Требуется помощь, как отозвать токен JWT.

Ссылка - https://docs.feathersjs.com/cookbook/authentication/revoke-jwt.html имеет пример redis.

1 Ответ

0 голосов
/ 11 февраля 2020

Успешно отозвал 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());
};
...