Как распознать токен JWT из другого гнезда арендатора js Мути-арендатор JWT - PullRequest
0 голосов
/ 11 марта 2020

Я использую мультитенант для нескольких баз данных и использую токен jwt в качестве авторизации, меня беспокоит то, что когда пользователь 1 арендатора 2 входит в систему и получает токен jwt, когда он использует токен для доступа к другому арендатору, он распознается как пользователь 1 арендатора 2? Если да, то как мы можем это исправить?

Моя стратегия

jwt.strategy.ts


@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,

    private readonly moduleRef: ModuleRef,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      passReqToCallback: true,
      secretOrKey: configService.get('JWT_SECRET_KEY'),
    });
  }

  async validate(request: Request, jwtPayload: JwtPayload) {
    const contextId = ContextIdFactory.getByRequest(request);

    const authService: AuthService = await this.moduleRef.resolve(
      AuthService,
      contextId,
    );

    let { iat, exp } = jwtPayload;
    const timeDiff = exp - iat;

    if (timeDiff <= 0) {
      throw new UnauthorizedException();
    }
    return jwtPayload;
  }
}

Моя служба аутентификации

auth.service.ts


@Injectable({ scope: Scope.REQUEST })
export class AuthService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
    private readonly userService: UsersService,
    private readonly auctionHouseService: AuctionHouseService,
  ) {}

  async createToken(user: User) {
    let plainUser: any = Object.assign({}, user);
    plainUser.auctionHouseId = (
      await this.auctionHouseService.getCurrentAuctionHouse()
    ).id;
    return {
      expiresIn: this.configService.get('JWT_EXPIRATION_TIME'),
      accessToken: this.jwtService.sign(plainUser),
    };
  }

}

Контроллер My Login

auth.controller.ts


@Controller('api/auth')
@ApiUseTags('authentication')
export class AuthController {
  constructor(
    private readonly authService: AuthService,
    private readonly userService: UsersService,
  ) {}

  @Post('login')
  @ApiResponse({ status: 201, description: 'Successful Login' })
  @ApiResponse({ status: 400, description: 'Bad Request' })
  @ApiResponse({ status: 401, description: 'Unauthorized' })
  async login(@Body() payload: LoginPayload, @Req() req): Promise<any> {
    let user = await this.authService.validateUser(payload);

    return omitPassword(await this.authService.createToken(user));
  }

1 Ответ

1 голос
/ 19 марта 2020

Как правило, правильным способом определения домена, в котором действует JWT, является поле aud (или аудитория). По RFC7519 :

Заявка "aud" (аудитория) определяет получателей, для которых предназначен JWT. Каждый принципал, предназначенный для обработки JWT, ДОЛЖЕН идентифицировать себя со значением в заявке аудитории. Если принципал, обрабатывающий претензию, не идентифицирует себя со значением в претензии "aud", когда эта претензия присутствует, то JWT ДОЛЖЕН быть отклонен. В общем случае значение «aud» представляет собой массив строк с учетом регистра, каждая из которых содержит значение StringOrURI. В особом случае, когда JWT имеет одну аудиторию, значение «aud» МОЖЕТ быть единственной чувствительной к регистру строкой, содержащей значение StringOrURI. Интерпретация ценностей аудитории обычно определяется приложением c. Использование этого утверждения НЕОБЯЗАТЕЛЬНО.

В вашем контексте вы хотите выбрать уникальную аудиторию для каждого из ваших арендаторов (скажем, это tenant1 и tenant2) и при создании JWT. вы бы сделали что-то вроде этого:

plainUser.aud = this.configService.get("JWT_TENANT")

При проверке токена вы вводите проверку, которая подтверждает, что заявка aud соответствует текущему арендатору.

let { iat, exp, aud } = jwtPayload;
if (aud !== this.configService.get("JWT_TENANT")) {
  throw new UnauthorizedException();
}

// The rest of your validation code

ПРИМЕЧАНИЕ Я предполагаю, что вы будете запускать несколько экземпляров приложения с разными конфигурациями для каждого арендатора, однако если арендаторы получены в другом месте, вам следует вместо этого собрать эту информацию из соответствующего источника данных.

Подходя таким образом, вы сможете определить пользователя и арендатора, к которому он принадлежит, и запретить использование токенов tenant1 для доступа к tenant2.

.
...