An authentication strategy for restful data and application interfaces built with Fastify.

Dennis Bauszus

Fastify is a low overhead web framework for node.js. We can not provide definitive benchmarks in terms of performance but have chosen Fastify as our framework (web server & router) of choice for its developer friendliness and extensive plugin ecosystem.

The authentication strategy outlined in this article may probably be applied to other web frameworks which facilitate node middleware (e.g. Express, Hapi, Restify, Koa). Code examples are reducted from the XYZ repository for which this authentication strategy was designed. Please consult the Fastify pages for implementation specific details on decorators, hooks, handler, route schema validation & serialization.

XYZ is an open source spatial data and application interface in active development at GEOLYTIX. Once deployed, the middleware will expose a RESTful API as well as a client library which interacts with the hosted API. A responsive view is returned from the XYZ root endpoint. The script provided with this view expands the capabilities of the XYZ control bundle and wires its API methods to a browser interface.

Authentication strategy, Rules, and Security.

Authentication is a key component for the overall security strategy at GEOLYTIX.

Successful authentication grants to a client roles for access of data available to the XYZ backend. Having 3rd party API keys and PostgreSQL user credentials stored as environment variables the node process acts as proxy to external services and data sources.

Rules define which roles are required for individual endpoints, how these roles can be obtained, and securely transferred from the client to the host.

Starting with the obvious the three cardinal rules for our authentication strategy are:

  1. A client must be able to securely log in to the system to access data.
  2. Roles must be available to discern data access and administrative tasks.
  3. Anonymous access must be provided for public facing interfaces.

Registering, verifying, and approving user accounts.

User accounts are stored in the Access Control List (ACL), a PostgreSQL table.

Registration is the first step to create a new user account. A valid email address must be associated with every new account.

Following a link with a verification token which is sent to the registered email address a user verifies his identity as the owner of the email account.

Once an account has been verified an approval token is sent to all administrators asking them to either approve (or block) the account.

The user can now log on to the system.

Password resets are achieved by repeating the verification process. A new passwords is confirmed after the user confirms the receipt of the verification token.

Failed logins result in an account being locked. Repeating the verification process will unlock the account.

Administrator may assign roles such as the admin role itself to other user accounts. They can also block an account. A blocked account can no longer be verified and will thus restrict the use of the same email address to gain access to the system.

Who ate all the session cookies?

The hyper text protocol being stateless makes secure authentication and session management one of the most daunting features to develop. Even more so with the restrictions of a serverless architecture where subsequent requests maybe routed to different process spawns.

Authentication is possible by checking an id against a stored session and/or by validating a signature against a secret available to the middleware.

The XYZ framework does not require sessions and we decided against the use of cookies.

Authentication is ensured through the verification of JWT signatures. Every non-public request to the middleware must provide a signed token as querystring parameter.

The fastify-jwt plugin provides an implementation of the JOSE framework; A series of standards for the encryption and signature of arbitrary data token. The token’s payload contains the email and roles associated with the user account.

Anatomy of a fastify route.

Within a node process, request and response will traverse a series of layers. These layers, the node middleware, are often compared to an onion.

Middleware and hooks allow us to inject a security strategy into the Fastify lifecycle using existing plugins.

Requests for the application view from root route handler must pass through a preValidation hook. At this stage the authToken function is called by the fastify-auth plugin. Public as well as requests with verified token are routed to the root handler which returns an application view to the client.

If not validated a login view will be returned to the client. The submit action of the login form will post the credentials (email / password) to the root route which attaches the root handler to the request object before being validated by the login handler.

The root handler is returned from the login handler once the credentials from the request object are validated against the access control list (ACL). This will return the view from the root handler to the client.

Before returning to the client the root handler will render the signed token as a data-attribute into the document body of the view.

Non-login routes

API routes will not return a login view. If not public, missing, or failing to verify a token the request will respond with a 401 error code.

Passing preValidation, the route schema will be validated.

Request parameter are further validated in the preHandler hook to prevent the handler failing, protect against SQL injections, and check role access against a lookup set in the process’ workspace.

The preHandler hook allows to pass the request object through a chain of custom fastify decorators.

authToken

Fastify-auth does not provide an authentication strategy. The strategy, defined in the authToken function will be assigned to the fastify-auth module as a decorator.

The request and response object are passed through the authToken method.

At points of failure an Error (401) with the appropriate message is returned as a response to the client.

The request is passed on to the route validation if the token authorization is successful.

preValidation hooks may pass an access object as 4th parameter to authToken. The access parameter defines whether a route should respond with a login view, requires administrative credentials, or is public.

If public, as defined by environment variables, authToken may immediately forward the request. Otherwise fastify-jwt must verify the token signature against an environment secret.

API-keys

The XYZ host may issue API keys. A single API key may be assigned to a user account in the ACL.

API keys do not expire!

API keys may never be used for administrative tasks.

After verification, authToken will query the ACL for the user account associated with the key. A new token with user roles, but an expiry of 10 seconds only, will be signed and replaces the API key token on the request object.

Let her rip…

With this being said we can finally look at the Fastify startup. Node will execute server.js in which the Fastify process is declared.

Alongside the aforementioned modules, fastify-helmet is registered with directives for the http server’s content security policies (CSP).

A logger is defined, plugins are registered, and decorators for parameter evaluation, login view/handler, as well as authToken are set.

Finally Fastify may listen to requests from the client…

I hope this article may be helpful whether you work with Fastify or develop a security strategy for a different framework. Any comments and especially concerns are welcome on the appropriate channels. Please open an issue in the XYZ github repository with any comments in regard to the authentication strategy.

Watch this space and follow us on twitter (Dennis Bauszus) for XYZ updates and exciting career opportunities with GEOLYTIX.

Please contact info@geolytix.co.uk for any business inquiries.

Dennis Bauszus

Written by

I am doing some web and map stuff with @GEOLYTIX. Mostly maps on the web. https://GEOLYTIX.net/?geodata

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade