Blog
Security Headers in Next.JS

Security Headers in Next.JS

To ensure your site is protecting its users. several security headers can be set to help prevent certain attacks against websites.

For Next.JS these are set in the next.config.js file. Typically I use the following config.

1/** @type {import('next').NextConfig} */
2const nextConfig = {
3 async headers() {
4 return [
5 {
6 source: '/:path*',
7 headers: [
8 {
9 key: 'X-Frame-Options',
10 value: 'SAMEORIGIN',
11 },
12 {
13 key: 'Content-Security-Policy',
14 value: "frame-ancestors 'none'",
15 },
16 {
17 key: 'Referrer-Policy',
18 value: 'same-origin',
19 },
20 {
21 key: 'Strict-Transport-Security',
22 value: 'max-age=15768000',
23 },
24 {
25 key: 'X-Content-Type-Options',
26 value: 'nosniff',
27 },
28 {
29 key: 'X-XSS-Protection',
30 value: '1; mode=block',
31 },
32 ],
33 },
34 ];
35 },
36};
37
38module.exports = nextConfig;
39

Content-Security-Policy

Setting frame-ancestors: none is similar to X-Frame-Options and will prevent a site loading in an ancestor frame, iframe. object or embed.

X-Frame-Options

Indicates whether a browser should be allowed to render a page in a frame, iframe, embed or object tag. By setting to SAMEORIGIN this ensures the site is only rendered in this way on itself and not on other sites.

Click-jacking attacks commonly use display other sites within themselves to fool a user as to what site they are on.

Referrer-Policy

Referrer Policy sets how much information is sent with the referrer header. By setting to same-orign, the referrer header is only sent on same origin requests.

Strict-Transport-Security

This header instructs the browser to only access the site over https. By setting the age it instructs the browser to remember this setting for the number of seconds given.

X-Content-Type-Options

Setting to nosniff will block a request if the destination is of type style and the MIME type is not text/css, or of type script and the MIME type is not a JavaScript MIME type.

X-XSS-Protection

This is a non-standard header and isn't supported in any current browsers but has history support with Chrome and Edge.

The header instructs the browser how to handle any cross-site scripting attacks it detects on the page. Setting to 1; mode-block will prevent the page from rendering if an attack is detected.

Knowing what type your object is in C# 8

Knowing what type your object is in C# 8

If your familiar with object oriented programming then you'll know one of the advantages is classes can be designed to inherit from base classes to avoid duplication in your code. In fact in C# all classes ultimately inherit from the base class object. So if you had a list of objects, it would be valid that any object could be added to the list.

Lets look at a scenario of a library where people can borrow Books, DVDs and Games. All will have a Title and Barcode, but each type will also have some more specific properties.

1public class BaseClass
2{
3 public string Name { get; set; }
4 public string Barcode { get; set; }
5}
6
7public class Book : BaseClass
8{
9 public int Pages { get; set; }
10}
11
12public class DVD : BaseClass
13{
14 public int RunningTime { get; set; }
15}
16
17public enum GameConsole
18{
19 Playstation,
20 Xbox
21}
22
23public class Game : BaseClass
24{
25 public GameConsole Format { get; set; }
26}

Those are some classes. Some example data for a members borrowings could be like this.

1List<BaseClass> membersLoans = new List<BaseClass>();
2membersLoans.Add(new Book() { Name = "A Christmas Carol", Barcode = "123", Pages = 210 });
3membersLoans.Add(new DVD() { Name = "Wonka", Barcode = "124", RunningTime = 180 });
4membersLoans.Add(new Game() { Name = "Alan Wake 2", Barcode = "125", Format = GameConsole.Xbox });

Now we have a list of what a member has borrowed we can output the list using a foreach loop.

1foreach (var item in membersLoans)
2{
3 Console.WriteLine(item.Name);
4}
5
6/*
7Ouput
8------------------------
9A Christmas Carol
10Wonka
11Alan Wake 2
12 */

That's a list of the titles, but what if we want to add more info such as the type and some of the details from that type. These are outside the properties of BaseClass so we will need some way of knowing what type of object item is and then cast to that object.

Type checking in C# using 'is'

The is keyword can be used to determine if an instance of an object matches a pattern, such as an object type or null. We can use some if else statements check what are type is.

1foreach (var item in membersLoans)
2{
3 if (item is Book)
4 {
5 Console.WriteLine($"{item.Name}, {((Book)item).Pages} pages");
6 }
7 else if (item is DVD)
8 {
9 Console.WriteLine($"{item.Name}, {((DVD)item).RunningTime}mins");
10 }
11 else if (item is Game)
12 {
13 Console.WriteLine($"{item.Name}, {((Game)item).Format}");
14 }
15}
16
17/*
18Ouput
19------------------------
20A Christmas Carol, 210 pages
21Wonka, 180mins
22Alan Wake 2, Xbox
23 */

Type checking using switch

With C# 7 switch expressions become more lightweight and now also support patterns, so rather than all those if else statements, we can combine them all into one simple switch.

Unlike a traditional switch statement the switch returns a result, the case keyword is removed, colons are replaced with =>, and the default keyword is replaced with an underscore.

1foreach (var item in membersLoans)
2{
3 var result = item switch
4 {
5 Book => $"{item.Name}, {((Book)item).Pages} pages",
6 DVD => $"{item.Name}, {((DVD)item).RunningTime}mins",
7 Game => $"{item.Name}, {((Game)item).Format}",
8 _ => item.Name,
9 };
10 Console.WriteLine(result);
11}
12
13/*
14Ouput
15------------------------
16A Christmas Carol, 210 pages
17Wonka, 180mins
18Alan Wake 2, Xbox
19 */

That's all there is to it. We can now mix our objects together and work out what's what as simply as checking the value of a property.

Storybook + NextJs with TypeScript Paths set

Storybook + NextJs with TypeScript Paths set

Previously I have written about making your code neater by using TypeScript paths. Since then I have found that the NextJs create app Wizzard now asks you about setting this, so that from the get-go you will now likely start with it set in an application and have neater code for the better.

However, if you then try using Storybook then you're likely to see an error Module not found: Error: Can't resolve '@/components...' on any component that has an import using one of the paths.

Storybook error relating to paths

Quite simply, Storybook does not pick up the setting in your tsconfig.json file and it has no idea where to import the module from.

To get around this issue we need to also tell Storybook about the paths we've set in .storybook\main.ts. We do this by adding a resolve alias to the config returned by webpackFinal. The code example here sets an alias that will match the default path set by NextJs in its create app wizzard.

1import type { StorybookConfig } from "@storybook/nextjs";
2import path from "path";
3
4const config: StorybookConfig = {
5 // Other config removed for clarity
6 webpackFinal: async (config, { configType }) => {
7 if (!config.resolve) {
8 return config;
9 }
10
11 config.resolve.alias = {
12 ...config.resolve.alias,
13 "@": path.resolve(__dirname, "../src"),
14 };
15
16 return config;
17 },
18};
19export default config;
20

Of course if you have other paths set then you can add them here as well. When you next run storybook the error should be gone and your components now show in Storybooks UI.

Checking Auth0 Roles and Permissions with a React SPA

Checking Auth0 Roles and Permissions with a React SPA

With Auth0 you can set up a completely SAAS-based Authentication and Authorization provider, freeing you of any worries surrounding losing passwords, implementing the latest authentication best practices and a whole heap of other things.

One thing that tripped me up with it, however, was checking what permissions have been assigned to my users.

In my setup, I was using a .NET Core Web API hosted in Azure and a React SPA hosted separately. My API would need to check the permissions assigned to my users in order to check they could perform actions such as updating another user, and my React front end would need to show and hide various pieces of functionality to match.

Checking Permissions in the .NET Core Web API

This article isn't about permissions in APIs but it's important to understand how this differs too what's needed in the React front end.

The tutorial ASP.NET Core Web API v2.1: authoization is relatively straightforward to follow and at the end, you will have an API that performs Authorization with a user's permissions.

Permissions in Auth0 are assigned to users via roles. i.e. A user gets assigned a role and roles have related permissions. This way we can design our application around granular permissions and the roles which give those permissions to a user can be configured separately.

The permissions are provided to the API within the user's authentication token, however for this to work they actually have to be in the token to start with. By default roles and permissions are not included in a token.

These can be included by setting the scope property when calling getAccessTokenSilently (the function to get a token) in React.

1const token = await getAccessTokenSilently({
2 authorizationParams: {
3 audience: 'https://api.example.com/',
4 scope: 'read:posts',
5 },
6});
7const response = await fetch('https://api.example.com/posts', {
8 headers: {
9 Authorization: `Bearer ${token}`,
10 },
11});

Alternatively, you can Enable Role-Based Access Control for APIs. This will increase the size of your token by including all permissions assigned to the person, but removes the need to request them.

Checking Permissions in React

It's likely that before calling an API you will want your React logic to check the users permissions. After all, it wouldn't be a great user experience if they're allowed to perform actions which result in permission errors.

As well as the getAccessTokenSilently the useAuth0 React Hook contains a property for the user and getIdTokenClaims. When using these you will be able to see the details associated with the logged in user. e.g. Name. However unlike getAccessTokenSilently, it doesn't matter what you include in the scope or if you've enabled role-based access control, the properties will not include what permissions or roles are assigned to the user.

To include them you must setup a login action to add them to the token. See Add user roles to ID and Access tokens in Auth0's documentation.

This will direct you to create a login flow where you add a custom action containing the following.

1/**
2 * @param {Event} event - Details about the user and the context in which they are logging in.
3 * @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
4 */
5exports.onExecutePostLogin = async (event, api) => {
6 const namespace = 'https://my-app.example.com';
7 if (event.authorization) {
8 api.idToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
9 api.accessToken.setCustomClaim(`${namespace}/roles`, event.authorization.roles);
10 }
11}

Note, the namespace part is so that what you add to the token is unique and doesn't clash with anything Auth0 is adding.

You can now follow these examples to perform a claims checks on the user. E.g.

1import { User } from '@auth0/auth0-react';
2
3function checkClaims(claim?: User, role?: string) {
4 return claim?.['https://my-app.example.com/roles']?.includes(role);
5}
6
7export default checkClaims;

This as you may have spotted is only assigning a role to the token rather than actual permissions. In my case, this was enough, however, this is one area I think the react hook is severely lacking.

Writing custom logic to set a users permissions into the set of claims feels highly wrong, but after some back and forth with Auth0's support team, for now though this appears to be the only option.