Authentication Persistence

The previous post within this blog series discussed how the authentication system within the React application works, however stated that the persistence of this login state would be covered in another post. In this post the persistence of a users logged in state will be covered, along with some issues that were discovered that led to certain design decisions being made.

Authentication State Storage Options

As previously discussed, the authentication system used within the application uses JSON Web Tokens, however the application requires somewhere to store the token. This functionality is made available by the JWT Auth(Useful Team, n.d.) plugin through the WordPress plugins catalogue. There are three locations the token can be stored, however each location brings its own unique advantages and disadvantages. 

Stored In Memory

By storing the token in memory, memory meaning a JavaScript variable, other tabs and web pages can not access the token. This approach however has one major drawback where if the user opens a new tab or the page gets refreshed then the login session is lost and the user will have to re-authenticate. 

This approach works well if this loss of login state is not a concern. For many applications this approach is completely unsuitable, however can be used for things like banking applications where storing login details in non volatile memory is a huge risk.

Stored Within LocalStorage

Storing the JWT within LocalStorage makes the token available across tabs and sessions, meaning login state can be persisted in multiple different scenarios. This approach is susceptible to XSS attacks which is one of the most common forms of web attacks(PortSwigger, 2019). 

Stored Within A Cookie

Storing the JWT within a cookie is certainly a valid option. The cookie will be sent with every subsequent request, however one major drawback is that this approach is susceptible to Cross Site Request Forgery(CSRF) attacks(KirstenS, n.d.). This is because cookies are automatically sent with every request to the domain for which they are set. WordPress by default uses cookie based authentication, however it pairs this technique with a nonce that acts like an anti CSRF-Token. This technique can not be used when the page is not sent directly from WordPress.

Due to the inability to set cross site cookies, storing the JWT within a cookie is the more desirable than storing it within LocalStorage as the plugin requires the token to be sent in an Authorization header and not in a cookie. This means malicious websites can not force an authenticated client to send authorised requests to the WordPress server. For these reason, cookies are the most suitable storage mechanism for the JWT.

Adopted Approach

Cookies were used to persist the authenticated state of a user across sessions. The applications is able to read the users cookies when the page first loads, and therefore allows the application to persist login state. When the page is loaded the token is extracted from the browsers cookies and placed within a React context which can then be used throughout the entire application.

A custom hook was created to handle the login and logout client side logic, adding or deleting the cookie. The described hook can be seen below.

Implementation Details

Once successfully logged in the NextJs application encapsulates the login response into a React Context, making the context available throughout the application so that the token can be accessed on different pages.

The type definitions for the React Context used for storing the login state in memory can be seen in the above screenshot.

The following screenshot shows the _app.tsx files contents and how the context is made available throughout the entire virtual DOM using the AuthContext.Provider component. The same code extract shows how the page retrieves the cookie values upon page load and updates the context values.

Additional information like the users display name can also be retrieved from this context and displayed to the user. The following screenshot shows this context being consumed with the useContext hook. The contents of this context are then inspected and the values are used to determine what should be rendered using TSX conditional rendering.

This post discussed issues encountered with authentication when using WordPress as a headless CMS. Certain security tradeoffs must be used as any ability to use techniques such as CRSF tokens are unavailable. 

Concluding Remarks

When using the WordPress REST API combined with the JWT Auth plugin, storing the login details retrieved from a successful authentication attempt can be done using cookies. As the JWT Auth plugin does not read cookie data to authorise actions other websites can not exploit the automatic sending of cookies to perform actions the legitimate user did not intend for.

References

KirstenS (n.d.). Cross Site Request Forgery (CSRF) | OWASP. [online] owasp.org. Available at: https://owasp.org/www-community/attacks/csrf.

PortSwigger (2019). What is cross-site scripting (XSS) and how to prevent it? [online] Portswigger.net. Available at: https://portswigger.net/web-security/cross-site-scripting.

Useful Team (n.d.). JWT Auth – WordPress JSON Web Token Authentication. [online] WordPress.org. Available at: https://wordpress.org/plugins/jwt-auth/ [Accessed 6 Apr. 2021].

Comments

Popular posts from this blog

WordPress Modifying A Child Theme & Using The OpenWeatherMap API

Creating A WordPress Post Using The REST API

Consuming The WordPress Posts Via The REST API