Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Undefined ctx.request.route when using Exception Filter with basic authorization handled by passport #2416

Open
1 task
cazeaux opened this issue Aug 29, 2023 · 3 comments
Assignees
Labels

Comments

@cazeaux
Copy link

cazeaux commented Aug 29, 2023

Information

  • Version: 7.34.6
  • Packages:

In the Exception Filter (using exactly the one documented here: https://tsed.io/docs/exceptions.html#exception-filter), in the catch methode, when we try to use the ctx.request.route parameter, we get undefined in the special situation where we catch an unauthorized exception.

So it happens with a basic authentication (using passport), and I observe 2 cases:

  • When the Authorization header is not set, the ctx.request.route is OK
  • When the Authorization header is set with wrong credentials, the ctx.request.route is undefined (but the ctx.request.url is OK)

Example

Exception filter

@Catch(Exception)
export class HttpExceptionFilter implements ExceptionFilterMethods {

  @Inject()
  metricsService: MetricsService

  // The catch does not change the TS.ED default behavior. It is intended to calculate metrics only.
  catch(exception: Exception, ctx: PlatformContext) {
    const error = this.mapError(exception);
    const headers = this.getHeaders(exception);

    // /!\ undefined when 401 error due to wrong credentials
    console.log(ctx.request.route?.toString());

    ctx.response.setHeaders(headers).status(error.status).body(error);
  }

  // Default mapError
  mapError(error: any) {
    return {
      name: error.origin?.name || error.name,
      message: error.message,
      status: error.status || 500,
      errors: this.getErrors(error)
    };
  }

  // Default getErrors
  protected getErrors(error: any) {
    return [error, error.origin].filter(Boolean).reduce((errs, { errors }: ResponseErrorObject) => {
      return [...errs, ...(errors || [])];
    }, []);
  }

  // Default getHeaders
  protected getHeaders(error: any) {
    return [error, error.origin].filter(Boolean).reduce((obj, { headers }: ResponseErrorObject) => {
      return {
        ...obj,
        ...(headers || {})
      };
    }, {});
  }
}

Basic Auth protocol

@Protocol({
  name: "basic",
  useStrategy: BasicStrategy,
  settings: {}
})
export class BasicProtocol implements OnVerify, OnInstall {

  async $onVerify(@Req() request: Req, @Arg(0) username: string, @Arg(1) password: string) {
    if (password !== "okpassword") {
      return false;
    }

    return true;
  }

  $onInstall(strategy: Strategy): void {
    // intercept the strategy instance to adding extra configuration
  }
}

Simple controller with auth

@Controller("/reproducebug")
export class TestController {
  @Get("/")
  @Authorize("basic")
  @Returns(200, String)
  async get_withid(@PathParams("id") id: string, @Res() response: any) {
    return "hello";
  }

Acceptance criteria

  • ctx.request.route should not be defined in case of authentication failure in the exception filter
@Romakita
Copy link
Collaborator

It's probably because the Auth check is processed by Passport and the middleware are executed before the endpoint itself. I'm not really a bug and I don't want to create an enhancement for that, because it will probably cause many refactor on the middleware orchestration.

And because you haven't create a repository to reproduce the bug, I won't take a time to do it myself due to the complexity of your exemple. In this specific case, a repo is helpful with an integration test (+ expectation), to not waste time to try to reproduce correctly your issue.

See you ;)
Romain

@cazeaux cazeaux changed the title [BUG] Title [BUG] Undefined ctx.request.route when using Exception Filter with basic authorization handled by passport Aug 30, 2023
@cazeaux
Copy link
Author

cazeaux commented Aug 30, 2023

Hello

Thank you for your answer.
You can go to https://github.com/cazeaux/tsed-express-issue-passport repository to reproduce the behavior that I have observed.
I hope it helps.

Stéphane.

@Romakita
Copy link
Collaborator

Romakita commented Sep 2, 2023

Hello @cazeaux
You can get the ctx.request.url instead ;).

If route isn't defined, it means the middleware isn't executed during the endpoint context.

See you
Romain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants