Loading
0x30Lesson 4 of 15

Protect identities and access

Separate authentication from authorization, limit access, and contain a compromised device.

28 min 7-question quiz 1 code exercise
By the end of this lesson you can
  • Distinguish proving an identity from deciding what it can do
  • Apply role-based access control with deny-by-default
  • Prevent insecure direct object references (IDOR)
  • Explain why network location alone does not grant trust and how segmentation limits movement

Two questions guard every request:

  • Authentication (authn): who are you? - proven with a password, passkey, certificate or token.
  • Authorization (authz): what may you do? - decided by permissions, roles, ownership and policy.

Getting authorization wrong is so common that Broken Access Control is number one in the OWASP Top 10:2025. Typical mistakes: checking permissions only in the user interface, forgetting a check on one endpoint, or trusting an ID in the URL without checking who owns that record.

Try it

Up to 15 XP

Authentication or authorization?

Sort each check or failure.

0 of 6 sortedScore 0/0
  • “Verifying a passkey signature at sign-in”

  • “Only managers can approve expense reports”

  • “A signed-in user opens /invoices/1043, which belongs to someone else”

  • “Checking a one-time code from an authenticator app”

  • “A support agent can read tickets but not delete them”

  • “A service presents a client certificate to another service”

Least privilege and deny-by-default

Role-based access control (RBAC) groups permissions into roles (viewer, editor, admin) and gives users roles. Two principles keep it safe:

  • Deny by default - anything not explicitly allowed is refused, including unknown roles and actions.
  • Least privilege - give only the access a task needs, for only as long as it’s needed, and review it regularly.

Roles aren’t enough for personal data: a user may view invoices, but only their own. When a URL contains an ID like /invoices/1043, the server must check ownership on every request. Returning 404 Not Found for records the user doesn’t own (instead of 403) also avoids confirming that the record exists.

Practice: deny by default

Try it

Up to 15 XP

Give each role only what it needs

Viewers read documents, editors read and change them, and nobody else gets in. Turn rules on and off until every request gets the right answer.

Round 1 of 1: Roles in a document app

Anything no rule allows is denied by default.

Your policy

Requests

  • A viewer reads a documentAllowed (should be allowed)Decided by: Everyone can do everything
  • A viewer changes a documentAllowed (should be denied)Decided by: Everyone can do everything
  • An editor changes a documentAllowed (should be allowed)Decided by: Everyone can do everything
  • An editor reads a documentAllowed (should be allowed)Decided by: Everyone can do everything
  • An unknown role reads a documentAllowed (should be denied)Decided by: Everyone can do everything
2 requests get the wrong decision.

Practice: read someone else’s invoice

Try it

Up to 15 XP

Exploit a broken access check

You’re signed in to a simulated billing site as ana, and this is your own invoice. Change the number in the URL to open someone else’s. Then turn on the fix and try again. No hacking tools needed: that’s why this bug is so common.

A simulation. You’re signed in as ana.

Invoice 1043Billed to: anaWeb hosting: $40
  • Open an invoice that isn’t yours
  • Turn on the fix and see the same request refused

Assume one device is compromised

A stolen staff laptop is already inside the company network. If every internal machine can reach every database and backup, one compromised device can become a much larger incident. Network segmentation limits which systems can talk to one another: a web app may need database access, but a staff laptop and the open Internet do not.

Zero trust adds a second idea: being on the office Wi-Fi, VPN, or a company-owned device does not automatically make a request trustworthy. Check the identity, device, requested resource and policy for each access decision; grant only the access needed. Segmentation is useful, but network location is not a substitute for application authorization. NIST SP 800-207 explains the principle, and CISA’s microsegmentation guidance shows how smaller segments limit lateral movement.

Try it

Up to 15 XP

Keep the database behind the app

The database listens on port 5432. Customers still need HTTPS on 443, and the app server still needs its database connection. A broad allow rule currently opens the database to everyone. Reorder the first-match rules until all four flows have the right verdict. A compromised laptop must not reach the database directly.

Rules, checked top to bottom

  1. 1AllowDatabase from anywhere (too broad)
  2. 2DenyBlock other database access
  3. 3AllowApp server to database
  4. 4AllowHTTPS for customers
  5. –Anything else: denied by default

Traffic

  • App server queries the databaseShould pass. Matched rule 1: Allow.
  • Compromised staff laptop probes the databaseShould be blocked. Matched rule 1: Allow.
  • Internet host probes the databaseShould be blocked. Matched rule 1: Allow.
  • Customer loads the HTTPS siteShould pass. Matched rule 4: Allow.

2 flows have the wrong verdict.

Key takeaways

  • Authentication asks who; authorization asks what they may do.

  • Deny by default and grant least privilege; review access regularly.

  • Check ownership on the server for every record a request names.

  • Segment systems to limit lateral movement, and verify access even inside the network.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: write Python

Write Python in the editor and run it against sample inputs. Python runs locally in your browser using a WebAssembly runtime.

Exercise 1

Stop insecure direct object references

+25 XP

The first line is JSON mapping invoice IDs to their owners. Each following line is user GET /invoices/ID. Print user /invoices/ID -> 200 only if the invoice exists and belongs to the user; otherwise print -> 404 (don’t reveal that someone else’s invoice exists).

  • Own, other and missing invoices
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…