Bird
Raised Fist0
Expressframework~20 mins

Middleware composition for auth layers in Express - Practice Problems & Coding Challenges

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Challenge - 5 Problems
🎖️
Middleware Mastery
Get all challenges correct to earn this badge!
Test your skills under time pressure!
component_behavior
intermediate
2:00remaining
What happens when multiple auth middlewares are composed in Express?

Consider two middleware functions authA and authB used in sequence in an Express route. What will happen if authA calls next() without error, but authB sends a response and does not call next()?

Express
const authA = (req, res, next) => { console.log('authA'); next(); };
const authB = (req, res, next) => { console.log('authB'); res.status(401).send('Unauthorized'); };
app.get('/secure', authA, authB, (req, res) => { res.send('Welcome'); });
AAn error is thrown because authB does not call next().
BBoth middlewares run and then the final handler sends 'Welcome'.
CThe response 'Unauthorized' is sent and the final handler is never called.
DThe request hangs because authB neither calls next() nor ends the response.
Attempts:
2 left
💡 Hint

Think about what happens when a middleware sends a response and does not call next().

📝 Syntax
intermediate
2:00remaining
Which middleware composition syntax correctly applies two auth middlewares in Express?

Given two middleware functions auth1 and auth2, which option correctly applies both to a route /dashboard so that auth1 runs before auth2?

Aapp.get('/dashboard', auth1 && auth2, (req, res) => { res.send('Dashboard'); });
Bapp.get('/dashboard', auth1, auth2, (req, res) => { res.send('Dashboard'); });
Capp.get('/dashboard', [auth2, auth1], (req, res) => { res.send('Dashboard'); });
Dapp.get('/dashboard', auth1 || auth2, (req, res) => { res.send('Dashboard'); });
Attempts:
2 left
💡 Hint

Remember how Express accepts multiple middleware functions as separate arguments.

🔧 Debug
advanced
2:00remaining
Why does this composed auth middleware cause the request to hang?

Examine the following middleware composition. Why does the request to /profile never complete?

Express
const checkToken = (req, res, next) => { if (!req.headers.token) { res.status(401).send('No token'); } else { next(); } };
const verifyUser = (req, res, next) => { if (req.headers.token === 'valid') { next(); } else { res.status(401).send('Invalid token'); } };
app.get('/profile', checkToken, verifyUser, (req, res) => { res.send('User Profile'); });
ABecause verifyUser does not call next() or send a response when token is invalid, causing the request to hang.
BBecause checkToken sends a response and calls next(), causing double responses.
CBecause the route handler is missing a response call.
DBecause the middleware functions are in the wrong order.
Attempts:
2 left
💡 Hint

Look at all code paths in verifyUser and see if next() or res.send() is always called.

state_output
advanced
2:00remaining
What is the value of req.user after this middleware composition?

Given these two middlewares, what will be the value of req.user in the final handler?

Express
const authA = (req, res, next) => { req.user = { id: 1, role: 'user' }; next(); };
const authB = (req, res, next) => { if (req.user.role === 'user') { req.user.permissions = ['read']; } next(); };
app.get('/data', authA, authB, (req, res) => { res.json(req.user); });
A{"id":1,"role":"user","permissions":["read"]}
B{"id":1,"role":"user"}
Cundefined
D{"permissions":["read"]}
Attempts:
2 left
💡 Hint

Consider how req.user is modified by each middleware.

🧠 Conceptual
expert
2:00remaining
Which statement best describes middleware composition for layered authentication in Express?

When building layered authentication with multiple middleware functions in Express, which statement is true about their composition and execution?

AMiddleware functions can only be composed using arrays, not as separate arguments.
BMiddleware functions run in parallel and the first to send a response ends the request.
CMiddleware functions automatically merge their results into a single object passed to the final handler.
DMiddleware functions run in the order they are declared; each must call next() to pass control, or send a response to end the chain.
Attempts:
2 left
💡 Hint

Think about how Express processes middleware functions sequentially.

Practice

(1/5)
1. What is the main purpose of composing multiple middleware functions for authentication in Express?
easy
A. To run several small auth checks in order before allowing access
B. To combine all auth logic into one big function
C. To skip authentication for faster response
D. To handle database queries inside middleware

Solution

  1. Step 1: Understand middleware composition

    Middleware composition means running multiple middleware functions one after another.
  2. Step 2: Purpose in auth layers

    Using multiple small auth checks in order helps keep code clean and checks each condition separately.
  3. Final Answer:

    To run several small auth checks in order before allowing access -> Option A
  4. Quick Check:

    Middleware composition = multiple small auth checks [OK]
Hint: Think of middleware as a chain of small checks [OK]
Common Mistakes:
  • Thinking all auth logic must be in one function
  • Believing middleware skips auth
  • Confusing middleware with database queries
2. Which of the following is the correct way to apply two middleware functions checkToken and checkRole to an Express route using an array?
easy
A. app.get('/admin', checkToken, checkRole, (req, res) => res.send('OK'))
B. app.get('/admin', checkToken && checkRole, (req, res) => res.send('OK'))
C. app.get('/admin', [checkToken, checkRole], (req, res) => res.send('OK'))
D. app.get('/admin', checkToken || checkRole, (req, res) => res.send('OK'))

Solution

  1. Step 1: Understand Express middleware syntax

    Express accepts multiple middleware as an array or separate arguments before the handler. This question specifies using an array.
  2. Step 2: Check each option

    A uses separate arguments. B and D use logical operators which are invalid here. C correctly uses an array.
  3. Final Answer:

    app.get('/admin', [checkToken, checkRole], (req, res) => res.send('OK')) -> Option C
  4. Quick Check:

    Middleware array syntax = app.get('/admin', [checkToken, checkRole], (req, res) => res.send('OK')) [OK]
Hint: Use arrays to group middleware in routes [OK]
Common Mistakes:
  • Using logical operators instead of arrays
  • Passing middleware as a single combined expression
  • Forgetting to include middleware before handler
3. Given the middleware functions below, what will be the response when a request with req.user = { role: 'user' } hits the route?
function checkToken(req, res, next) {
  if (!req.user) return res.status(401).send('No token');
  next();
}

function checkAdmin(req, res, next) {
  if (req.user.role !== 'admin') return res.status(403).send('Forbidden');
  next();
}

app.get('/secure', [checkToken, checkAdmin], (req, res) => res.send('Welcome admin'));
medium
A. Welcome admin
B. Forbidden
C. No token
D. Internal Server Error

Solution

  1. Step 1: Analyze checkToken middleware

    It checks if req.user exists. Here req.user is { role: 'user' }, so it passes and calls next().
  2. Step 2: Analyze checkAdmin middleware

    It checks if req.user.role is 'admin'. Here it is 'user', so it returns 403 Forbidden response.
  3. Final Answer:

    Forbidden -> Option B
  4. Quick Check:

    Role check fails = Forbidden [OK]
Hint: Check middleware order and conditions carefully [OK]
Common Mistakes:
  • Assuming role 'user' passes admin check
  • Ignoring middleware that sends response early
  • Confusing status codes
4. Identify the error in this middleware composition code:
function auth(req, res, next) {
  if (!req.headers.authorization) {
    res.status(401).send('Unauthorized');
  }
  next();
}

app.get('/data', auth, (req, res) => res.send('Data'));
medium
A. Missing return after sending 401 response, so next() runs anyway
B. Middleware should be async function
C. Route handler missing res.end() call
D. Authorization header check should be in route handler

Solution

  1. Step 1: Check middleware flow

    If authorization header is missing, it sends 401 but does not stop execution.
  2. Step 2: Identify missing return

    Without return after res.status(401).send(), next() is called anyway, causing route handler to run incorrectly.
  3. Final Answer:

    Missing return after sending 401 response, so next() runs anyway -> Option A
  4. Quick Check:

    Send response must stop middleware with return [OK]
Hint: Always return after sending response in middleware [OK]
Common Mistakes:
  • Calling next() after sending response
  • Thinking async needed for simple middleware
  • Putting auth logic in route handler
5. You want to create a reusable middleware group for routes that require both token validation and admin role check. Which is the best way to compose and apply these middlewares in Express?
hard
A. Use a global app.use() for all routes regardless of auth needs
B. Create a single middleware combining both checks and use it in routes
C. Call each middleware manually inside the route handler function
D. Use an array of separate middlewares and apply the array to routes

Solution

  1. Step 1: Understand middleware grouping

    Grouping middlewares as an array keeps each check separate and reusable.
  2. Step 2: Compare options

    Use an array of separate middlewares and apply the array to routes uses an array of middlewares applied to routes, which is clean and composable. Create a single middleware combining both checks and use it in routes merges checks into one, losing modularity. Call each middleware manually inside the route handler function is manual and error-prone. Use a global app.use() for all routes regardless of auth needs applies auth globally, which is not selective.
  3. Final Answer:

    Use an array of separate middlewares and apply the array to routes -> Option D
  4. Quick Check:

    Middleware arrays = reusable and clean [OK]
Hint: Group middlewares in arrays for reuse [OK]
Common Mistakes:
  • Combining all logic into one middleware
  • Calling middleware inside handlers manually
  • Applying auth globally without route control