Using JWT Authentication with Swagger and Node.js

TL;DR: check the code on Github

I recently decided to use Swagger as the underlying technology for a Node.js REST API. Swagger (or it’s new “enterprise-friendly” OpenAPI branding) allows you to easily define a RESTful API using a JSON or YAML schema. Not only does it enforce you to follow all of REST’s best practices, it also provides a few very interesting tools that simplify the development process. A couple of examples are the Swagger Editor, that allows you to edit the API spec and see changes in real time, Swagger UI that automatically builds beautiful documentation, and Swagger Codegen, that generates the first version of the API endpoints’ code. Furthermore, there are many tools and integrations built for Swagger by its community.

While Swagger looked like a great fit for what I was looking for and everything started out nicely, some limitations soon became apparent. The first that I encountered is related to the use of JSON Web Tokens (JWT) for authentication purposes. Swagger’s specification allows for two types of mechanisms: OAuth, and what they call “apiKey”. Since JWT is definitely not OAuth, we have to use use “apiKey” to define that the JWT token will be sent in the HTTP Authorization header as “Bearer token_string“:

Furthermore, if we want to have different roles and manage the access to each API endpoint based on the user’s role, we will have to extend the Swagger spec, as it does not allow this for “apiKey” authentication. We can allow for role-based access as follows:

After the Swagger configuration is defined, we need to write the code to actually make this work. Here I will use Express and swagger-tools to care care of all the heavy lifting:

As you can see in line 13, the security checks are handed off to the verifyToken function in the auth module. Here is the code:

We just verify that the request presents a valid token (lines 21 through 27) and that the role of the user (which is saved in the token) matches one of the roles of the endpoint (line 13 and 29). The final piece of the puzzle is issuing a JWT with the user’s role as part of its payload:

Just return the token when the user correctly logs in, and you’re set:

And that’s basically it! All the code is available on Github, so feel free to check it out and test it for yourself.

  • Charlie Blackstock

    I cloned your repo and it doesn’t work…

    • Hi! I just updated the repo with a fix. Sorry for taking so long

    • Hi! I just updated the repo with a fix. Sorry for taking so long

      • Wojtek Hejna

        Hi, the code doesn’t work, the security middleware is ignored, it should be declared after the metadata middleware. I have created a pull request with that fix. The strange thing is that, the latest pull request seemed to be saying exactly the opposite thing:

        app.use(middleware.swaggerMetadata()); // needs to go after swaggerSecurity, otherwise using ‘Authorization’ header from swagger api_key doesn’t authenticate properly

        while debugging, you can see clearly that the security middleware is ignoring the operation:

        Started server on port 3000
        swagger-tools:middleware:ui GET /api/protected +18s
        swagger-tools:middleware:ui Will process: no +0ms
        swagger-tools:middleware:security GET /api/protected +0ms
        swagger-tools:middleware:security Will process: no +1ms

        • Hey Wojtek. I don’t have time to test your PR right now, but I went ahead and merged it. I will try to make sure it’s working later.