Course outline

Node.js / Intermediate: application boundaries / Lesson 12

Authentication and authorization concepts

Separate identity from permission, protect credentials, and reason about sessions without inventing a production authentication protocol.

About 4 min readContent reviewed
On this page

Lesson goals

  • Explain the concepts and trade-offs behind authentication and authorization concepts.
  • Predict and verify both examples, including their outputs and cleanup behavior.
  • Diagnose the three common failures and apply the worked solutions to related inputs.

Identity does not imply permission

Authentication establishes an actor’s identity; authorization decides whether that actor may perform a specific operation on a specific resource. A valid session does not entitle its owner to every record. Use deny-by-default rules and check access on the server for every protected operation. The first example shows a small owner-or-admin policy over synthetic objects. It is deliberately independent of HTTP so the important business rule can be tested directly. Do not trust a role or owner ID merely because a browser submitted it in a hidden field.

Handle credentials as sensitive data

Passwords should be verified through a suitable password-hashing scheme with unique salts and carefully chosen work parameters, using a reviewed library or identity service. A fast plain hash is not a password storage strategy. Tokens and session identifiers are credentials too: avoid logging them, placing them in URLs, or exposing them through analytics. Transport credentials over TLS and define rotation and revocation procedures. Authentication failures should not disclose unnecessary account existence information, and repeated attempts need rate controls appropriate to both account and network abuse.

Understand session choices

An opaque session identifier refers to server-side state. A signed token carries claims whose integrity is checked, but signing alone does not encrypt those claims. Either approach needs expiry, audience and issuer policy where applicable, and a way to respond to compromised credentials. For browser cookies, HttpOnly, Secure, and an appropriate SameSite setting reduce specific risks; they do not replace CSRF defenses or XSS prevention. Cross-origin permission is separate from authentication. CORS controls browser access to responses and should never be treated as a server authorization mechanism.

javascript Complete example: Understand session choices
function mayEdit(actor, resource) {
  return Boolean(actor && (actor.role === 'admin' || actor.id === resource.ownerId));
}
const resource = { ownerId: 7 };
console.log(mayEdit(null, resource));
console.log(mayEdit({ id: 7, role: 'user' }, resource));
console.log(mayEdit({ id: 8, role: 'user' }, resource));
console.log(mayEdit({ id: 8, role: 'admin' }, resource));
Expected output
false
true
false
true

The policy denies anonymous and unrelated users while allowing the owner and an independently trusted administrator role.

Compare secrets with correct primitives

The second example uses timingSafeEqual on equal-length synthetic byte buffers. The API requires matching byte lengths, and surrounding parsing or lookup logic can still leak timing information. This demonstration does not implement password verification or a complete token validator. Use established protocol libraries for token formats and verify all required claims rather than only decoding their text. Keep keys outside source code, reject unsupported algorithms explicitly through library configuration, and separate development test credentials from deployed secrets. Security comes from the complete flow, not one cryptographic function.

javascript Complete example: Compare secrets with correct primitives
import { timingSafeEqual } from 'node:crypto';
function sameBytes(candidate, expected) {
  const a = Buffer.from(candidate, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  return a.length === b.length && timingSafeEqual(a, b);
}
console.log(sameBytes('lab-token-a', 'lab-token-a'));
console.log(sameBytes('lab-token-b', 'lab-token-a'));
console.log(sameBytes('short', 'lab-token-a'));
Expected output
true
false
false

These public synthetic strings demonstrate equal-length byte comparison only. They are not credentials and must not become deployed secrets.

Test authorization as a matrix

List actor types, operations, resource ownership, and relevant state. Test anonymous access, the owner, another ordinary user, an administrator, and expired or revoked credentials. An authorization rule can depend on tenant membership and resource status in addition to role. Fetch or update data with the ownership condition applied close to persistence so a later unchecked lookup cannot bypass it. Audit privileged changes with safe actor and resource identifiers while omitting secrets. When requirements grow beyond a simple policy, centralize the rules and review changes as carefully as database permissions.

Common errors and fixes

A signed token exposes private claims

Why it happens
Signing was mistaken for encryption.
How to fix it
Remove sensitive claims or choose a reviewed confidentiality design.
Prevent it next time
Review what every token holder can decode.

A user edits another user’s record

Why it happens
The server checked login but not resource authorization.
How to fix it
Apply ownership or permission checks to the actual operation.
Prevent it next time
Test unrelated-user cases for every protected route.

timingSafeEqual throws a length error

Why it happens
The byte buffers had different lengths.
How to fix it
Validate lengths before invoking the primitive.
Prevent it next time
Prefer reviewed authentication components over custom protocols.

Check your understanding

1. A browser hides an administrator button. Does this protect its server endpoint?

Show worked solution

No. A caller can send the request directly. Authenticate the actor and apply server-side authorization to the endpoint and target resource. The hidden button improves presentation only. Test an ordinary user’s direct request and require the documented denial.

2. Build the four outcomes for anonymous, owner, other user, and admin in the sample policy.

Show worked solution

The outcomes are false, true, false, true. Keep the role source trusted and the resource ownership loaded from persistence. If ownership can change concurrently, bind the authorization condition to the update rather than trusting a stale earlier check.

Key takeaways

  • Authentication establishes an actor’s identity; authorization decides whether that actor may perform a specific operation on a specific resource.
  • Passwords should be verified through a suitable password-hashing scheme with unique salts and carefully chosen work parameters, using a reviewed library or identity service.
  • List actor types, operations, resource ownership, and relevant state.

Official references