#GraphQL & Refresh Token

8 messages · Page 1 of 1 (latest)

sharp lagoon
#

Hello everyone, I have a very simple doubt but that has complicated me a bit the development of my application, and basically is, how can I make an "endpoint" or better said, solve to be able to update the access token based on the refresh token? I am having a problem and it is that I never get to the JwtRefreshStrategy.

I will attach code to show.

JwtRefreshGuard

@Injectable()
export class JwtRefreshGuard extends AuthGuard('jwt-refresh') {
  constructor(private readonly reflector: Reflector) {
    super();
  }

  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    const req = ctx.getContext().req;
    return req;
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (isPublic) return true;

    return super.canActivate(context) as Promise<boolean>;
  }
}

JwtRefreshStrategy

@Injectable()
export class JwtRefreshStrategy extends PassportStrategy(
  Strategy,
  'jwt-refresh',
) {
  constructor(
    @Inject(EnvConfig.KEY) private configService: ConfigType<typeof EnvConfig>,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.SECURITY.JWT_REFRESH_TOKEN,
      passReqToCallback: true,
    });
  }

  async validate(request: Request, payload: JwtPayload): Promise<any> {
    const refreshToken = request
      .get('Authorization')
      .replace('Bearer', '')
      .trim();

    if (!refreshToken) throw new ForbiddenException('Refresh token malformed');

    return { ...payload, refreshToken };
  }
}
#

My endpoint looks like this:

@Mutation(() => String, {
    name: 'refreshToken',
    description: 'Refresh the access token using the refresh token.',
  })
  @UseGuards(JwtRefreshGuard)
  async refreshToken(
    @GetCurrentUserId() userId: string,
    @GetCurrentUser('refreshToken') refreshToken: string,
  ) {
    const refreshTokenDtoSend: RefreshTokenDto = { refreshToken, userId };

    return await this.authService.refreshToken(refreshTokenDtoSend);
  }

However, I never enter the JwtRefreshStrategy. Does anyone know why?

digital kelp
#

What's currently happening instead of entering the strategh?

sharp lagoon
#

Thank you, I realized that with GraphQL strategy configuration, specifically in the constructor it does not work with jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), but it should go like this:

constructor(
    @Inject(EnvConfig.KEY) private configService: ConfigType<typeof EnvConfig>,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([
        (request: Request) => {
          const token = request?.headers?.authorization
            ?.replace('Bearer ', '')
            .trim();

          return token;
        },
      ]),
      secretOrKey: configService.SECURITY.JWT_REFRESH_TOKEN,
      passReqToCallback: true,
    });
  }
#

I understand that this configuration is used for REST schemas, but in GraphQL it is done differently, if I am wrong please correct me.

woven jacinth
#

I'd highly suggest to create a REST endpoint for your refresh process. The reason being, the cookie you store the refresh token in can be set with the path of that endpoint, so the cookie only gets sent to that endpoint. Otherwise with what you are doing with GraphQl, you have to send the refresh token cookie with every request, which is not ideal.

sharp lagoon
#

I will always accept any improvement with pleasure, thank you

sharp lagoon