Skip to main content

Client Side Security

Client-side security means protecting the data, tokens, sessions, and browser storage used by a frontend application.

In the browser, data can be stored in places like localStorage, sessionStorage, IndexedDB, cookies, and cache storage.

Frontend App -> Browser Storage -> Tokens / Session Data / Cached Data

The main idea is simple:

Do not trust the client completely.
Store less data.
Protect what must be stored.
Expire sensitive values.
Verify that data was not changed.

One-line idea: Client-side security means storing less sensitive data in the browser, protecting what must be stored, expiring tokens, validating integrity, respecting storage limits, and managing sessions safely.

Core Concepts​

Why It Matters​

Client-side storage is useful, but it can become risky if sensitive data is stored carelessly.

Examples of sensitive data:

  • passwords
  • tokens
  • session IDs
  • personal user data
  • payment-related data
  • identity-related data

If this data is exposed or modified, it can affect the user account, application security, and data correctness.

AreaWhy It Matters
Sensitive data storageBrowser storage can be inspected or misused
AuthenticationTokens and sessions must be controlled properly
Data integrityStored data should not be changed silently
Storage limitToo much client-side data can hurt performance or cause data loss
Session managementSessions and cookies must be handled safely

Core Flow​

Need to store data in browser?
↓
Check if it can stay on the server
↓
If client storage is required
↓
Store only required data
↓
Encrypt sensitive data if needed
↓
Set token/session expiry
↓
Verify data integrity
↓
Check storage usage and quota
↓
Manage session cookies safely

Main Security Goals​

Client-side security mainly focuses on five important goals.

GoalSimple MeaningMain Practice
Sensitive Data ProtectionAvoid exposing private data in the browserPrefer server storage, encrypt if required, set expiry
Authentication SafetyLogin/session should be secureUse JWT/OAuth/OIDC, session expiry, and MFA
Data IntegrityData should not be changed secretlyUse checksum or integrity checks
Storage ControlBrowser storage should not exceed limitsTrack usage and avoid storing too much data
Session ManagementSessions and cookies should be safeUse proper cookie flags and server-managed sessions

Practical Examples​

Sensitive Data Storage​

The safest rule is:

Try to store sensitive data on the server first.

Client storage should only contain data that is actually required by the frontend.

Bad example:

localStorage.setItem("password", "mySecretPassword");

This is unsafe because the browser is not a fully trusted place.

Better example:

const sensitiveData = "cached-profile-data";
const encryptedData = encryptFunction(sensitiveData);

localStorage.setItem("encryptedData", encryptedData);

This is better than storing raw data, but it does not make client storage completely safe. Do not store passwords in browser storage, even encrypted, because client-side keys and code can be exposed.

Encryption reduces risk.
Server-side storage is still safer for truly sensitive data.

Token Expiry​

Tokens should not remain valid forever.

If a token is stored on the client, it should have a short expiration time so the risk window is smaller.

const token = generateToken();
const tokenExpirationTime = 15 * 60 * 1000; // example: 15 minutes

localStorage.setItem("token", token);

setTimeout(() => {
localStorage.removeItem("token");
}, tokenExpirationTime);

Simple idea:

Token created -> token stored -> token expires -> token removed/invalidated

Client-side removal is only local cleanup. The token must also expire or be invalidated on the server side.

Without Token ExpiryWith Token Expiry
Token may stay usable for a long timeToken becomes unusable after a fixed time
Higher risk if token is leakedLower risk window
Session may stay active unnecessarilySession is controlled better

Authentication​

Authentication should use standard and secure mechanisms.

The PDF highlights:

  • JWT/OAuth or OpenID Connect depending on the login flow
  • session token expiry
  • MFA, meaning multi-factor authentication
User logs in
↓
Server verifies user
↓
Server issues token/session
↓
Client stores only what is required
↓
Token/session expires after a fixed time

MFA adds another layer of security because the user needs more than just a password.

Password only -> weaker
Password + MFA -> stronger

Data Integrity​

Data integrity means data has not been changed in an unauthorized way.

It applies to data:

  • in storage
  • during processing
  • while in transit

Simple meaning:

Data integrity = data is still the same as expected

For browser storage, this means we may need to verify whether stored data was modified.

Checksum for Data Integrity​

A checksum can be used to check whether stored data changed accidentally. For security against tampering, use a keyed MAC/signature or server-side verification because an attacker who can edit client storage may also edit a plain checksum.

const dataToStore = "myData";
const checksum = calculateChecksum(dataToStore);

localStorage.setItem("data", dataToStore);
localStorage.setItem("checksum", checksum);

const storedData = localStorage.getItem("data");
const storedChecksum = localStorage.getItem("checksum");

if (calculateChecksum(storedData) === storedChecksum) {
console.log("Data integrity is intact");
} else {
console.log("Data may have been changed");
}

Important difference:

Encryption hides data.
Checksum detects accidental data changes.
MAC/signature detects unauthorized changes.

So, encryption, checksum, and MAC/signature solve different problems.

Storage Limit​

Browser storage is limited.

The PDF mentions two major impacts of storing too much data on the client:

  1. It affects performance.
  2. Storing more data than the browser capacity can lead to data loss.
More client-side data
↓
More browser storage usage
↓
Possible performance impact
↓
Quota errors or data loss

Client Storage Limits​

Common browser storage limits mentioned in the PDF:

Storage TypeApproximate Limit
localStorage5-10 MB
sessionStorage5-10 MB
IndexedDB50-100 MB
Cookie4 KB-20 KB
Cache APIBrowser-managed

Use larger storage like IndexedDB only when the app really needs it, such as for offline data or structured client-side data.

Checking Storage Usage​

The browser StorageManager API can be used to estimate current usage and available quota.

function hasEnoughSpaceForData() {
if ("storage" in navigator && "estimate" in navigator.storage) {
navigator.storage.estimate().then((estimate) => {
console.log(
"Usage: " + (estimate.usage / 1024 / 1024).toFixed(2) + " MB",
);

console.log(
"Quota: " + (estimate.quota / 1024 / 1024).toFixed(2) + " MB",
);
});
} else {
console.log("StorageManager API is not supported in this browser.");
}
}

This is useful when the frontend stores data for:

  • offline support
  • cached API responses
  • PWA data
  • IndexedDB records
  • media or file cache

Session Management​

Sessions and cookies should be managed carefully.

A session usually connects a browser user with server-side user data.

Browser has session ID
↓
Server maps session ID to user data
↓
User stays authenticated

For session cookies, use proper cookie flags.

res.cookie("sessionId", sessionId, {
httpOnly: true,
secure: true,
});
Cookie FlagPurpose
HttpOnlyHelps prevent JavaScript from reading the cookie
SecureSends the cookie only over HTTPS

Important note:

Session cookies should usually be controlled from the server.
Do not depend only on client-side JavaScript for session security.

Summary​

Client-side security means storing less sensitive data in the browser, protecting what must be stored, expiring tokens, validating integrity, respecting storage limits, and managing sessions safely.

Client storage is useful, but not fully trusted.

Remember it like this:

Client-side Security = Store Less + Encrypt + Expire + Verify + Limit + Secure Sessions

Or even simpler:

Server first.
Client only when needed.
Protect everything important.