express-openapi-validator icon indicating copy to clipboard operation
express-openapi-validator copied to clipboard

validateSecurity to use custom errors

Open agavazov opened this issue 4 years ago • 2 comments

Is your feature request related to a problem? Please describe. I'm not able to throw custom errors in validateSecurity and handle them after that. I can see you are mapping the errors from the status code which eliminates previous throwed error (my custom errors) https://github.com/cdimascio/express-openapi-validator/blob/master/src/middlewares/openapi.security.ts#L112

Describe the solution you'd like

  • To provide an option like useCustomSecurityExceptions: true which will skip const err = HttpError error factory
  • Or to add something like this in HttpError.create like this (we will define custom errors which extend HttpError):
class HttpError extends Error {
    // ...
    static create(err) {
        if (err instanceof HttpError) {
            return err;
        }
        
        // ...
    }
}
  • Or to provide next in SecuritySchemes constructor (then we will be able to pass directly the errors, but this solution may create more problems with validateSecurity logic)
      const results = await new SecuritySchemes(
        securitySchemes,
        securityHandlers,
        securities,
        next
      ).executeHandlers(req);

Additional context index.js

const OpenApiValidator = require("express-openapi-validator");
const express = require("express");
const http = require("http");

const app = express();

class MyForbiddenError extends Error {
}

class MyUserError extends Error {
}

app.use(
  OpenApiValidator.middleware({
    apiSpec: "./openapi.yaml",
    validateSecurity: {
      handlers: {
        testKey: async (req, scopes, schema) => {
          let key = req.query.key;

          if (key !== "ok") {
            throw new MyForbiddenError("Wrong key value");
          }

          return true;
        },
      },
    },
  }),
);

app.get("/test", function(req, res, next) {
  throw new MyUserError("Everything is fine");
});

app.use((err, req, res, next) => {
  if (err instanceof MyUserError) {
    // OK
    res.status(200);
    res.send(`<h1>Error matches to MyUserError</h1>`);
  } else if (err instanceof MyForbiddenError) {
    // FAIL: YOU NEVER GET HERE
    res.status(403);
    res.send(`<h1>Error matches to MyForbiddenError</h1>`);
  } else {
    res.send(`<h1>Unknown error</h1>` + JSON.stringify(err));
  }
});

http.createServer(app).listen(3001);
console.log("http://127.0.0.1:3001/");

openapi.yaml

openapi: "3.0.0"
info:
  version: 1.0.0
  title: api-test-gateway
paths:
  /test:
    get:
      security:
        - testKey: [ ]
      description: Test authentication
      responses:
        "200":
          description: Some html content
          content:
            text/html:
              schema:
                type: string
components:
  securitySchemes:
    testKey:
      type: apiKey
      name: key
      in: query

agavazov avatar May 23 '21 18:05 agavazov

I'm not able to get custom security handlers to run at all: #539

stevenhair avatar Jun 08 '21 13:06 stevenhair