The thing that I struggled with the most when adding the login/authorization functionality was figuring out how to control the state in a global context and how to pass it on to the children components. Besides that, everything went smoothly.
The hardest part for the backend was figuring out how to make my tests compatible with the middleware that checked if a user currently has a token. Another hard part was figuring out how to add security features to the app as that is something that I have never done before.
I implemented several measures to prevent XSS attacks. Before the audit, I relied on input validation with Zod, and hoped for the default behavior of react to automatically escape values embedded in TSX/JSX. After the audit, I added the support of helmet to restrict which sources scripts can be executed from.
To mitigate CSRF attacks I have implemented several strategies. First was the use of CORS to control which domain can make requests to my server. I have also set the sameSite attribute on cookies to strict, this way cookies are only ever sent in the first-party context. The last change was also related to cookie settings as I added a httpOnly attribute which prevents client-sided scripts from accessing the cookies.
I used the rate limiter using the express-rate-limit. I added a basic implementation to limit any user to 100 requests within 10 minutes, and then provided a tighter policy for login/register pages with only 10 requests within 10 minutes.
I used the following headers: Content-Security-Policy which basically restricts sources of where scripts, styles, etc.. can be loaded from. This is useful as it restricts XSS attacks by only allowing resources to be loaded from trusted sources. Another header that I used was the Cross-Origin-Embedder-Policy which controls the embedding of cross-origin resources, which basically prevents unauthorized embedding of resources. The last header was Cross-Origin-Resources-Policy which controls the sharing of resources cross origins. It is useful as it helps to prevent data leaks as it restricts which origins can access the resources.
I don’t remember adding anything extra besides all that is mentioned above