![](https://yourselfhood.com/storage/2024/02/1709195056react-cookies-sessions.jpg)
In this article, we’ll explore the implementation techniques and best practices for cookies and sessions in React.
Cookies and sessions are integral components of web development. They are a medium for managing user data, authentication, and state.
Cookies are small chunks of data (maximum 4096 bytes) stored by the web browser on the user’s device on behalf of the web server. A typical example of a cookie looks like this (this is a Google Analytics — _ga
— cookie):
<code class="bash language-bash">Name: _ga Value: GA1.3.210706468.1583989741 Domain: .example.com Path: / Expires / Max-Age: <span class="token number">2022</span>-03-12T05:12:53.000Z </code>
Cookies are only strings with key–value pairs.
“Sessions” refer to users’ time browsing a website. They represent the contiguous activity of users within a time frame.
In React, cookies and sessions help us create robust and secure applications.
In-depth Basics of Cookies and Sessions
Understanding the basics of cookies and sessions is foundational to developing dynamic and user-centric web applications.
This section delves deeper into the concepts of cookies and sessions, exploring their types, lifecycle, and typical use cases.
Cookies
Cookies mainly maintain stateful data between the client and the server across multiple requests. Cookies enable you store and retrieve data on the user’s machine, facilitating a more personalized/seamless browsing experience.
Types of Cookies
There are various types of cookies, and each works well for its intended use case.
-
Session Cookies are temporary and exist only for a user’s session duration. They store transient information, such as items in a shopping cart:
<code class="jsx language-jsx"> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; path=/"</span><span class="token punctuation">;</span> </code>
-
Persistent Cookies have an expiration date and remain on the user’s machine longer. They work for features like the “Remember Me” functionality:
<code class="jsx language-jsx"> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"username=JohnDoe; expires=Fri, 31 Dec 2023 23:59:59 GMT; path=/"</span><span class="token punctuation">;</span> </code>
Use cases of cookies in React
-
User Authentication. When us successfully login, a session token or JWT (JSON Web Token) is often stored in a cookie:
<code class="jsx language-jsx"><span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; path=/"</span><span class="token punctuation">;</span> </code>
-
User Preferences. Cookies commonly store user preferences, such as theme choices or language settings, for a better-personalized experience.
<code class="jsx language-jsx"> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"theme=dark; path=/"</span><span class="token punctuation">;</span> </code>
Sessions
Definition and purpose
Sessions represent a logical and server-side entity for storing user-specific data during a visit. Sessions are closely related to cookies but differ in storage; a session identifier often stores cookies on the client side. (The cookie data stores on the server.)
Server-side vs. client-side sessions
-
Server-side sessions involve storing session data on the server. Frameworks like Express.js use server-side sessions for managing user state:
<code class="jsx language-jsx"> <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express-session'</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span><span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> <span class="token string">'your-secret-key'</span><span class="token punctuation">,</span> resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
-
Client-side sessions. With client-side, sessions ensure there’s no need for replicating across nodes, validating sessions, or querying a data store. While “client-side sessions” might refer to session storage information on the client, it often involves using cookies to store session identifiers:
<code class="jsx language-jsx"> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; path=/"</span><span class="token punctuation">;</span> </code>
Understanding the nuances of cookies and sessions helps build dynamic and interactive web applications.
The coming section explores practical implementations of cookies and sessions in React applications.
Implementing cookies
As mentioned earlier, cookies are a fundamental part of the web process and a React application.
Ways of implementing cookies in React include:
- using the
document.cookie
API - creating custom hooks
- using third-party libraries
Using the document.cookie API
The most basic way to work with cookies in React is through the document.cookie
API. It provides a simple interface for setting, getting, and deleting cookies.
-
Setting a cookie:
<code class="jsx language-jsx"> <span class="token keyword">const</span> <span class="token function-variable function">setCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span> value<span class="token punctuation">,</span> days</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> expirationDate <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> expirationDate<span class="token punctuation">.</span><span class="token method function property-access">setDate</span><span class="token punctuation">(</span>expirationDate<span class="token punctuation">.</span><span class="token method function property-access">getDate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> days<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; expires=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>expirationDate<span class="token punctuation">.</span><span class="token method function property-access">toUTCString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; path=/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">setCookie</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">,</span> <span class="token string">"john_doe"</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
-
Getting a cookie:
<code class="jsx language-jsx"> <span class="token keyword">const</span> <span class="token function-variable function">getCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> cookies <span class="token operator">=</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token punctuation">.</span><span class="token method function property-access">split</span><span class="token punctuation">(</span><span class="token string">"; "</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token method function property-access">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> row<span class="token punctuation">.</span><span class="token method function property-access">startsWith</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword control-flow">return</span> cookies <span class="token operator">?</span> cookies<span class="token punctuation">.</span><span class="token method function property-access">split</span><span class="token punctuation">(</span><span class="token string">"="</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">:</span> <span class="token keyword null nil">null</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> username <span class="token operator">=</span> <span class="token function">getCookie</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
-
Deleting a cookie:
<code class="jsx language-jsx"> <span class="token keyword">const</span> <span class="token function-variable function">deleteCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>name<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">deleteCookie</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
Using custom hooks for cookies
Creating a custom React hook encapsulates cookie-related functionality, making it reusable across components:
<code class="jsx language-jsx"> <span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useState<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">useCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">cookieName</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>cookieValue<span class="token punctuation">,</span> setCookieValue<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> cookie <span class="token operator">=</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token punctuation">.</span><span class="token method function property-access">split</span><span class="token punctuation">(</span><span class="token string">"; "</span><span class="token punctuation">)</span> <span class="token punctuation">.</span><span class="token method function property-access">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">row</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> row<span class="token punctuation">.</span><span class="token method function property-access">startsWith</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cookieName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setCookieValue</span><span class="token punctuation">(</span>cookie <span class="token operator">?</span> cookie<span class="token punctuation">.</span><span class="token method function property-access">split</span><span class="token punctuation">(</span><span class="token string">"="</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>cookieName<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">setCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">value<span class="token punctuation">,</span> expirationDate</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cookieName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>value<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; expires=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>expirationDate<span class="token punctuation">.</span><span class="token method function property-access">toUTCString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; path=/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">deleteCookie</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>cookieName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword control-flow">return</span> <span class="token punctuation">[</span>cookieValue<span class="token punctuation">,</span> setCookie<span class="token punctuation">,</span> deleteCookie<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>username<span class="token punctuation">,</span> setUsername<span class="token punctuation">,</span> deleteUsername<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useCookie</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
This custom hook, useCookie
, returns the current value of the cookie, a function to set a new value, and a function to delete the cookie.
Using third-party libraries
Third-party libraries, such as js-cookie
, simplify cookie management in React applications.
-
Install the library:
<code class="bash language-bash"><span class="token function">npm</span> <span class="token function">install</span> js-cookie </code>
-
Usage in a React component:
<code class="jsx language-jsx"> <span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">React</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> useEffect <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">Cookies</span></span> <span class="token keyword module">from</span> <span class="token string">"js-cookie"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">MyComponent</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">set</span><span class="token punctuation">(</span><span class="token string">"user_token"</span><span class="token punctuation">,</span> <span class="token string">"abc123"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> expires<span class="token operator">:</span> <span class="token number">7</span><span class="token punctuation">,</span> path<span class="token operator">:</span> <span class="token string">"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> userToken <span class="token operator">=</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">get</span><span class="token punctuation">(</span><span class="token string">"user_token"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">logout</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">remove</span><span class="token punctuation">(</span><span class="token string">"user_token"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><span class="token plain-text">User Token: </span><span class="token punctuation">{</span>userToken<span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>logout<span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text">Logout</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword module">export</span> <span class="token keyword module">default</span> <span class="token maybe-class-name">MyComponent</span><span class="token punctuation">;</span> </code>
Using third-party libraries like js-cookie
provides a clean and convenient API for cookie management in React components.
Understanding these different approaches helps us choose the method that best fits the requirements and complexity of our React applications.
Implementing Sessions
In React applications, sessions work on the server side, and the session identifier works on the client side using cookies.
Ways of implementing sessions include:
- server-side sessions
- token-based authentication
Server-side sessions
Server-side sessions involve storing session data on the server. In React, it means using a server-side framework like Express.js along with a session management middleware.
-
Setting up Express.js with express-session:
First, install the required packages:
<code class="bash language-bash"><span class="token function">npm</span> <span class="token function">install</span> express express-session </code>
Now, configure Express:
<code class="jsx language-jsx"> <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"express"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> session <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"express-session"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span> <span class="token function">session</span><span class="token punctuation">(</span><span class="token punctuation">{</span> secret<span class="token operator">:</span> <span class="token string">"your-secret-key"</span><span class="token punctuation">,</span> resave<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> saveUninitialized<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
The
secret
signs the session ID cookie, adding an extra layer of security. -
Using sessions in routes:
On configuring sessions, we can use them in our routes:
<code class="jsx language-jsx"> app<span class="token punctuation">.</span><span class="token method function property-access">post</span><span class="token punctuation">(</span><span class="token string">"/login"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> req<span class="token punctuation">.</span><span class="token property-access">session</span><span class="token punctuation">.</span><span class="token property-access">user</span> <span class="token operator">=</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> username<span class="token operator">:</span> <span class="token string">"john_doe"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> res<span class="token punctuation">.</span><span class="token method function property-access">send</span><span class="token punctuation">(</span><span class="token string">"Login successful!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">get</span><span class="token punctuation">(</span><span class="token string">"/profile"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token property-access">session</span><span class="token punctuation">.</span><span class="token property-access">user</span><span class="token punctuation">;</span> <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>user<span class="token punctuation">)</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span> message<span class="token operator">:</span> <span class="token string">"Welcome to your profile!"</span><span class="token punctuation">,</span> user <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword control-flow">else</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token method function property-access">status</span><span class="token punctuation">(</span><span class="token number">401</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span> message<span class="token operator">:</span> <span class="token string">"Unauthorized"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
After a successful login, the user information stores in the session. Subsequent requests to the
/profile
route can then access this information.
Token-based authentication
Token-based authentication is a method for managing sessions in modern React applications. It involves generating a token on the server upon successful authentication, sending it to the client, and including it in the headers of subsequent requests.
-
Generating and sending tokens:
On the server side:
<code class="jsx language-jsx"> <span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"jsonwebtoken"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">post</span><span class="token punctuation">(</span><span class="token string">"/login"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> username<span class="token operator">:</span> <span class="token string">"john_doe"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> token <span class="token operator">=</span> jwt<span class="token punctuation">.</span><span class="token method function property-access">sign</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> <span class="token string">"your-secret-key"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">"1h"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> res<span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span> token <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
The server generates a JWT (JSON Web Token) and sends it to the client.
-
Including a token in requests:
On the client side (React):
<code class="jsx language-jsx"> <span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">React</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> createContext<span class="token punctuation">,</span> useContext<span class="token punctuation">,</span> useReducer <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token maybe-class-name">AuthContext</span> <span class="token operator">=</span> <span class="token function">createContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">authReducer</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword control-flow">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span><span class="token property-access">type</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token string">"LOGIN"</span><span class="token operator">:</span> <span class="token keyword control-flow">return</span> <span class="token punctuation">{</span> <span class="token spread operator">...</span>state<span class="token punctuation">,</span> isAuthenticated<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> token<span class="token operator">:</span> action<span class="token punctuation">.</span><span class="token property-access">token</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">case</span> <span class="token string">"LOGOUT"</span><span class="token operator">:</span> <span class="token keyword control-flow">return</span> <span class="token punctuation">{</span> <span class="token spread operator">...</span>state<span class="token punctuation">,</span> isAuthenticated<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> token<span class="token operator">:</span> <span class="token keyword null nil">null</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword module">default</span><span class="token operator">:</span> <span class="token keyword control-flow">return</span> state<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function"><span class="token maybe-class-name">AuthProvider</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> children <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>state<span class="token punctuation">,</span> dispatch<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useReducer</span><span class="token punctuation">(</span>authReducer<span class="token punctuation">,</span> <span class="token punctuation">{</span> isAuthenticated<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> token<span class="token operator">:</span> <span class="token keyword null nil">null</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">login</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">"LOGIN"</span><span class="token punctuation">,</span> token <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">logout</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">"LOGOUT"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword control-flow">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span><span class="token class-name">AuthContext.Provider</span></span> <span class="token attr-name">value</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> state<span class="token punctuation">,</span> login<span class="token punctuation">,</span> logout <span class="token punctuation">}</span><span class="token punctuation">}</span></span><span class="token punctuation">></span></span><span class="token plain-text"> </span><span class="token punctuation">{</span>children<span class="token punctuation">}</span><span class="token plain-text"> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span><span class="token class-name">AuthContext.Provider</span></span><span class="token punctuation">></span></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">useAuth</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> context <span class="token operator">=</span> <span class="token function">useContext</span><span class="token punctuation">(</span><span class="token maybe-class-name">AuthContext</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>context<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword control-flow">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">"useAuth must be used within an AuthProvider"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword control-flow">return</span> context<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword module">export</span> <span class="token exports"><span class="token punctuation">{</span> <span class="token maybe-class-name">AuthProvider</span><span class="token punctuation">,</span> useAuth <span class="token punctuation">}</span></span><span class="token punctuation">;</span> </code>
The above uses React Context to manage the authentication state. The
login
function updates the state with the received token. -
Using tokens in requests:
With the token available, include it in the headers of our requests:
<code class="jsx language-jsx"> <span class="token keyword module">import</span> <span class="token imports">axios</span> <span class="token keyword module">from</span> <span class="token string">"axios"</span><span class="token punctuation">;</span> <span class="token keyword module">import</span> <span class="token imports"><span class="token punctuation">{</span> useAuth <span class="token punctuation">}</span></span> <span class="token keyword module">from</span> <span class="token string">"./AuthProvider"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> api <span class="token operator">=</span> axios<span class="token punctuation">.</span><span class="token method function property-access">create</span><span class="token punctuation">(</span><span class="token punctuation">{</span> baseURL<span class="token operator">:</span> <span class="token string">"https://your-api-url.com"</span><span class="token punctuation">,</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> api<span class="token punctuation">.</span><span class="token property-access">interceptors</span><span class="token punctuation">.</span><span class="token property-access">request</span><span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">config</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> state <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useAuth</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword control-flow">if</span> <span class="token punctuation">(</span>state<span class="token punctuation">.</span><span class="token property-access">isAuthenticated</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> config<span class="token punctuation">.</span><span class="token property-access">headers</span><span class="token punctuation">.</span><span class="token property-access"><span class="token maybe-class-name">Authorization</span></span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Bearer </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>state<span class="token punctuation">.</span><span class="token property-access">token</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword control-flow">return</span> config<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword module">export</span> <span class="token keyword module">default</span> api<span class="token punctuation">;</span> </code>
When making requests with
Axios
, the token automatically works in the headers.Either methods help us manage sessions effectively, providing a secure and seamless experience.
Best Practices or Managing Sessions and Cookies in React
Handling sessions and cookies in React applications is vital for building secure, user-friendly, and performant web applications.
To ensure our React application works, do the following.
Securing cookies with HttpOnly and secure flags
Always include the HttpOnly
and Secure
flags where applicable.
-
HttpOnly
. The flag prevents attacks on the cookie via JavaScript or any other malicious code, reducing the risk of cross-site scripting (XSS) attacks. It ensures that cookies are only accessible to the server:<code class="jsx language-jsx"><span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; HttpOnly; path=/"</span><span class="token punctuation">;</span> </code>
-
Secure
. This flag ensures the cookie only sends over secure, encrypted connections (HTTPS). It mitigates the risk of interception by malicious users:<code class="jsx language-jsx"><span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; Secure; path=/"</span><span class="token punctuation">;</span> </code>
Implementing session expiry and token refresh
To enhance security, implement session expiry and token refresh properties. Regularly refreshing tokens or setting a session expiration time helps mitigate the risk of unauthorized access.
- Token refresh. Refresh authentication tokens to ensure users remain authenticated. It’s relevant for applications with long user sessions.
- Session expiry. Set a reasonable session expiry time to limit the duration of a user’s session. It helps protect against session hijacking.
<code class="jsx language-jsx"> <span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"express"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> jwt <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"jsonwebtoken"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> secretKey <span class="token operator">=</span> <span class="token string">"your-secret-key"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">generateToken</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">user</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword control-flow">return</span> jwt<span class="token punctuation">.</span><span class="token method function property-access">sign</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> secretKey<span class="token punctuation">,</span> <span class="token punctuation">{</span> expiresIn<span class="token operator">:</span> <span class="token string">"15m"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">post</span><span class="token punctuation">(</span><span class="token string">"/login"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> username<span class="token operator">:</span> <span class="token string">"john_doe"</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token function">generateToken</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> res<span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span> token <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">post</span><span class="token punctuation">(</span><span class="token string">"/refresh-token"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> refreshToken <span class="token operator">=</span> req<span class="token punctuation">.</span><span class="token property-access">body</span><span class="token punctuation">.</span><span class="token property-access">refreshToken</span><span class="token punctuation">;</span> <span class="token keyword">const</span> user <span class="token operator">=</span> <span class="token function">decodeRefreshToken</span><span class="token punctuation">(</span>refreshToken<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> newToken <span class="token operator">=</span> <span class="token function">generateToken</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> res<span class="token punctuation">.</span><span class="token method function property-access">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span> token<span class="token operator">:</span> newToken <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> app<span class="token punctuation">.</span><span class="token method function property-access">listen</span><span class="token punctuation">(</span><span class="token number">3001</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span> <span class="token console class-name">console</span><span class="token punctuation">.</span><span class="token method function property-access">log</span><span class="token punctuation">(</span><span class="token string">"Server is running on port 3001"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
The /login
endpoint returns an initial JWT token upon successful authentication. The /refresh-token
endpoint generates a new access token using a refresh token.
Encrypting sensitive data
Avoid storing sensitive information directly in cookies or sessions. To preserve sensitive data in unavoidable cases, encrypt them before storing. Encryption adds an extra layer of security, making it more challenging for malicious users to access sensitive information even if they intercept the data:
<code class="jsx language-jsx"> <span class="token keyword">const</span> sensitiveData <span class="token operator">=</span> <span class="token function">encrypt</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">sensitiveData=</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>sensitiveData<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">; Secure; HttpOnly; path=/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> </code>
Using the SameSite attribute
The SameSite
attribute helps protect against cross-site request forgery (CSRF) attacks by specifying when to send cookies with cross-site requests.
-
Strict. Cookies are sent only in a first-party context, preventing third-party websites from making requests on behalf of the user.
<code class="jsx language-jsx"><span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; Secure; HttpOnly; SameSite=Strict; path=/"</span><span class="token punctuation">;</span> </code>
-
Lax. Allows us to send cookies with top-level navigations (such as when clicking a link), but not with cross-site POST requests initiated by third-party websites:
<code class="jsx language-jsx"><span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"sessionID=abc123; Secure; HttpOnly; SameSite=Lax; path=/"</span><span class="token punctuation">;</span> </code>
Separating authentication and application state
Avoid storing the entire application state in cookies or sessions. Keep authentication data separate from other application-related states to maintain clarity and minimize the risk of exposing sensitive information:
<code class="jsx language-jsx"> <span class="token dom variable">document</span><span class="token punctuation">.</span><span class="token property-access">cookie</span> <span class="token operator">=</span> <span class="token string">"authToken=xyz789; Secure; HttpOnly; path=/"</span><span class="token punctuation">;</span> </code>
Utilizing third-party libraries for cookie management
Consider using well-established third-party libraries for cookie management. Libraries like js-cookie
provide a clean and convenient API, abstracting away the complexities of the native document.cookie
API:
<code class="jsx language-jsx"> <span class="token keyword module">import</span> <span class="token imports"><span class="token maybe-class-name">Cookies</span></span> <span class="token keyword module">from</span> <span class="token string">"js-cookie"</span><span class="token punctuation">;</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">set</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">,</span> <span class="token string">"john_doe"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> expires<span class="token operator">:</span> <span class="token number">7</span><span class="token punctuation">,</span> path<span class="token operator">:</span> <span class="token string">"</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> username <span class="token operator">=</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">get</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token maybe-class-name">Cookies</span><span class="token punctuation">.</span><span class="token method function property-access">remove</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code>
Regularly update dependencies
Keep third-party libraries and frameworks up to date to benefit from security patches and improvements. Regularly updating dependencies ensures that our application is less susceptible to known vulnerabilities.
Testing security measures
Perform regular security audits and testing on your application. It includes testing for common vulnerabilities such as XSS and CSRF. Consider using security tools and practices, like content security policies (CSP), to mitigate security risks.
Summary
Cookies and sessions are helpful tools for building secure and efficient React applications. They work for managing user authentication, preserving user preferences, or implementing stateful interactions.
By following best practices and using established libraries, we create robust and reliable applications that provide a seamless user experience while prioritizing security.
If you enjoyed this React article, check out these out awesome resources from SitePoint: