Backend Frameworks (Node.js/Django)

Chapter 6
Authentication, Authorization, and Identity

Bachelors Program in Full Stack Development
Backend Frameworks (Node.js/Django)   •   Bachelor

Authentication, Authorization, and Identity

Introduction

Modern backend systems do more than store data and respond to requests. They must establish who is using the system, determine what that person or service may do, protect credentials and personal information, and support account changes throughout the identity lifecycle. These responsibilities are commonly grouped into identity and access management (IAM).

Three questions distinguish the major functions:

  1. Authentication: Who are you?
  2. Authorization: What are you allowed to do?
  3. Accounting or auditing: What did you do, and when?

A Node.js or Django application typically combines browser cookies, server-side sessions, password hashing, access-control rules, and sometimes signed tokens or delegated identity providers. These mechanisms are related but not interchangeable. A JSON Web Token (JWT), for example, can carry authentication claims, but possessing a valid token does not automatically mean that every operation is authorized.

This chapter develops a practical and conceptual foundation for implementing secure identity systems in full-stack applications.

Learning Objectives

By the end of this chapter, you should be able to:

  • distinguish authentication, authorization, identity, sessions, and auditing;
  • explain how cookies and server-side sessions support browser authentication;
  • select and use secure password-hashing approaches;
  • describe token-based authentication and JWT structure, strengths, and limitations;
  • explain OAuth 2.0 and OpenID Connect and distinguish delegation from authentication;
  • design role-based and attribute-based access-control policies;
  • implement account recovery and identity lifecycle controls;
  • identify common attacks and apply defensive engineering practices in Node.js and Django;
  • evaluate governance, privacy, usability, and operational trade-offs.

1. Identity as a Security System

An identity is a representation of a human, organization, device, or service. It normally contains an identifier, attributes, credentials, and relationships. A user record may include a database identifier, email address, display name, status, roles, and authentication metadata. A credential is evidence used to authenticate that identity, such as a password, passkey, or federated assertion.

Authentication factors are often classified as:

FactorMeaningExample
KnowledgeSomething the user knowsPassword or PIN
PossessionSomething the user hasHardware security key or authenticator device
InherenceSomething the user isBiometric characteristic

Multi-factor authentication (MFA) combines independent factors. Two passwords are not normally two independent factors because both are knowledge factors. MFA reduces the impact of a stolen password, although it does not eliminate phishing, session theft, or account-recovery risks.

A secure system also defines a trust boundary. The browser, application server, database, identity provider, email service, and administrator console have different trust levels. Credentials and tokens should be accepted only from appropriate issuers, validated in the correct context, and transmitted over encrypted connections.

Authentication and authorization

Authentication establishes a security principal: a user, service account, or external identity. Authorization then evaluates a policy against that principal, the requested action, and the target resource. A useful abstraction is:

Permit = Policy(subject, action, resource, context)

Here, subject is the authenticated principal, action is an operation such as read or delete, resource is the target object, and context may include time, device, location, or transaction risk. The expression is a policy model, not a universal numerical formula. It assumes that authentication has already produced a trustworthy subject and that policy inputs have been validated.

A common security failure is confused deputy behavior: an application correctly authenticates a user but performs an operation with greater authority than the user should possess. Authorization must therefore be enforced on the server, close to the protected operation, rather than only by hiding buttons in a user interface.

2. Passwords and Secure Credential Storage

Passwords are shared secrets. The application must verify them without storing the original password. A password-hashing function deliberately makes guessing expensive and uses a unique salt for each password. Suitable choices include Argon2id, scrypt, and bcrypt when correctly configured. A fast general-purpose hash such as SHA-256 is not an appropriate password-storage algorithm by itself because attackers can test enormous numbers of guesses quickly.

For a password P, a simplified stored record is:

stored = (algorithm, parameters, salt, hash(P, salt, parameters))

The salt is not secret. Its purpose is to ensure that identical passwords produce different stored values and to prevent effective use of precomputed tables. The work parameters control memory, time, or parallelism. They must be selected through benchmarking on the deployment environment and reviewed as hardware changes.

Password verification should use the password-hashing library's verification function. It should not compare passwords with ordinary string operations when the library provides a safe comparison mechanism. The database must be protected as sensitive security data even though salts and hashes are not plaintext passwords.

Password policy and usability

Length is generally more valuable than arbitrary complexity rules. Systems should reject known-compromised passwords, permit password managers, avoid forced periodic changes without evidence of compromise, and provide clear recovery mechanisms. Rate limiting, breached-password screening, MFA, and secure session management often provide more practical protection than requiring unusual punctuation.

In Node.js, libraries such as argon2 or bcrypt can perform password hashing. In Django, the password framework and make_password/check_password abstractions select configured password hashers. Application code should avoid implementing cryptographic primitives itself.

3. Cookies and Server-Side Sessions

A browser session allows an application to recognize a sequence of requests as belonging to an authenticated user. In a server-side session design:

  1. The user submits credentials over HTTPS.
  2. The server verifies the password.
  3. The server generates a random, unpredictable session identifier.
  4. The server stores session state, such as user ID and expiration, in a database or cache.
  5. The server sends the identifier in a cookie.
  6. The browser returns the cookie on subsequent requests.
  7. The server looks up the session and applies authorization rules.

The cookie should normally have these attributes:

  • Secure: send it only over HTTPS;
  • HttpOnly: prevent ordinary JavaScript from reading it;
  • SameSite: restrict cross-site sending according to the application's request patterns;
  • an appropriate expiration or session lifetime;
  • a narrow Domain and Path where practical.

HttpOnly helps limit token theft through some cross-site scripting attacks, but it does not prevent an injected script from making requests as the user. Cross-site request forgery (CSRF) remains relevant when browsers automatically attach cookies. Synchronizer tokens, double-submit techniques, and suitable SameSite settings are common defenses.

Session fixation and lifecycle

In session fixation, an attacker causes a victim to use a session identifier known to the attacker and later benefits when the victim authenticates. The server must rotate the session identifier after login, privilege elevation, and sometimes password change. On logout, it should invalidate the server-side session rather than merely deleting a browser cookie.

Session design involves several independent lifetimes:

  • idle timeout: expiration after inactivity;
  • absolute timeout: maximum session age;
  • renewal period: when a valid session receives a new identifier;
  • revocation: immediate invalidation after risk events.

A distributed Node.js or Django deployment needs a shared session store or another coordination mechanism. In-memory sessions on one process cause inconsistent behavior across instances and are unsuitable for production clusters unless carefully architected.

4. Token-Based Authentication and JWT

A token is a credential presented by a client. Unlike a server-side session identifier, a self-contained token may carry claims that the server validates without a session lookup. This can support APIs and distributed services, but it creates difficult revocation and key-management problems.

A JWT commonly consists of three Base64URL-encoded parts separated by periods:

header.payload.signature

The header identifies metadata such as the signing algorithm. The payload contains claims such as iss (issuer), sub (subject), aud (audience), exp (expiration time), iat (issued-at time), and possibly scopes. The signature protects integrity and authenticity; it does not encrypt the payload. Sensitive information should therefore not be placed in a JWT merely because it is encoded.

A verifier should:

  1. use a trusted key selected by server configuration, not blindly by attacker-controlled input;
  2. allow only explicitly configured algorithms;
  3. validate the signature;
  4. validate issuer, audience, expiration, and relevant time claims;
  5. apply application authorization rules to the resulting identity;
  6. reject malformed, expired, or context-inappropriate tokens.

The alg: none issue illustrates why accepting an algorithm from an untrusted token without policy validation is dangerous. Similarly, confusing an HMAC shared secret with an asymmetric public key can produce signature-verification vulnerabilities.

Access and refresh tokens

Short-lived access tokens reduce the window of misuse. A refresh token can obtain a new access token and should be stored and transmitted more carefully. Refresh-token rotation records token use and replaces a token after each successful refresh. Reuse detection can revoke the associated token family, indicating possible theft.

JWTs are not automatically superior to sessions. Sessions provide straightforward revocation and small cookies, while JWTs can simplify stateless API verification. A JWT remains valid until expiration unless the system adds a denylist, changes signing keys, checks a token version, or uses short lifetimes. The design should be driven by deployment needs rather than fashion.

5. OAuth 2.0 and OpenID Connect

OAuth 2.0 is an authorization framework for delegated access. It allows a client application to obtain limited access to a resource server on behalf of a resource owner. OAuth access tokens express authorization to an API; OAuth alone does not define a standard identity claim set or guarantee that a token is suitable for logging a user in.

OpenID Connect (OIDC) extends OAuth 2.0 with an identity layer. An OIDC provider issues an ID token, normally a JWT, describing the authentication event and subject. The client validates the ID token according to the provider's discovery metadata and protocol rules. An access token is intended for the resource server and should not automatically be interpreted as an ID token.

The preferred browser flow for a web or mobile client is generally Authorization Code with PKCE. The client creates a random code verifier and derives a code challenge. It sends the challenge to the authorization server. After authentication and consent, the authorization server returns a short-lived authorization code. The client exchanges the code, along with the verifier, for tokens. PKCE reduces the value of an intercepted authorization code.

Important protections include:

  • validate the state value to defend against request forgery and login CSRF;
  • use a nonce in OIDC to bind the ID token to the authentication request;
  • register exact or tightly controlled redirect URIs;
  • use HTTPS and avoid tokens in URLs or logs;
  • request minimal scopes and validate issuer, audience, and nonce;
  • distinguish the provider's stable subject identifier from mutable email addresses.

Federated logout, account linking, and changes to the external provider's email address require explicit design. Automatically linking accounts solely because two providers report the same email can enable account takeover in some provider configurations.

6. Authorization Models

Role-based access control

Role-based access control (RBAC) assigns permissions to roles and roles to users. A permission can be represented as a pair such as (invoice, approve). A role such as finance_manager may contain several permissions. RBAC is understandable and effective for stable organizational responsibilities.

Its weaknesses include role explosion and difficulty representing context. A simple role check such as user.isAdmin may also become dangerously broad. Permissions should be specific, and administrative roles should follow least privilege.

Attribute-based access control

Attribute-based access control (ABAC) evaluates attributes of the subject, resource, action, and environment. For example, a clinician may view a record only when assigned to the patient's department and when the request occurs during an approved operational context. ABAC is expressive but requires reliable attributes, clear policy ownership, and explainable decisions.

A practical system often combines models: roles provide baseline permissions, while resource ownership, organization membership, classification, and transaction state provide additional constraints. This is sometimes called a hybrid or relationship-aware model.

Authorization must be checked for every relevant object. An endpoint that verifies that a user may access the orders feature but fails to verify ownership of order 4821 is vulnerable to insecure direct object reference (IDOR), also called broken object-level authorization.

7. Implementation Patterns in Node.js and Django

A backend should centralize authentication middleware and authorization policies while keeping decisions close to domain operations. In Express, middleware may authenticate a session or bearer token and attach a principal to the request. Route-level middleware can require a permission, but the service layer should also enforce important invariants. In Django, authentication middleware populates request.user; decorators, permissions, groups, and class-based permission checks can then be combined with object-level checks.

A robust request sequence is:

  1. terminate or validate TLS at a trusted boundary;
  2. parse and validate the request;
  3. authenticate the principal;
  4. authorize the requested action and object;
  5. execute the business operation transactionally;
  6. record security-relevant events without logging secrets;
  7. return an error that reveals no unnecessary account information.

Do not rely on client-supplied user IDs, roles, prices, or organization identifiers. Derive security context from the authenticated principal and server-side data. Use parameterized queries or an ORM, protect administrative routes separately, and test both allowed and denied cases.

8. Account Recovery and Identity Lifecycle

Identity security continues after registration. A lifecycle normally includes enrollment, verification, activation, normal use, privilege changes, suspension, recovery, and deprovisioning.

Email verification links and password-reset links should contain high-entropy, single-use, time-limited random values. Store a hash of the reset token where practical, so a database compromise does not immediately reveal usable links. Invalidate previous reset tokens after successful use, notify the user of security changes, and avoid revealing whether an email address exists in the system.

Recovery is an alternate authentication path and must be protected as strongly as possible. Security questions based on public facts are weak. Support staff should use documented identity-proofing procedures, dual control for sensitive changes, and audit trails. A user who loses an MFA device may require backup codes, a verified second factor, or a carefully reviewed recovery process.

Provisioning and deprovisioning should be connected to organizational sources where appropriate. When employment ends or access is withdrawn, disable accounts, revoke sessions and refresh tokens, remove group memberships, rotate service credentials, and preserve necessary audit records. Dormant accounts should be reviewed. Service accounts require named owners, narrow scopes, rotation procedures, and monitoring.

9. Security Threats, Governance, and Privacy

Important threats include credential stuffing, phishing, brute-force guessing, session theft, CSRF, XSS, token leakage, replay, authorization bypass, enumeration, and compromised dependencies. Controls should be layered:

  • rate-limit login and recovery operations;
  • use MFA and phishing-resistant passkeys where feasible;
  • monitor anomalous sign-ins and impossible travel cautiously;
  • protect secrets using a managed secret store;
  • rotate signing keys and publish key metadata safely;
  • log authentication and authorization events with time, principal, action, outcome, and correlation ID;
  • avoid passwords, access tokens, reset links, and full personal data in logs;
  • patch frameworks and dependencies;
  • test negative authorization paths and recovery flows.

Privacy principles require purpose limitation, data minimization, retention controls, access transparency, and appropriate user rights under applicable law. Identity data can reveal behavior and associations, so collecting more attributes than a policy requires increases both privacy and security risk. Governance should define who may change roles, who reviews privileged access, how incidents are handled, and how long audit records are retained.

AI-based risk scoring can assist anomaly detection, but it should not silently make irreversible identity decisions. Models may reproduce bias, generate false positives, and be difficult to explain. Human review, measurable thresholds, appeal processes, data protection, and continuous evaluation are essential when automated identity decisions affect access to important services.

10. Illustrative Case: University Research Portal

Background

A university research portal allows students, supervisors, finance officers, and external collaborators to manage projects, documents, and reimbursements. The first version stores a user ID in a browser cookie and checks an isAdmin flag in several routes.

Problem

An attacker discovers that changing a project identifier in a URL exposes another research team's documents. Password-reset responses reveal whether an email exists. Sessions remain valid after a password change, and the application uses long-lived JWTs in browser local storage.

Analysis

The portal has object-level authorization failures, account enumeration, weak session lifecycle controls, and excessive token exposure. The administrative boolean also cannot express project membership or the distinction between viewing and approving a reimbursement.

Approach and solution

The team adopts server-side sessions for the browser application, with Secure, HttpOnly, and suitable SameSite cookies. Session identifiers rotate after login and privilege changes. Passwords are rehashed with Argon2id at configured parameters. Reset responses are uniform, and reset tokens are single-use and time-limited.

The authorization model combines roles with resource attributes. A supervisor may view documents only for projects they supervise. A finance officer may approve reimbursements only when assigned to the relevant faculty and when the reimbursement is in a pending state. Every document and reimbursement query applies a server-side ownership or membership predicate.

MFA is introduced for staff and administrators. Security events are logged without tokens. Password change and account suspension revoke active sessions and refresh credentials. Automated tests include requests made with valid authentication but invalid project ownership.

Outcome

The portal gains smaller, clearer security boundaries. A stolen browser cookie has a limited lifetime and can be revoked centrally; a changed URL no longer bypasses object authorization; and recovery and privileged actions become auditable. The project also documents the trade-off: server-side sessions require shared storage and operational monitoring, but they simplify revocation for this browser-centric application.

Learning points

Authentication is only one stage of the security design. Authorization must be object-aware, recovery must be treated as authentication, and lifecycle events must revoke previously issued authority. The most effective design is usually a combination of controls rather than a single technology.

Best-Practice Checklist

  • Use HTTPS everywhere and configure secure transport correctly.
  • Store passwords only with an adaptive password-hashing function.
  • Rotate sessions after login and privilege changes.
  • Set appropriate cookie attributes and defend state-changing requests against CSRF.
  • Validate JWT issuer, audience, signature, algorithm, and time claims.
  • Prefer Authorization Code with PKCE for delegated browser authorization.
  • Enforce authorization server-side and at object level.
  • Apply least privilege and review privileged access.
  • Make recovery tokens random, single-use, short-lived, and non-enumerating.
  • Revoke sessions and tokens during high-risk lifecycle events.
  • Log useful security events, never secrets.
  • Test denial paths, race conditions, account linking, and deprovisioning.

Chapter Summary

Authentication establishes the identity of a principal; authorization evaluates what that principal may do; auditing records relevant activity. Browser applications commonly use server-side sessions with carefully configured cookies, while APIs may use bearer tokens or JWTs when their operational trade-offs are understood. Passwords must be protected with adaptive password-hashing functions and unique salts. OAuth 2.0 delegates access, whereas OpenID Connect adds an identity layer; Authorization Code with PKCE, state, nonce, and strict redirect validation are central protections. RBAC provides manageable role-based permissions, while ABAC and hybrid models express ownership, organization, resource, and environmental constraints. Secure identity systems also address recovery, MFA, revocation, deprovisioning, privacy, logging, and governance. No credential mechanism substitutes for precise, server-side, object-level authorization.

Key Terms

Authentication: Verifying the identity of a principal.

Authorization: Determining whether a principal may perform an action.

Identity: A representation of a person, service, device, or organization.

Credential: Evidence used to authenticate an identity.

MFA: Authentication using two or more independent factors.

Session: Server-maintained state linking requests to an authenticated principal.

Cookie: Browser-managed data sent with matching requests.

CSRF: An attack that causes a browser to send an unintended authenticated request.

Password hashing: One-way, deliberately expensive processing used to verify passwords.

Salt: Unique non-secret input added to a password hash.

JWT: A signed, structured token carrying claims.

Access token: A credential intended to authorize access to a resource server.

Refresh token: A credential used to obtain new access tokens.

OAuth 2.0: A framework for delegated authorization.

OpenID Connect: An identity layer built on OAuth 2.0.

RBAC: Authorization based on roles and their permissions.

ABAC: Authorization based on subject, resource, action, and environmental attributes.

Least privilege: Granting only the authority required for an approved purpose.

Identity lifecycle: Enrollment, use, change, suspension, recovery, and deprovisioning of an identity.

Review Questions

Short Answer Questions

  1. How do authentication and authorization differ?
  2. Why is a unique salt used in password storage?
  3. What security properties do Secure and HttpOnly cookie attributes provide?
  4. Why is a JWT payload not automatically confidential?
  5. What is the purpose of PKCE in an OAuth authorization-code flow?

Long Answer Questions

  1. Compare server-side sessions and JWT-based authentication, including revocation, scalability, storage, and browser security considerations.
  2. Explain how a backend should validate an OIDC login and distinguish an ID token from an access token.
  3. Compare RBAC and ABAC and describe a hybrid policy for a multi-tenant application.
  4. Design a secure password-reset and account-recovery process.
  5. Explain how authentication, authorization, auditing, and privacy governance interact in an enterprise system.

Analytical / Application Questions

  1. An API verifies a valid JWT but allows any authenticated user to request /projects/784/documents. Identify the authorization weakness and propose a corrected policy.
  2. A company stores long-lived refresh tokens in plaintext and never revokes sessions after an employee leaves. Analyze the risks and recommend lifecycle controls.
  3. A university wants social login and automatic account linking based only on email addresses. Evaluate the design and propose safer linking and recovery procedures.

Multiple Choice Questions with Answers

Question 1

Which statement best describes authorization?

A. Verifying a password against a stored hash

B. Determining whether an authenticated principal may perform an action

C. Encrypting a database connection

D. Creating a browser cookie

Correct Answer: B. Determining whether an authenticated principal may perform an action

Question 2

Why should a password normally be stored using Argon2id, scrypt, or bcrypt rather than plain SHA-256?

A. Those algorithms make guessing deliberately expensive

B. Those algorithms make passwords recoverable

C. SHA-256 cannot process text

D. Password hashes must contain a user’s email address

Correct Answer: A. Those algorithms make guessing deliberately expensive

Question 3

Which cookie attribute prevents ordinary client-side JavaScript from reading the cookie?

A. Secure

B. SameSite

C. HttpOnly

D. Domain

Correct Answer: C. HttpOnly

Question 4

What does a JWT signature primarily provide?

A. Confidentiality of the payload

B. Integrity and authenticity when correctly verified

C. Automatic database revocation

D. Protection against all authorization errors

Correct Answer: B. Integrity and authenticity when correctly verified

Question 5

Which claim is used to identify the intended recipient or audience of a JWT?

A. aud

B. iat

C. sub

D. nonce

Correct Answer: A. aud

Question 6

What is the principal purpose of PKCE?

A. To hash user passwords

B. To protect an intercepted authorization code

C. To encrypt an ID-token payload

D. To replace all redirect-URI validation

Correct Answer: B. To protect an intercepted authorization code

Question 7

Which model evaluates attributes of the subject, resource, action, and environment?

A. RBAC

B. ABAC

C. MFA

D. DNS

Correct Answer: B. ABAC

Question 8

A user changes an order ID in a URL and sees another customer's order. What vulnerability does this most directly indicate?

A. Broken object-level authorization

B. Password spraying

C. Session fixation only

D. Algorithm confusion

Correct Answer: A. Broken object-level authorization

Question 9

Which is the strongest description of a secure password-reset token?

A. A permanent token derived from the user's email

B. A short, predictable numeric value reused for every request

C. A random, single-use, time-limited value

D. The user's existing password encrypted with a database key

Correct Answer: C. A random, single-use, time-limited value

Question 10

What is a key difference between OAuth 2.0 and OpenID Connect?

A. OAuth 2.0 is only for password hashing

B. OpenID Connect adds an identity layer to OAuth 2.0

C. OAuth 2.0 requires cookies, while OIDC forbids them

D. OpenID Connect eliminates the need for authorization

Correct Answer: B. OpenID Connect adds an identity layer to OAuth 2.0

Backend Frameworks (Node.js/Django)
Chapter 6 of 14