Router Set: distinction between unauthenticated vs not having a role

For router Set, it looks like both the unauthenticated and not-having-the-right-role cases have the same redirection target. For most application, this would be the sign-in page. However, this makes the ux confusing.

To workaround this, I’m currently handling roles with a HasRoleLayout.

Is there an interest to supporting an optional but separate redirection (say to a 403 page for missing roles)? If so, I’d be glad to contribute.

On the sign-in page you could check if the user is already logged in, and if so check their roles. Then you could display the correct error message and UI depending on what roles they have.

Or you have a separate page for that logic that you use for the unauthenticated prop. And if the user isn’t logged in you can do a manual redirect to the sign-in page.

I’m personally not a big fan of adding too many props to our router components (routes, sets, etc). But I think your question highlights a need for what I call “route guards”. I.e. a more powerful/flexible way to determine who can access what routes. It’s been discussed here:

And your exact use case has been discussed in the linked RFC issue:

1 Like

useGuard looks pretty cool. I’ll give it a try.

My original thought was for unauthenticated to get redirected to sign-in and roleMismatch to the ForbiddenPage. However, a couple hours after posting, I realized that displaying an error component would make for better UX than redirecting to another page. So useGuard and ErrorBoundary would work quite well for this.

Right now, I’m handling it with a wrap that uses hasRole and either render a fallback error component or {children}. Something like this

const AdminLayout = ({ children }: AdminLayoutProps) => {
  const { hasRole } = useAuth()
  const allowedRoles = ['ADMIN']

  if (!hasRole(allowedRoles)) {
    return (
      <div className="container mx-auto max-w-lg pt-8">
        <ErrorAlert type="access-denied" />

  return (

My current thinking is if we have to handle roleMismatch handling ourselves, then that takes away the main reason for roles specification in Set to exist in the first place. Imo a cleaner DX experience should have this error handling baked into the Set implementation, perhaps with a rolesMismatch parameter that takes a fallback component. Thoughts?

That’s a valid point. Let me think about that one for a bit.

1 Like

I brought this up with the rest of the core team the day after we talked about it here. Just forgot to report back. Sorry!

Unfortunately there wasn’t much interest in the question. So until more users have input on this nothing is probably going to happen.