fastify-swagger icon indicating copy to clipboard operation
fastify-swagger copied to clipboard

How could we automatically add schema.security when we add authorization requirements to a route?

Open tmcw opened this issue 1 year ago • 2 comments

What are you trying to achieve, or the steps to reproduce?

We're using some very basic fastify.decorateRequest and fastify.decorate calls to support bearer auth in our application:

fastify.decorateRequest("user", null);

fastify.decorate("bearerAuthOptional", async (request: FastifyRequest) => {
  request.user = await getAuth(request.headers.authorization);
});

As an example. Then in each route, we use a preHandler to run this decorator:

preHandler: fastify.auth([fastify.bearerAuthOptional]),

Now, we're generating OpenAPI with fastify/swagger, and it becomes necessary to tell API consumers which routes have which kinds of authentication. The code knows which routes do and don't, and we can repeat this information in the route-specific schema, but it'd be lovely to be able to have routes with auth automatically get a schema.security value.

I don't know how this is possible - preHandler, probably not. Maybe like a plugin that operates on each route?

Is there a kind of abstraction that can both add a preHandler hook and affect a route's schema in this way?

tmcw avatar May 29 '24 19:05 tmcw

Thanks for reporting. It would be great to add this feature somehow to fastify-swagger.

I'm moving this issue there.

mcollina avatar Jun 11 '24 15:06 mcollina

I've just tried this quick hack. The idea is to look in the route hooks for what you're using to authenticate requests. In this example I'm using @fastify/auth.

It's not well-tested but it might help someone until a proper solution is implemented.

const swaggerOptions: FastifyDynamicSwaggerOptions = {
openapi: { ... },
transform: (data) => {
      const onReq = data.route?.onRequest as
        | { name?: string }
        | { name?: string }[];
      const hooks = Array.isArray(onReq) ? onReq : [onReq];
      const hasAuthHook = hooks.some((hook) => hook?.name === "bound _auth");
      if (hasAuthHook) data.schema.security = [{ bearerAuth: [] }];
      return data;
    }
}

await fastify.register(require("@fastify/swagger"), swaggerOptions);

labarilem avatar Feb 20 '25 15:02 labarilem