Bird
Raised Fist0
Remixframework~20 mins

Role-based access control in Remix - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Role-based Access Control Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ component_behavior
intermediate
2:00remaining
What is the output of this Remix loader with role check?

Consider this Remix loader function that checks user roles before returning data.

export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user || !user.roles.includes('admin')) {
    throw new Response('Forbidden', { status: 403 });
  }
  return json({ message: 'Welcome, admin!' });
}

What will the loader return if the user has roles: ['user', 'editor']?

Remix
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user || !user.roles.includes('admin')) {
    throw new Response('Forbidden', { status: 403 });
  }
  return json({ message: 'Welcome, admin!' });
}
AA runtime error because roles is undefined
BA JSON response with { message: 'Welcome, admin!' }
CA Response with status 403 and body 'Forbidden'
DA JSON response with { message: 'Welcome, user!' }
Attempts:
2 left
💡 Hint

Check the role check condition and what happens if 'admin' role is missing.

❓ state_output
intermediate
2:00remaining
What is the rendered output of this Remix component with role-based UI?

This React component in Remix shows different UI based on user roles.

export default function Dashboard({ user }) {
  return (
    <div>
      {user.roles.includes('admin') ? (
        <h1>Admin Panel</h1>
      ) : (
        <h1>User Dashboard</h1>
      )}
    </div>
  );
}

If user.roles is ['editor'], what will be rendered?

Remix
export default function Dashboard({ user }) {
  return (
    <div>
      {user.roles.includes('admin') ? (
        <h1>Admin Panel</h1>
      ) : (
        <h1>User Dashboard</h1>
      )}
    </div>
  );
}
A<div><h1>User Dashboard</h1></div>
B<div></div>
C<div><h1>Admin Panel</h1></div>
DComponent throws an error because roles is undefined
Attempts:
2 left
💡 Hint

Check if 'admin' is included in the roles array.

📝 Syntax
advanced
2:00remaining
Which option correctly implements role check in Remix loader?

Choose the correct Remix loader function that returns 401 if user role is not 'member'.

A
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user.roles.includes('member')) {
    throw new Response('Unauthorized', { status: 401 });
  }
  return json({ data: 'Member content' });
}
B
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (user.roles !== 'member') {
    throw new Response('Unauthorized', { status: 401 });
  }
  return json({ data: 'Member content' });
}
C
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user.roles.includes(member)) {
    throw new Response('Unauthorized', { status: 401 });
  }
  return json({ data: 'Member content' });
}
D
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user.roles.contains('member')) {
    throw new Response('Unauthorized', { status: 401 });
  }
  return json({ data: 'Member content' });
}
Attempts:
2 left
💡 Hint

Check correct method to check if array includes a string.

🔧 Debug
advanced
2:00remaining
Why does this Remix route throw a 500 error on role check?

Given this loader code:

export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user.roles.includes('admin')) {
    return new Response('Forbidden', { status: 403 });
  }
  return json({ secret: 'data' });
}

But the app throws a 500 error instead of 403 when user has no roles. Why?

Remix
export async function loader({ request }) {
  const user = await getUserFromRequest(request);
  if (!user.roles.includes('admin')) {
    return new Response('Forbidden', { status: 403 });
  }
  return json({ secret: 'data' });
}
AThe roles array does not include 'admin', so it returns 403 correctly
Buser is null or undefined, so accessing roles causes a TypeError
Cjson() is not imported, causing a ReferenceError
DResponse with status 403 is not allowed in loader, must throw instead
Attempts:
2 left
💡 Hint

Consider what happens if user is null or missing roles property.

🧠 Conceptual
expert
3:00remaining
Which approach best secures Remix routes with role-based access control?

In Remix, you want to restrict access to certain routes based on user roles. Which approach is the most secure and recommended?

ARender UI conditionally in the component based on user roles, hiding restricted content
BStore user roles in localStorage and check them in the component before rendering
CUse client-side JavaScript to redirect unauthorized users after page loads
DCheck user roles in the loader function and throw Response with 403 if unauthorized
Attempts:
2 left
💡 Hint

Think about where access control should happen to prevent unauthorized data exposure.

Practice

(1/5)
1. What is the main purpose of role-based access control (RBAC) in a Remix app?
easy
A. To store user passwords securely
B. To speed up page loading times
C. To style components differently for each user
D. To limit user actions based on their assigned roles

Solution

  1. Step 1: Understand RBAC concept

    RBAC means users get permissions based on their roles, like admin or guest.
  2. Step 2: Identify RBAC purpose in Remix

    In Remix, RBAC controls what pages or data a user can access depending on their role.
  3. Final Answer:

    To limit user actions based on their assigned roles -> Option D
  4. Quick Check:

    RBAC = limit actions by role [OK]
Hint: RBAC controls what users can do by their roles [OK]
Common Mistakes:
  • Confusing RBAC with performance optimization
  • Thinking RBAC is for styling UI
  • Mixing RBAC with password security
2. Which code snippet correctly checks a user's role in a Remix loader function?
easy
A. const user = await getUser(request); if (user.role !== 'admin') throw new Response('Forbidden', { status: 403 });
B. const user = getUser(request); if (user.role == 'admin') return redirect('/admin');
C. const user = await getUser(request); if (user.role = 'admin') return null;
D. const user = await getUser(request); if (user.role !== 'admin') return 'Access granted';

Solution

  1. Step 1: Identify async user fetching

    Using await with getUser(request) is correct to get user info asynchronously.
  2. Step 2: Check role comparison and response

    const user = await getUser(request); if (user.role !== 'admin') throw new Response('Forbidden', { status: 403 }); correctly compares role with !== and throws 403 response if not admin.
  3. Final Answer:

    const user = await getUser(request); if (user.role !== 'admin') throw new Response('Forbidden', { status: 403 }); -> Option A
  4. Quick Check:

    Async fetch + role check + 403 response = const user = await getUser(request); if (user.role !== 'admin') throw new Response('Forbidden', { status: 403 }); [OK]
Hint: Use await and strict role check with Response for access control [OK]
Common Mistakes:
  • Forgetting await when calling async functions
  • Using assignment (=) instead of comparison (== or !==)
  • Returning wrong responses on unauthorized access
3. Given this Remix loader code, what happens if a user with role 'user' tries to access the page?
export async function loader({ request }) {
  const user = await getUser(request);
  if (user.role !== 'admin') {
    return redirect('/login');
  }
  return json({ message: 'Welcome Admin' });
}
medium
A. The loader returns null and page is blank
B. The user is redirected to '/login' page
C. The page throws a 403 Forbidden error
D. The user sees 'Welcome Admin' message

Solution

  1. Step 1: Analyze role check condition

    The code redirects if user.role is not 'admin'. A 'user' role is not 'admin'.
  2. Step 2: Determine loader behavior for 'user' role

    Since role is 'user', the redirect('/login') runs, sending user to login page.
  3. Final Answer:

    The user is redirected to '/login' page -> Option B
  4. Quick Check:

    Non-admin role triggers redirect [OK]
Hint: Non-admin roles trigger redirect to login [OK]
Common Mistakes:
  • Thinking user sees admin message
  • Assuming 403 error instead of redirect
  • Ignoring redirect and expecting blank page
4. Identify the error in this Remix loader code for role-based access control:
export async function loader({ request }) {
  const user = getUser(request);
  if (user.role !== 'admin') {
    throw new Response('Unauthorized', { status: 401 });
  }
  return json({ data: 'Secret Data' });
}
medium
A. Missing await before getUser causing user to be a Promise
B. Incorrect status code; should be 403 instead of 401
C. Throwing Response is not allowed in loader functions
D. json() function is not imported from Remix

Solution

  1. Step 1: Check async function usage

    getUser is likely async, so missing await means user is a Promise, not user data.
  2. Step 2: Understand impact of missing await

    Without await, user.role is undefined, causing runtime error or wrong behavior.
  3. Final Answer:

    Missing await before getUser causing user to be a Promise -> Option A
  4. Quick Check:

    Async call missing await = Missing await before getUser causing user to be a Promise [OK]
Hint: Always await async calls before accessing properties [OK]
Common Mistakes:
  • Ignoring missing await and expecting user object
  • Confusing 401 and 403 status codes
  • Thinking throwing Response is invalid in loader
5. You want to restrict a Remix route so only users with roles 'admin' or 'manager' can access it. Which loader code correctly implements this with a redirect for others?
export async function loader({ request }) {
  const user = await getUser(request);
  // Fill in the role check
}
hard
A. if (user.role === 'admin' || user.role === 'manager') return redirect('/not-authorized');
B. if (user.role !== 'admin' || user.role !== 'manager') return redirect('/not-authorized');
C. if (user.role !== 'admin' && user.role !== 'manager') return redirect('/not-authorized');
D. if (user.role === 'admin' && user.role === 'manager') return redirect('/not-authorized');

Solution

  1. Step 1: Understand role conditions for access

    Users allowed are 'admin' or 'manager', so others must be redirected.
  2. Step 2: Choose correct logical operator

    Use AND (&&) with !== to check if user is neither 'admin' nor 'manager'.
  3. Step 3: Verify redirect logic

    If user role is not admin and not manager, redirect to '/not-authorized'.
  4. Final Answer:

    if (user.role !== 'admin' && user.role !== 'manager') return redirect('/not-authorized'); -> Option C
  5. Quick Check:

    Redirect if not admin AND not manager = if (user.role !== 'admin' && user.role !== 'manager') return redirect('/not-authorized'); [OK]
Hint: Use && with !== to exclude multiple roles [OK]
Common Mistakes:
  • Using || instead of && causing wrong redirects
  • Checking for both roles with && equality (impossible)
  • Redirecting allowed roles instead of others
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard