This blog post has been created based on the Headless Security eBook – which aims to give modern builders security tips for headless web-apps.
Single Page Applications, JAM Stack, Headless: the features these architectures provide sound all too good. We’re told that we can now develop apps at two different speeds and, thus, experiment with new shiny frontend features. These applications are faster than ever and even include some native-like features – so-called Progressive Web Apps
With all the buzzwords and benefits being talked about, we came to the conclusion that there is just too little discussion of best practices. This is especially regarding security. Frontend applications are very often developed by dedicated frontend teams that never previously had to worry so much about security before. With the shift towards headless architecture, more and more business logic—especially including integrations with third-party systems—is now taking place in the frontend.
The times where you needed to worry about SQL Injection are probably gone. Now you query some API from Amazon, Azure, Firebase, Elastic, or MongoDB. However, there is a whole new set of issues and vulnerabilities we need to be aware of, including: API authorization, session handling, exposure of sensitive information, SSR caching, and so on.
Security tips for headless architecture
Tip 1: Always use HTTPS
Progressive Web Apps, by default, must be served from SSL-certified servers, using HTTPS protocol. It’s the only way to make the Service Workers work and we can only be sure via HTTPS that the data passed back and forth between Browser and the APIs is securely encrypted. This is especially important because of passing the customer’s / user’s tokens via HTTP Headers or request parameters.
Tip 2: Use tokens for API authorization
With SPAs, you always need to query some kind of API for a user’s data. Authorization is a key feature of an enterprise-grade application. If you remember the beginnings of web 2.0 and Web APIs back then, a typical authorization scenario was based on an API key or HTTP authorization. There are some strings attached. Basically, these “static” (API key) and not strongly encrypted (basic authorization) methods were not secure enough.
This is where delegated authorization methods come into play. By delegated, we mean that authorization can be given by an external system/identity provider. One of the first methods of providing such authentication was the OpenID standard (http://openid.net/) developed around 2005. It could provide a “One Login” and Single “Sign On” for any user. Unfortunately, it wasn’t widely accepted by identification providers like Google, Facebook, or email providers.
The OAuth standard works similarly to OpenID. The authorization provider allows Application Developers to register their own applications with the required data-scope to be obtained in the name of the user. The user authorizes specific applications to use with their account.
Tip 3: Follow the Express.js Security Best Practices
Most headless frontends are based on an Express.js HTTP server. Please make sure that you follow the Express.js Security Best Practices. There are great modules, like helmet, which are available out of the box and can be easily installed into your frontend app.
Tip 4: Use the API to query authorized data sources
The config file and any configurable properties you embed are publicly available to users. They’re bundled within the JS bundles or stored some other way in the browser. However, the config files used by Server-Side API endpoints are usually secret. They’re guaranteed not to be served to the client devices in any form.
For example, the Magento2 secret API keys (OAauth2) are stored in the vue-storefront-api configuration files and all the Magento2 API requests are done ONLY by vue-storefront-api – which is kind of a proxy-layer over the authorized Magento API.
You shouldn’t query any data source that requires a private key-based authorization from the Vue Storefront application directly.
There are two exceptions to this general rule:
- If the API key is public (e.g. it lets the user query only public information such as the product catalog)
- If there is a dynamic API key / JWT Token / any other form of token which is acquired by the user from the authorization service based on the credentials provided by the user (e.g. password/login). This token, of course, won’t be stored in the config file. This is how Vue Storefront passes the user tokens for requests like order history.
Tip 5: Consider using a Web Application Firewall
It’s usually a great idea to use an external line of control/filtering over your web application. Web Application Firewalls are the best defense in such cases. You can find a whole variety of different on-prem and cloud solutions like AWS WAF, Fortinet, and Nginx WAF. You can also try the open-source ModSecurity solution as well.
Get more security tips for headless builds
We love to talk about the benefits of headless, but we think it is important to discuss how to build safely while moving at speed and delivering great end-user experiences. Read more in the Headless Security eBook. It’s free to view and read right now and contains dozens of security tips for headless builds.