Swizec Teller - a geek with a hatswizec.com

    Add granular role-based access to your JAMStack app

    Say you've got a JAMStack app with authentication. Works great, loads fast, some pages need login.

    That part's easy with something like useAuth, a manual integration with Auth0, or any number of 3rd party providers.

    You have some code that asks "Is this user logged in?". Show them the page or some "Please Login" interface. There's a button somewhere that starts the login flow.

    Something like this for example:

    Now what if you want to add an area that only some users have access to? How would you do that?


    Roles are the answer

    User roles are the simplest approach to granular permissions. Everything else I've tried gets out of hand super fast.

    Is this user a student or not? Access to course.

    Does this user have module X? Access.

    You can go as detailed as you want. Admin vs. not-admin is often the first and only role-based permission. Some apps eventually need more.

    The more roles you add, the more complex it all gets. But trust me, roles are the only approach that scales at all.

    A friend of mine lived through a horror story where it took an entire team and 3 years to build a robust permission system for a large app. 3 years ๐Ÿ˜ณ

    Roles are way easier.

    With useAuth 0.7.0

    Click through for source
    Click through for source

    Hot off the presses, useAuth 0.7.0 adds a helper to check for user roles. Still just for Auth0, soon for others I promise.

    Here's what you do:

    Click through for source
    Click through for source

    And that's pretty much it, really.

    The isAuthorized method verifies your user is currently logged-in and that they have the Student role.

    You'll need to add a rule to your Auth0 config as well. They don't send this info by default. Don't know why, I tried everything. ๐Ÿ˜”

    Click through for source
    Click through for source

    And you have to make sure that namespace matches a config in the <AuthProvider> that wraps your whole component tree. That's how useAuth hooks into the React context and keeps track of everything.

    Click through for source
    Click through for source

    No, I don't know why the namespace needs to be a full URL. The Auth0 documentation isn't clear on that part and I was unable to hunt down details on the forums.

    How do you get roles onto users in the first place?

    Ah yes, adding roles to users. That part is a little tricky.

    Here's an article I wrote on Connecting Gumroad to Auth0 for paywalled JAMStack apps โค๏ธ

    The TL;DR is that your checkout provider triggers your cloud function through a webhook and that adds a role to your user. You can also do it manually.

    I use Gumroad, Stripe works too. I use AWS Lambda, a Netlify or Vercel cloud function should be fine.

    Click through for source
    Click through for source

    Full details in the Connecting Gumroad to Auth0 for paywalled JAMStack apps article.

    What if there's many roles to check?

    This is where life gets tricky. The more roles you have, the trickier. ๐Ÿ˜…

    Somewhere in your code there's going to be a component like this.

    Click through for source
    Click through for source

    Like I said, messy. And there's nothing you can do about it.

    Might look a little better, if you bake it into your router and use individual checks on individual pages. But the complexity remains. Somewhere something has to check this stuff. ๐Ÿคทโ€โ™€๏ธ

    Using different components for different content pages makes it easier โ€“ check authorization in the component itself. But I'm using some MDX shenanigans and the <Content> component doesn't know what it's showing.

    So a nice big truth table is what I gotta do.

    Click through for source
    Click through for source

    What about without useAuth?

    Same principle my friend. You get the role for your user and you ask "Does this role have access to this page?"



    PS: the coding-on-a-ipad workflow I suggested on Friday totally worked ๐Ÿค˜

    Click through for source
    Click through for source

    Did you enjoy this article?

    Published on May 18th, 2020 in Front End, Technical

    Learned something new?
    Want to become an expert?

    Here's how it works ๐Ÿ‘‡

    Leave your email and I'll send you thoughtfully written emails every week about React, JavaScript, and your career. Lessons learned over 20 years in the industry working with companies ranging from tiny startups to Fortune5 behemoths.

    Join Swizec's Newsletter

    And get thoughtful letters ๐Ÿ’Œ on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.

    "Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. ๐Ÿ‘Œ"

    ~ Ashish Kumar

    Join over 14,000 engineers just like you already improving their careers with my letters, workshops, courses, and talks. โœŒ๏ธ

    Have a burning question that you think I can answer?ย I don't have all of the answers, but I have some! Hit me up on twitter or book a 30min ama for in-depth help.

    Ready to Stop copy pasting D3 examples and create data visualizations of your own? ย Learn how to build scalable dataviz components your whole team can understand with React for Data Visualization

    Curious about Serverless and the modern backend? Check out Serverless Handbook, modern backend for the frontend engineer.

    Ready to learn how it all fits together and build a modern webapp from scratch? Learn how to launch a webapp and make your first ๐Ÿ’ฐ on the side with ServerlessReact.Dev

    Want to brush up on your modern JavaScript syntax?ย Check out my interactive cheatsheet: es6cheatsheet.com

    By the way, just in case no one has told you it yet today: I love and appreciate you for who you areย โค๏ธ

    Created by Swizec with โค๏ธ