koa-oai-router-security

Auto security middleware loader for koa-oai-router

Usage no npm install needed!

<script type="module">
  import koaOaiRouterSecurity from 'https://cdn.skypack.dev/koa-oai-router-security';
</script>

README

koa-oai-security-middleware

Security middleware plugin for koa-oai-router

The middleware parse security entries from the Swagger schema and load the user's handlers for them.

Installation

npm

npm i --save koa-oai-security-middleware

yarn

yarn add koa-oai-security-middleware

Example

In this example, there is two kind of security in place: SessionCookie and ApiToken. The middleware is initialised with the handlers of the same name.

# ./api/paths/pets.yaml

/pets:
  get:
    description: "Returns all pets from the system"
    security:
      - SessionCookie:
        - MYSESSIONCOOKIE
    responses:
      "200":
        description: "pet response"
        schema:
          type: "array"
          items:
            $ref: "#/definitions/Pet"
/users:
  get:
    description: "Returns all users from the system"
    security:
      - ApiToken:
        - x-api-token
    responses:
      "200":
        description: "pet response"
        schema:
          type: "array"
          items:
            $ref: "#/definitions/Pet"
const Koa = require('koa');
const Router = require('koa-oai-router');
const securityPlugin = require('koa-oai-security-middleware');

const app = new Koa();
const router = new Router({
  apiDoc: './api'
});

router.mount(securityPlugin, {
  // Check if a required cookie is present
  SessionCookie: cookiesNames => {
    return (ctx, next) => {
      // Cookiesnames is an array
      (cookiesNames || []).forEach(cookieName => {
        // We only check if it's set here.
        ctx.assert(ctx.cookies.get(cookieName), 403, `Cookie "${cookieName}" missing`);
        // Here you can fetch the session from your session storage and set it on `ctx` for later access.
      });

      return next();
    };
  },

  // Validate a JWT
  ApiToken: tokenNames => {
    const jwt = require('jsonwebtoken');
    const ms = require('ms');

    return (ctx, next) => {
      // Token names is an array, even if there is only one name.
      (tokenNames || []).forEach(tokenName => {
        const token = ctx.headers[tokenName.toLowerCase()];
        ctx.assert(token, 403, `API token "${tokenName}" missing`);

        try {
          // Verify the JWT's signature and validity.
          const res = jwt.verify(token, config.get('JWT:pubkey'), {
            subject: ctx.url,
            issuer: config.get('JWT:issuer'),
            maxAge: config.get('JWT:maxAge')
          });

          ctx.assert(res.iat * 1000 - Date.now() < ms(config.get('JWT:futureAge')), 403, 'jwt `iat` is too far in the future');
        } catch (err) {
          ctx.throw(403, err);
        }

        // You can set anything on `ctx` here to access it within the route handlers
      });

      return next();
    };
  }
});

app.use(router.routes());