Nestjs + Passport: запретить пользователю 1 доступ к информации пользователя 2

Как я могу запретить пользователю 1 доступ к информации пользователя 2 с помощью паспорта в приложении Nesjs?

У меня уже есть 2 стратегии:

  • локальная стратегия, которая проверяет пользователя с помощью электронной почты / пароля. Маршрут, защищенный этой стратегией, возвращает токен jwt.

  • стратегия jwt, которая проверяет данный токен jwt.

Теперь я хочу ограничить доступ к таким маршрутам, как users/:idв токен jwt, который фактически имеет тот же зашифрованный идентификатор пользователя.

Как это сделать?

2 ответа

РЕДАКТИРОВАТЬ

Я смешивал аутентификацию и авторизацию: я хочу добиться авторизации после аутентификации использования.

Пришлось использовать Guard:

own.guard.ts

@Injectable()
export class OwnGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const req = context.switchToHttp().getRequest();
    return req.user.id === req.params.id;
  }
}

Затем используйте его в моем маршруте:

@Get(':id')
@UseGuards(OwnGuard)
async get(@Param('id') id: string) {
  return await this.usersService.get(id);
}

ОРИГИНАЛЬНЫЙ ОТВЕТ

Я создал третью стратегию на основе стратегии jwt:

@Injectable()
export class OwnStrategy extends PassportStrategy(Strategy, 'own') {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: SECRET,
      passReqToCallback: true
    });
  }

  async validate(req: Request, payload: { sub: string }) {
    if (req.params.id !== payload.sub) {
      throw new UnauthorizedException();
    }
    return { userId: payload.sub };
  }
}

Обратите внимание, как я передаю собственное имя в качестве второго параметра PassportStrategyчтобы отличить его от "jwt". Его охранник:

@Injectable()
export class OwnAuthGuard extends AuthGuard('own') {}

Это работает, но мне интересно, хороший ли это способ сделать это...

Что, если позже я захочу внести изменения для пользователей с правами администратора?

Должен ли я создать четвертую стратегию, которая проверяет, role === Role.ADMIN || req.params.id === payload.sub?

Думаю, что-то упускаю. Должен быть способ создать стратегию, которая проверяет только jwt, еще одну - только userId, еще одну - только роль, и комбинирует их так, как я хочу, применяя охрану к моим маршрутам.

тот же случай. вы можете использовать handleRequest метод в карауле.

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

      @Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
    canActivate(context: ExecutionContext) {
        return super.canActivate(context);
    }

    handleRequest(err, user, info, context: ExecutionContext) {
        const request = context.switchToHttp().getRequest<Request>();
        const params = request.params;
        if (user.id !== +params.id) {
            throw new ForbiddenException();
        }

        return user;
    }
}

подробнее здесь https://docs.nestjs.com/security/authentication#exnding-guards

Другие вопросы по тегам