Skip to content
Back to Secure APIs and Student Data course

Work & Development · Backend & Full Stack Development

Free preview

Separate authentication from permission

Lesson 1 of Secure APIs and Student Data. Anyone can read this lesson with no account. Every lesson after this one is for students.

Accounts and permissions

Use test accounts to separate checking identity from granting permission to a note.

After this lesson you will be able to separate who a request comes from (authentication) from what that account may do (authorization), and test an ownership rule in code.

1Knowing a name does not grant access

First finish Server Applications with Node.js and SQL and Relational Data. Authentication checks who is asking. Authorization checks what that account may do.

Think of a school library card. A checked card identifies a learner; it does not let that learner open another person's private notebook. Likewise, a signed-in account may still have no permission to read someone else's note. The login service can work correctly while the app's permission rule is wrong.

Start with a policy, a clear rule for access, before building a login form. Use two test accounts and two invented notes. This exercise supplies identities from test code you control. A caller cannot choose those identities through a header or body. The function tests permission; it does not sign anyone in.

2Worked example: ownership is required

Save policy.mjs and run node policy.mjs.

import assert from 'node:assert/strict';
export function canReadNote(verifiedUser, note) {
  return Boolean(verifiedUser?.id && note && note.ownerId === verifiedUser.id);
}
const alex = { id: 'fictional-alex' };
const sam = { id: 'fictional-sam' };
const note = { id: 'note-1', ownerId: alex.id, title: 'Practice fractions' };
assert.equal(canReadNote(alex, note), true);
assert.equal(canReadNote(sam, note), false);
assert.equal(canReadNote(null, note), false);
assert.equal(canReadNote(alex, null), false);
console.log('Ownership policy checks passed');

Expect the success message. The decision requires both a verified identity and an owned resource. A public request cannot become alex merely by supplying that string. A real server obtains the user from an established authentication provider's verified session, which the next lesson addresses.

An ID tells the server which record is requested. It does not give permission. Even hard-to-guess IDs may appear in links, logs or browser data. Check ownership even when the caller knows the exact ID. Hiding an Edit button also provides no server protection: someone can send a request directly.

3Practice and debugging

  1. Make a policy table for a signed-out caller, owner, different account, missing note and malformed identity.
  2. Decide whether read and edit use the same rule. Add an admin role only if you can justify it and name a trusted source for that role.
  3. Write tests for the table.
  4. Temporarily allow any non-null user. Then try comparing the note ID with the user ID. Show why neither mistake checks ownership, and restore the correct rule.
  5. Include a guessed note ID in a denied case. Knowing the ID must still grant no access.

4Check yourself

  1. Does successful authentication authorize every resource?
  2. Can the browser's submitted ownerId establish ownership?
  3. Is hiding a link an adequate API defense?
Show answers
  1. No: each operation still needs its own permission decision.
  2. No: the server must use the verified account identity and stored record.
  3. No: the API must enforce its policy independently.

5Project milestone

Deliver a private-note permission table and an executable policy model with test accounts. State explicitly where verified identity will enter the server and where ownership will be checked, before implementing any network mutation.

Sources: OWASP authorization guidance, OWASP insecure direct object reference prevention.

Continue with the full course

This free preview is lesson 1 only. Enroll to open the rest of Secure APIs and Student Data.