Skip to content

X-API-KEY header is not being attached via swagger UI #264

Open
@JPStrydom

Description

@JPStrydom

I'm following Feather's API key auth strategy as listed here. My application only has API key auth and no other auth stratagies.

I've set up my API key to be read from the header field x-api-key and when running through Postman, the API key auth works as expected. With a correct x-api-key field in a request header, the request authenticates as expected.

I'm struggling to get the Swagger UI to send the header through, even though it looks like it's configured correctly.

My authentication is set up like this:

import { AuthenticationBaseStrategy, AuthenticationService } from '@feathersjs/authentication';
import { NotAuthenticated } from '@feathersjs/errors';

import { services } from '#src/enums';

class ApiKeyStrategy extends AuthenticationBaseStrategy {
  app;

  constructor(app) {
    super();
    this.app = app;
  }

  async authenticate(authentication) {
    const { apiKey } = authentication;

    const { total } = await this.app.service(services.API_KEYS).find({ query: { apiKey, $limit: 0 } });

    const hasAccess = total === 1;

    if (!hasAccess) {
      throw new NotAuthenticated('Incorrect API Key');
    }

    return { apiKey: true };
  }
}

export const authentication = app => {
  const authentication = new AuthenticationService(app);

  authentication.register('apiKey', new ApiKeyStrategy(app));

  // Not sure if I need to configure Swagger for the authentication here?

  app.use('authentication', authentication);
};

My Swagger instance is configured like this:

import feathersSwagger from 'feathers-swagger';

export const swagger = app => {
  const title = app.get('title');
  const description = app.get('description');
  const version = app.get('version');

  app.configure(
    feathersSwagger({
      prefix: /^(api|commands|subscriptions)\//,
      specs: {
        info: { title, description, version },
        components: { securitySchemes: { ApiKeyAuth: { type: 'apiKey', in: 'header', name: 'x-api-key' } } },
        security: [{ ApiKeyAuth: [] }]
      },
      include: { paths: ['api', 'commands', 'subscriptions'] },
      ui: feathersSwagger.swaggerUI()
    })
  );
};

These are then configured in my app.js file like so:

app.configure(swagger);
app.configure(authentication);  
app.configure(api); // Configure all /api/xxx endpoints
app.configure(commands);  // Configure all /commands/xxx endpoints
app.configure(subscriptions); // Configure all /subscriptions/xxx endpoints

My endpoints are each configures like this:

import { authenticate } from '@feathersjs/authentication';
import { hooks as schemaHooks } from '@feathersjs/schema';
import swagger from 'feathers-swagger';

import { claims, methods, services } from '#src/enums';

import { ApiKeysService, getOptions } from './api-keys.class.js';
import { apiKeysDocs } from './api-keys.schema.js';

const path = services.API_KEYS;
const allowedMethods = [methods.FIND, methods.GET, methods.CREATE, methods.PATCH, methods.REMOVE];
const apiKeyDocs = swagger.createSwaggerServiceOptions({
  schemas: { 
    // ...
  },
  docs: {
    description: 'An API key REST service',
    securities: ['ApiKeyAuth']
  }
});

export const apiKeys = app => {
  app.use(path, new ApiKeysService(getOptions(app)), {
    methods: allowedMethods,
    events: [],
    docs: apiKeysDocs
  });
  app.service(path).hooks({
    // ...
  });
};

In the Swagger UI, I can see the correct authentication UI:
image

But when making requests whilst authentication, the header doesn't appear to be attached to the request:
image

I've tried setting cors in my app.js like so, but the x-api-key request header is still not being set:

app.use(
  cors({
    origin: '*', // Adjust based on your security needs
    allowedHeaders: ['x-api-key', 'Content-Type']
  })
);

Does anyone know what I'm missing? Would really like to be able to test the API via the Swagger UI.

Bonus question: Is there a way I could have my sub-endpoints (/api/, /commands/, /subscriptions/) grouped together in Swagger UI, so that I could collapse them independently? I've tried using tags, but these set all the /api/ endpoints under one tag

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions