Quiz

How can you implement secure authentication and authorization in JavaScript applications?

Topics
JavaScriptSecurity

TL;DR

Use a proven identity provider or framework rather than inventing an authentication protocol. Protect credentials with HTTPS; use phishing-resistant passkeys or properly hashed passwords with MFA where appropriate; establish a short-lived server-side session or carefully validated token; and keep browser session credentials in HttpOnly, Secure, appropriately scoped cookies when possible. Enforce authorization on every server-side operation using the application's actual permission model, never rely on hidden UI or client-side role checks. Cookie-based sessions also need CSRF defenses such as SameSite plus a CSRF token where necessary.


Authenticate identity, then authorize every action

Authentication establishes a principal; authorization separately evaluates whether that principal may perform this action on this resource.

Authentication and authorization request flow

Client-side route guards are user-interface behavior, not enforcement; the trusted server must validate authorization for every protected request.

Use HTTPS

Ensure that your application uses HTTPS to encrypt data in transit. This prevents man-in-the-middle attacks and ensures that data exchanged between the client and server is secure.

Choose a session architecture

Opaque session identifiers stored in a server-side session store are often the simplest choice for a browser application. JWTs can be useful for distributed systems, but they add key management, claim validation, revocation, and rotation concerns; they are a format, not an authentication strategy.

Example of generating a JWT

const jwt = require('jsonwebtoken');
const token = jwt.sign({ sub: '123', aud: 'api.example.com' }, signingKey, {
algorithm: 'RS256',
issuer: 'https://auth.example.com',
expiresIn: '1h',
});

Example of verifying a JWT

const jwt = require('jsonwebtoken');
try {
const decoded = jwt.verify(token, verificationKey, {
algorithms: ['RS256'],
audience: 'api.example.com',
issuer: 'https://auth.example.com',
});
console.log(decoded);
} catch (err) {
console.error('Invalid token');
}

Secure storage

localStorage and sessionStorage are readable by any script running in the origin, so a single XSS vulnerability can exfiltrate a bearer token. For same-site browser applications, prefer a narrowly scoped HttpOnly; Secure; SameSite session cookie. Because cookies are attached automatically, add CSRF protection where SameSite alone does not cover the flow.

// Server-side Express example. Use a random, opaque session ID and keep the
// session data in a server-side store.
res.cookie('session', sessionId, {
httpOnly: true,
secure: true,
sameSite: 'lax',
path: '/',
maxAge: 30 * 60 * 1000,
});

Server-side validation

Authenticate the session or token on the server for every protected request. For JWTs, allow-list the expected algorithm and validate the signature, issuer, audience, expiry, and any application-specific claims. Authentication proves who the caller is; authorization still decides whether that caller may perform this exact action on this exact resource.

OpenID Connect for third-party sign-in

OAuth 2.0 delegates authorization; OpenID Connect adds the identity layer used for sign-in. Use Authorization Code with PKCE through a maintained provider SDK or library, validate state and nonce, and use HTTPS redirect URIs. Avoid implementing the protocol from scratch.

Server-side authorization

RBAC is one option when permissions map cleanly to roles. Applications may instead need ownership checks, attribute-based policies, or explicit capabilities. Whatever the model, enforce it server-side and default to denial.

Example of RBAC middleware in Express.js

function checkRole(role) {
return function (req, res, next) {
if (req.user && req.user.role === role) {
next();
} else {
res.status(403).send('Forbidden');
}
};
}
// Usage
app.get('/admin', checkRole('admin'), (req, res) => {
res.send('Welcome, admin!');
});

Real handlers should also check resource-level permissions (for example, whether a user owns the document being edited) rather than assuming a coarse role is sufficient.

Further reading

Exercises

Check your understanding
Beta
Check your understanding Exercise 1 of 3
Check your understanding Exercise 1 of 3

An API verifies a token’s signature using the trusted issuer’s key. The token has not expired, but its audience names a different API. What should this API do?