Resource ownership checks make sure only the right person can change or see their own data. This keeps things safe and private.
Resource ownership checks in Express
Start learning this pattern below
Jump into concepts and practice - no test required
app.put('/resource/:id', (req, res, next) => { const resource = getResourceById(req.params.id); if (!resource) { return res.status(404).send('Resource not found'); } if (resource.ownerId !== req.user.id) { return res.status(403).send('Forbidden'); } // proceed with update });
Check if the resource's owner ID matches the logged-in user's ID.
Send a 403 Forbidden response if the user does not own the resource.
app.delete('/posts/:postId', (req, res) => { const post = findPost(req.params.postId); if (!post) { return res.status(404).json({ error: 'Post not found' }); } if (post.ownerId !== req.user.id) { return res.status(403).json({ error: 'Not allowed' }); } deletePost(req.params.postId); res.json({ message: 'Post deleted' }); });
app.get('/profile', (req, res) => {
const userProfile = getUserProfile(req.user.id);
res.json(userProfile);
});app.put('/comments/:id', (req, res) => { const comment = getCommentById(req.params.id); if (!comment) { return res.status(404).send('Comment not found'); } if (comment.ownerId !== req.user.id) { return res.status(403).send('Forbidden'); } updateComment(req.params.id, req.body); res.send('Comment updated'); });
This Express app simulates a user logged in as 'user1'. It allows updating posts only if the logged-in user owns the post. If the user tries to update a post they don't own, the server responds with 403 Forbidden.
import express from 'express'; const app = express(); app.use(express.json()); // Fake data store const posts = [ { id: '1', ownerId: 'user1', content: 'Hello world' }, { id: '2', ownerId: 'user2', content: 'Hi there' } ]; // Fake authentication middleware app.use((req, res, next) => { req.user = { id: 'user1' }; // Simulate logged-in user next(); }); // Route to update a post app.put('/posts/:id', (req, res) => { const post = posts.find(p => p.id === req.params.id); if (!post) { return res.status(404).send('Post not found'); } if (post.ownerId !== req.user.id) { return res.status(403).send('Forbidden: You do not own this post'); } post.content = req.body.content || post.content; res.json(post); }); // Start server app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });
Always verify ownership before allowing changes to sensitive data.
Use middleware to get the logged-in user info securely.
Return clear HTTP status codes like 403 for forbidden access.
Resource ownership checks protect user data by allowing only owners to modify or view their resources.
Check ownership by comparing resource owner ID with logged-in user ID.
Respond with 403 Forbidden if ownership does not match.
Practice
Solution
Step 1: Understand resource ownership
Resource ownership means a resource belongs to a specific user.Step 2: Purpose of ownership checks
Ownership checks prevent unauthorized users from accessing or changing resources they don't own.Final Answer:
To ensure only the owner can access or modify their resource -> Option BQuick Check:
Ownership check = restrict access to owner [OK]
- Thinking ownership checks speed up queries
- Allowing all users to edit resources
- Confusing ownership with logging
req.params.id and owner ID in resource.ownerId?Solution
Step 1: Check user ID equality
We comparereq.user.idwithresource.ownerIdusing strict equality to confirm ownership.Step 2: Respond with 403 if not owner
If IDs don't match, respond with 403 Forbidden to block access.Final Answer:
if (req.user.id === resource.ownerId) { next(); } else { res.status(403).send('Forbidden'); } -> Option CQuick Check:
Strict equality + 403 Forbidden = correct ownership check [OK]
- Using == instead of ===
- Sending wrong status codes like 404 or 401
- Comparing whole user object instead of user ID
req.user.id is '123' and resource.ownerId is '456'?
app.delete('/items/:id', (req, res) => {
const resource = {ownerId: '456'};
if (req.user.id === resource.ownerId) {
res.send('Deleted');
} else {
res.status(403).send('Forbidden');
}
});Solution
Step 1: Compare user ID and owner ID
Sincereq.user.id('123') does not equalresource.ownerId('456'), ownership check fails.Step 2: Return 403 Forbidden
The else block sends a 403 Forbidden response blocking deletion.Final Answer:
Response will be 403 Forbidden -> Option DQuick Check:
Non-matching IDs = 403 Forbidden [OK]
- Assuming deletion happens anyway
- Confusing 403 with 404
- Ignoring ownership check logic
function checkOwnership(req, res, next) {
const resource = {ownerId: '456'}; /* example */
if (req.user.id = resource.ownerId) {
next();
} else {
res.status(403).send('Forbidden');
}
}Solution
Step 1: Check the if condition syntax
The condition uses single equals (=), which assigns instead of compares, causing a bug.Step 2: Correct comparison operator
It should use strict equality (===) to comparereq.user.idandresource.ownerId.Final Answer:
Using assignment (=) instead of comparison (===) in the if condition -> Option AQuick Check:
Assignment in if condition = bug [OK]
- Confusing = with === in conditions
- Thinking next() needed in else block
- Wrong status code for forbidden access
post.ownerId. Which Express middleware correctly implements this ownership check and returns 403 if the user is not the owner?Solution
Step 1: Use middleware to check ownership before update
Middleware checks ifreq.user.idmatchespost.ownerIdand callsnext()if true.Step 2: Return 403 Forbidden if not owner
If IDs don't match, respond with 403 to block unauthorized edits.Final Answer:
app.put('/posts/:id', (req, res, next) => { if (req.user.id === post.ownerId) next(); else res.status(403).send('Forbidden'); }, (req, res) => { res.send('Post updated'); }); -> Option AQuick Check:
Middleware + strict equality + 403 Forbidden = correct pattern [OK]
- Using == instead of ===
- Sending wrong status codes like 404 or 401
- Not using middleware pattern for ownership check
