skip to content

Auth and RBAC in multi-tenant React apps

One of the first challenges many web apps face is how to manage user authentication. Julianna Lamb will show us how to use Stytch and its pre-built UI components to add auth to a React + Express app quickly.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Hello, everyone, and welcome to another episode of Learn With Jason. Today on the show, we're going to be having a whole lot of fun learning about something that I think is really important if you've ever considered being a, you know, solo founder, if you've considered setting up a side hustle, if you want to start your own business. This is the kind of stuff that is going to show up no matter what kind of business you're building. To help us learn about t I'm bringing to the show Julianna Lamb. For folks who aren't familiar with you and your work, can you give us a bit of a breakdown?

JULIANNA: Yeah, I'm the co-founder and CTO of Stytch. Stytch is a modern platform for authentication and fraud detection and prevention. My co-founder and I met working together at Plaid. I was on their engineering team, and he was on the product team. We ended up building out a bunch of auth experiences in-house there. I did it again at another company and decided to do it for a third and final time so that other people didn't have to suffer through all of the annoying pieces of authentication and fraud detection and prevention. We started Stytch about four years ago. We have a variety of different auth products, sort of different platforms, whether you're building a consumer app, a B2B app, and then we have a fraud suite as well. So, excited to show off the B2B platform today and talk a little bit about how you can build authentication into multitenant applications.

JASON: Yes, okay. And so before we get into the actual building, I have a couple questions because I feel like whenever I start talking about the idea of SaaS, there are a couple phrases where I don't feel like I know what they are or don't have the right words. So I want to dig into this. You just said multitenancy. Can you talk about what that is and how is that different from other approaches to building apps?

JULIANNA: Yeah, if you're building for consumers, you're often building a single-tenant app where all of those users are in the same sort of database. It's one sort of organization that you have for all of your end users. In B2B, you're often using a multitenant architecture, meaning you have sort of different tenants for each of your different customers so that you can segment data, put different requirements in place for those organizations because each of your customers is essentially a different entity that you're supporting, and each of those has their own pool of users. So instead of having that sort of one conjoined user pool like you might in a consumer context, you have sort of those segmented user pools that in the case of B2B are often tied to your customers and their employees.

JASON: Gotcha. Okay. So that would be like when I sign up for Twitter, that's a single-tenant app. So I'm one of the millions of Twitter users. We're all on the same website. We're all sharing the same UIs. But when I go into, say, my Netlify account or my Google account -- sorry, my Google for work, not Gmail -- when I log in, I have my multiple accounts. So that's a multitenant then. So in Netlify, for example, I log in and I have my account. In that, I have a few collaborators. Then I have access to another account, and in that one, it's just me and one other person. I have access to one of their sites but not all of them. So it's kind of like I'm moving in between an organization, basically. I'm logging into the organization's instance of Netlify as opposed to the global Netlify app. Is that right?

JULIANNA: Yeah, that's exactly right.

JASON: Okay. So this concept of organizations and users and stuff, I feel like this can get a little bit -- it can get kind of challenging for devs as they work on -- you know, what do you focus on? Should I be building user accounts? The users create orgs and you attach them to those orgs. Do you do the orgs first? What's the architecture I should be looking for as a developer to make sure I don't tie myself in knots later on?

JULIANNA: Yeah, it's a really good question. That sort of consumer example, the user is the top-level entity, right. That's sort of the object you care about. They're setting their own settings, all of that. When we're talking about the B2B use case, it's often the organization that should be sort of the primary object that you're building your data model on top of. If you think about it, your customers are going to be the sort of persistent entities, and their users, their employees, they might come and go. You might need to be able to access multiple organizations, like that Netlify example you gave. So the user is something that has membership to those organizations. So if you start with a user-first data model in B2B, you end up kind of having to reverse engineer this and build a lot of logic. Like how do you share user accounts? Are you able to have multiple accounts? Do you have to start doing hackie things like or whatever URL you have. Or can you do it in a way where you have that organization first, and they can then have their own settings. Maybe one organization wants to require you sign in with 2FA. The other is fine if it's just like O-auth log in. All of that can spiral. The organization should be in control of those settings, should be in control of who belongs to their organization. It's not the user that's the primary thing you're dealing with there.

JASON: Gotcha. So, that makes sense. As you were talking, I was thinking about the fact that on my Netlify account, the organization is -- like, I'm the admin there. I have control over everything. When I log into, for example, earlier this week I was working on a site with Lynn Fisher and got added to her Netlify account, where I'm not an admin. I don't have any privileges except for the one site I'm added to. So if my user was the primary object, how would you store -- so if my user is the primary object and I have an organization's array with permission array, it seems like that would be really hard, versus having the organization be at the top and you add the users. So, okay. This makes sense. I like this because it helps me disambiguate something. There's a lot of jargons that thrown around. People will say B2B, B2C, multitenant, all these words. Ultimately, what we're doing when we think about that is we're thinking about who is the primary customer. So in Netlify, the primary customer is the business or the organization that is getting the account. Then they grant users access to that account. Whereas in Twitter, which would be like a B2C example, you have users, and there is no concept of an organization really. Not in any account-base sense of the word, you know. So you end up with this -- it's just a way of thinking about who's really the decision maker, who's structuring the -- like you mentioned settings and things like that. Then architecting the app with that permission hierarchy in mind.

JULIANNA: Yeah, that's exactly right. That's a really good way to describe it.

JASON: Excellent. Okay. Now, that's helpful because it's one of those -- you know, I always get kind of nervous that I'm using words wrong. Being able to think about it, the words are just the way that we organize the information so we get a good result for what we're building. Okay, cool. The other one that I hear a lot that I want to make sure that we're clear on is RBAC, which is short for role-based access control.

JULIANNA: That's right.

JASON: So when we talk about this, I've seen a bunch of different models for this where there's roles. I think PBAC was one, permission-based access control. There's a bunch of other ones I've seen as well. What are we ultimately choosing when we kind of lean into a role-based versus permissions-based versus whatever-based access control?

JULIANNA: Yeah, so for role-based access controls, you're really starting with sort of the role as the primary thing. The permissions that are sort of attached to that role will then be consistent across users. So if I am an admin, for example, that probably gives me permission to take about every action I could in a dashboard. It sort of gives me those superpowers. But then if I'm maybe an ordinary member, I might not have permissions, for example, to update billing settings or maybe to invite other users kind of just depending on what application you're building and what makes sense. Oftentimes, there's sort of a set number of roles that you want to enable for your product so that people can have different access levels. Then the access then is sort of determined on, you know, a per resource or per page or whatever your breakdown is. You can customize that for the functionality your app supports and say this is what an admin gets access to. These are their permissions. This is what a member gets access to, their permissions. Maybe you have read-only, where they can view things but don't have any write permissions. Sort of coupling those permissions and roles together.

JASON: Got it, got it, got it. Okay, cool. So, today what I would love to learn is if I want to build my own SaaS app, I'm going to need all of these things. I'm going to need the ability to let people log in. I probably want them to be able to log in with email/password or O-auth or some combination of those things. Maybe there's other stuff we can try. Then I also need -- like, I want it to be a B2B app. My thought is that anything I would build, I would probably want you to be able to collaborate with something but in that organization-based thing where you can group your projects based on what org owns them. So we're probably looking at the B2B, the org-first architecture. I tend to write a lot of JavaScript, so I'm thinking -- is there any -- so, we're going to be using Stytch today. So maybe before I get too deep into the weeds here, let's talk a little bit about what Stytch is. You kind of gave us the high level. So maybe what I'll ask is if Stytch is going to give us the org-first structure and has got the RBAC, the auth, fraud detection, and a handful of other features, is that for a certain stack? Do I need to write JavaScript to use Stytch? Can I use it with anything? What are the guidelines for it?

JULIANNA: Yeah, so there are a number of different ways that you can integrate with Stytch. We are API first. So you can always integrate just directly with our APIs, whatever language. If you can make HTTP requests from it, you can integrate Stytch. We also have some backend SDKs that wrap that API to make it more ergonomic. But really, any language can be supported. You might just have to do a little more leg work to integrate that into a language that we don't have something pre-built for. But we also have client-side SDKs so that we can handle, you know, more of the logic for you. Things like setting sessions, refreshing sessions, all of that. So we have two options there on the client-side integration. You can either do a headless integration, so if you really want to own all the of the UI/UX of your app, you can do a client-side integration and basically use the headless SDK so that you're still getting that out of the box session management, handling all the API calls but owning the UI. A lot of times you want to get up and running really quickly, right, like building a log-in box is not super interesting and differentiated in most cases. And so we have frontend components as well. And we have a couple options there. We have just a plain JavaScript SDK. We have a Next.js SDK. So those are our options on the frontend. In terms of the backend, it's limitless in terms of what languages you're using.

JASON: Got it. Okay. Cool. And so today, then, if I wanted to build my frontend in React and do the backend in Node and Express, that would be okay?

JULIANNA: Yeah, we can use the frontend components in the React SDK, and we have a Node backend SDK we can integrate.

JASON: Excellent. All right. Well, I think at this point, any other questions I have are going to be easier answered by showing some code. So why don't I quickly take us over here. Let me throw this banner up as well. Then first and foremost, if you are not already following Julianna, you should be. Get over there on Twitter and give this account a follow. And we're talking today about Stytch. So, make sure that you go and check it out today. Getting some compliments on your pups.

JULIANNA: Very important.

JASON: Yes, that is a very cute dog. Okay. And let's see. What else we got here? I have -- oh, one other thing I need to do, which is to give a quick shout out to our captioner. We've got Rachel here from White Coat Captioning. That is available at the URL there at the bottom of the screen. Let me also throw that into the chat. There it goes. Okay. So if you want to get the captions, you can get to those there. That is made possible through the support of our sponsors. We've got Nx and Netlify both kicking in to make the show more accessible to more people, which I very much appreciate. Okay. So, with that being said, Julianna, if I want to get going here, what should I do first?

JULIANNA: Yeah, let's start at This is the Stytch dashboard where you can do, you know, all of your configuration, get API keys, all of that. And when you're creating a project, we basically decided at that point that it's going to be a consumer authentication project, where that user is the primary sort of object in the data model, or do you want to do a B2B app where it's an organization-first data model.

JASON: And this is cool because I feel like in other apps that I've used that are kind of in the same space, I haven't seen this differentiation where you've got -- like you get to choose is this a B2C or B2B app. So that's really cool. Okay. So I have completed -- I created a new project. And now I'm ready. I think.

JULIANNA: Sweet. Let's maybe get started by spinning up the app that we're going to be integrating Stytch into. Then we can go from there.

JASON: All right. So what I'm going to do is I'm going to head into my GitHub. Then we're going to make a directory called Stytch B2B SaaS. Apparently I already have one of those. So we're going to call this LWJ. Then we're going to get into that. And can I use Vite? Is that all right?

JULIANNA: Yeah, let's do that.

JASON: Okay. So I'm going to do create Vite at latest. We'll use React today. TypeScript. Here's our brand-new, no-features Vite project. I'm going to open this folder I just created. Okay. So, we've got that now. Inside, I have the basics. It's an app.tsx. It has all this good stuff in here. I'm going to drop all of this out, and instead, we'll say build an app. Oh, I stopped my server when I opened that folder. There we go. Okay. So this is our baseline app here. I might just start clearing everything out because I don't think we need any of this yet. We'll start as simple as we possibly can. We're not using any of this. Let's just clean this thing up. Our main.tsx has all the basics there. Okay. So, what's my next step here?

JULIANNA: Sweet. So, let's go to the Stytch docs, and we have some quick start guides there. We can kind of follow, they'll give us some code snippets to help make this easy.

JASON: Okay. So here's the docs.

JULIANNA: If you click on docs there under B2B SaaS -- exactly. So, we'll have kind of an overview and all of that here. What we're going to be doing today is we want to build an O-auth integration with what we call our discovery flow. So that means that the experience of you can log in and see all the organizations that you can join, that's what that discovery flow means. So if you scroll down under authentication there -- under UI components, sorry. Implement the discovery flow. Yeah, exactly. So this will be a guide for getting that UI integration up and running. The other thing we might want to take a look at is if you scroll up a little bit more on the side bar on the left-hand side there, we can do a React quick start, too, just to get the basics of Stytch integrated. So, under frameworks, there's a React quick start that'll tell us how to sort of do the basic Stytch integration.

JASON: Got it.

JULIANNA: So, you can start there and get Stytch installed.

JASON: Okay. So, let's see. We've got to actually stop the server first. So we're installing the Stytch package. I need to do a .env. I can do that over here. I'm going to need the Stytch --

JULIANNA: Yeah, we can use test for this. You'll need that public token to instantiate the client-side SDK.

JASON: Okay. And for me to get that public token, I'm going to go to --

JULIANNA: On the left, API keys. Yep. And down at the bottom.

JASON: Okay. So here's the public token. This one is okay to share because it says it's public.

JULIANNA: Yeah, it's meant to be something that can be visible client side.

JASON: Got it. And then back out here, we are -- so we've set that up. Now we need to configure the Stytch SDK settings. Enable frontend SDKs in your Stytch dashboard. And frontend SDKs. I can enable the SDK with great. I need to edit this because that's the wrong port. So that instead is going to be 5173 for Vite. All right. Then do I need any of these others here?

JULIANNA: You're going to want that switched on so when you're logging in, signing up, you can create a new organization to join.

JASON: Okay. Do I need member actions and permissions?

JULIANNA: Umm... yeah, let's turn that on too.

JASON: Okay. We have email magic links, SSO. What is this time-based one-time passwords? Is that right?

JULIANNA: Yeah, so like Google authenticator-type passwords.

JASON: Got it. O-auth passwords and one-time SMS passwords. This, I don't need to worry about, right?

JULIANNA: Yeah, though are all kind of advanced settings that you can configure, but we don't need them out of the box.

JASON: Got it, got it. Okay. So now that we're set up here -- oh, if I would have come back to the docs, it would have said turn this on. So then we're going to create the UI client. This will happen it looks like in the root of our project. I'm going to grab this out, and we'll head into our main.tsx. Then we're going to grab our Stytch client. Then we're going to actually use that provider. Okay. So, just recapping here. We pulled in the React provider and pulled in the B2B UI client. So, the reason it's B2B is because this is like flipping the whole architecture where it's org first versus user first.

JULIANNA: Yeah, that's exactly right. It's slightly different than the integration pattern. We have underlying APIs so we can do that org-first data model out of the box for you.

JASON: Got it. And we're just wrapping our entire app with that provider and sending in the client we created that uses our public token. Okay. All right. This is all -- this all makes sense. I'm feeling good. And then we have UI components. So we're going to do a log-in or sign-up. All right. And why don't I just copy this one straight up. We're going to create -- probably just set this up as a new component because we might use it in multiple places. Or what do you think? Should we try to keep this all in one big pile so it's easier to track what's going on?

JULIANNA: Yeah, that probably is helpful just for ease of looking back and forth. You're going to end up using this component, both when you sort of initialize the log-in page, and then we'll need to reload it on the O-auth redirect to complete that discovery flow. So you will end up using this component multiple times but the same config settings will work for both.

JASON: Got it. Okay. So we can -- let's start here and let's just see what we got. What did I miss?

JULIANNA: I think it might be the public token.

JASON: Expected a string, got undefined.

JULIANNA: I think it needs to be prefixed with Vite.

JASON: Oh, right, right, right. It needs to be public, whatever it is. Hey, there we go. Now I've got a built-in thing. Okay. We just keep getting guided here. I need to add this website as a domain for the Stytch SDK. So I'm going to come back here, and I do that --

JULIANNA: I think under frontend SDKs.

JASON: Oh, it didn't -- I didn't save my change apparently. Save. Save. There we go. All right. Now you're going to work, right?

JULIANNA: Hopefully.

JASON: Okay. So that sent me an email, which is over on my other screen here. There's my log-in request. It's going to give me a redirect. We haven't set those up yet, so we need to build this route for this to function. Okay. So, is this the sort of thing that I -- do I need to set up like a router? How do we handle the --

JULIANNA: Yeah, so you're going to want to set a redirect URL from the Stytch dashboard. So if you want to go back to the docs and that React quick start we were walking through, that'll give you some instructions there.

JASON: Got it. So, by default -- if the Stytch B2B component is rendered on the redirect URL, the email link token will be automatically authenticated. So, I pass that in here?

JULIANNA: Yes, exactly. So, what we're going to want to do is we're going to want to set it in the dashboard regardless, and we can set it as default, and it'll just work. But we can also -- like, if you have different use cases where you might want to specify different URLs, you'll be able to do that from code as well. So, yeah, we're going to want to add a redirect route that --

JASON: And, like, can I just send it to the homepage?

JULIANNA: Yeah, exactly. That will work. What you're going to end up needing to do is -- so, basically, you're going to want to have this redirect URL, and then on the page it redirects to, we're going to want to instantiate the frontend component again. What that's going to do is that's going to take that magic link token from the redirect URL and parse that and set the session. So what I would recommend doing is having a route that is maybe called authenticate. Once we do that sort of redirect, we'll then redirect to the homepage of the dashboard.

JASON: Okay. Got it. So if we start here, then we'll be able to handle the token exchange part. Then once we detect they're logged in, we can set a redirect to the dashboard page.

JULIANNA: Yeah. So what I would do for this first URL that we're setting is call it something like /authenticate. This is going to be for that discovery flow that we were talking about. So, basically, you'll click the magic link, it'll handle that redirect if we instantiate that component again, and then it'll pop up the screen where you can choose between the different organizations that you're a member of. Then from there, finish the log-in. Then we'll want to redirect to the homepage.

JASON: Okay. So I'm going to want to set up React Router or something here.

JULIANNA: Yeah, that probably makes sense.

JASON: Okay. So let's get -- did you have a preferred way to do this or a snippet or something you want me to use? Or should I just let it rip?

JULIANNA: I think, yeah, let it rip. Whatever makes sense to you.

JASON: All right. So, let's get into probably the quick start here. Because all we need is a really simple setup. And I'm going to -- uh, what do I need to install? Just React Router dom? Easy enough. So, npm install react router dom. Then I'll hide this bit. Up here, we're going to go with basic routing, which is all we need. So let's get all of these. I'm going to take this bit here and drop it first. Then I'm going to take the router bit and put that in here. Move this part probably to -- for now, I'll probably just stick it right there. What are you mad about? Oh, I forgot to actually put all the imports in. So I need this part. What? Uh-oh. What have I done? How does one make sure I'm looking at the right version of the docs? Tutorial, examples. Basic. That's what I want. Oh, yeah. We've like completely changed how React Router works. We're going to get the new example. Drop these in here. So the layout goes here. It's kind of been a while since I've used React Router. Copy these. Come up here. What have I done? I've made this so confusing. Oh, no. Okay. I know what I did, kind of. I messed up that part because that wasn't supposed to be a piece there. This comes down here. We end up with our app, right? Then in our layout, we need the sign-up or log-in. What is it called? Log-in or sign-up. Now we need to actually set these up to be a thing. So, we need the authenticate page. That's not the part I care about. You said we'll have a dashboard component. Do we need any others while I'm doing this right now?

JULIANNA: Yeah, that should be good. For the authenticate page, you're just going to need to reinstantiate the log-in or sign-up component. You can just call that the same way.

JASON: Got it. Okay.

JULIANNA: And we're going to want to do a redirect after that succeeds, basically. We'll need to handle that on our end.

JASON: Okay. So I can do that. So log-in or sign-up here. Then we've got the dashboard here, which we need to protect. Then this no match I'm just going to kind of ignore. So theoretically speaking then, this will get us -- I don't actually want to link to that. And we don't need that. So if I've done this properly, we should get our home and our dashboard. Okay. Got to actually start the app again. And I've done something wrong. These routes may only be used in a router component. Where did I use routes? Crap. What I did do? Routes. Stytch, B2B provider. Oh, do I have to set up a -- there's my layout. There's my routes. What I have done? Does anybody know what I've done? Router around routes.

JULIANNA: I can also send -- I do have a pretty basic snippet on this. So if that's helpful, maybe we just go with that.

JASON: Might be, considering I'm -- oh, you know what I bet I did? We got to add this browser router. Yeah, okay. All right. All right. I think this'll work. So we've got our browser router. Then we need to stick that browser router around the app. We'll make sure that the router has access to any Stytch stuff for when we want to do our setup there. Then, aha, look at you go. Okay. So nothing is protected, but we can go to our home, go to our dashboard. When I go to authenticate -- okay. I think it's going to send me another email here. I don't know if those are going to stack, and I don't want to show you my whole inbox. So, everybody just trust me that this worked. I'm coming back over here for my new log-in email. There it is. It sent to local host, but if I delete the secure part, aha. Okay. So, we need to fix whatever I did to put the HTTPS into the local host. But the fact that we're here means that we're creating an organization. And now I've successfully logged in. Okay. So this is the part where I would need my redirect.

JULIANNA: Yeah, we'll need to build a redirect here based on the callback that we're getting from the Stytch SDK.

JASON: Got it. Okay. So, what I'm getting back from the Stytch SDK, I assume it's going to talk about that in this setup here. Or no?

JULIANNA: Might need a different guide for that piece. One second.

JASON: Okay. So, just to recap because I feel like I kind of got all over the place there, for anybody who's watching, and all for me. We did two things just now. So, we've wrapped our whole app. This is like the root of our app. We've wrapped it with the browser router. We have the Stytch router around it so we can do protected things when we get to that point. Then inside of our app, we have this log-in or sign-up component. The log-in or sign-up component is what's doing all of that magic that we saw in our app with these components, like these little UI bits. They're all kind of pre-built. We don't have to do anything. They just work. Then we have our layout. So this is kind of like the basic structure of our page. In React Router, it's kind of passed into the top. So we've got navigation. Then we have an outlet, which is whatever the page content is. We have our homepage, authenticate page, and dashboard page. Whenever these pages are reached in the router, this is what shows up in the outlet. Then we've got the app itself, where we have our routes. Then we're looking for the default route. We use the layout for it. If it's the index route, we show home. If it's the authenticate path, we show authenticate. This down here is for 404. Everybody got that? Okay. So, now what we need to do is we are successfully creating our account here. But we need to catch some event from it, right.

JULIANNA: Yeah, that's right.

JASON: Okay. And to do that, am I looking for -- let's see.

JULIANNA: I sent you a code snippet in our chat.

JASON: Yeah, it got cut off. You can do it in Slack.

JULIANNA: There's documentation for this, too, if you go to the SDK reference. But I think for the purposes of this, I can talk through what that code snippet that I just sent over is doing. It's basically just configuring callbacks when we instantiate that.

JASON: Okay. So let's look at this and see what I'm missing here. We've got this coming from React Router. This one here, I believe, is coming from Stytch vanilla B2B. This one, same. It's coming from vanilla B2B. What else? Okay. So then the code itself, we've got our discovery component.

JULIANNA: Yeah, so you could rename that authenticate because we're doing this on the authenticate page. The example I have is -- yeah.

JASON: Got it, got it. So let me move this down to take the place of our existing authenticate. Okay. And so what this one's doing is we're saying we're using the O-auth product, session duration, using the discovery flow, and then once we've redirected, we go to the authenticate page. Then we got a callback. So this is like once I log in, send me here.

JULIANNA: That's just the initial instantiation, which doesn't matter for this purpose. What we want to do is change that to email magic links because we've been using email magic links. This example is using O-auth. You can delete that line, the providers. You can delete the whole O-auth option, actually. Then under products, up at the top of that config, where it says B2B products, yeah, email magic links. Exactly.

JASON: Got it. So then what we're doing is setting up on event. If somebody has created an organization or exchanged their intermediate session -- so an intermediate session, that's like because of the way the discovery flow works, I log in partially because I kind of log in with my email, but then I still haven't chosen an organization yet. That's what the discovery flow is about.

JULIANNA: Exactly. So once you choose that organization, we'll create a session that's actually tied to that organization. But you're in no man's land until you've chosen to log into a specific organization.

JASON: Got it. So the intermediate session is like this is enough authentication you can see which organizations you belong to, but you can't do anything else until you've chosen an org.

JULIANNA: Yep, exactly.

JASON: Okay, great. And in both cases, once we get the thing, we have a full session. So we go to the dashboard.

JULIANNA: Yep, exactly.

JASON: So, assuming -- let's see. We don't need -- we're not really using this data, so I'm going to drop it so it stops yelling at me. And no more tears. I'm back on my homepage. I'm going to log in. So, it takes me there. I'm going to go to my email. My magic link is going to come through. Where are you at? Oh, there it is. I'm clicking my link. I need to fix that. I can fake it by going through here. It says select an organization. I already created an organization last time. So I'm going to click this, but I could create a second team if I wanted. So I click through, and now I'm on the dashboard. Yes! Okay. So, we now have the ability -- and actually, why don't I -- well, we'll wait until I have the ability to log out before we go further on this. But that's pretty cool. We now have a full multitenant log-in flow where you sign in with your email, and you can access one of your organizations or create a different one. So you actually get the ability to do quite a bit, honestly. Like, that's pretty cool. So, if I do this again, will it let me create another one? I'll click through here. And fix my protocol error. Then I'm going to create another organization. Now I'm in another organization. I wonder what it did if -- okay. So now when I log in, one more time with these protocol errors before I fix them for real, now I have two organizations. So we'll add the ability as we go here to actually edit some of these things. For the time being, that's pretty slick that we're able to just do that. Okay. So, y'all, this is very cool. What should we do next? Now that we have the ability to log in and select an org, we are not -- so, there's a few things on my to-do list. One, we need to protect this route. Right now, even if you log out, you can still come to this dashboard. So we'll want to protect the route. I don't have a way to see which org I'm in. I don't have -- I'm missing a couple options. I don't know how much time we'll have for all of these things, but I don't have a way to invite new users to my org or manage those users or set whether or not they're admins. All of these things. Can I do all of that stuff with Stytch UI components?

JULIANNA: You can do a lot of that but not quite everything with the UI components. Some things like managing users. We're working on building the components for that right now. But today, you'd have to do that with the backend integration.

JASON: Very, very cool. Okay. Next is fix the protocol. Good call. Let me do that real quick. There it is. Will it just let me --

JULIANNA: You'll have to re-create it. We don't let you delete, unfortunately.

JASON: Got it. Okay. So that's correct. Then I'm just going to drop these that we don't use. Okay.

JULIANNA: Something we can do while in the dashboard, you can go look at your users that you've created.

JASON: Oh, right, yeah.

JULIANNA: So if you go to members there, you can see the two users. If you click on that email there, it should open up more details. So you can see status. You can see event logs, if you want to dig in, something is going wrong. Yeah, tons of details there you can see. The roles that you have, the sessions.

JASON: And so because I created these orgs, I'm automatically an admin, which makes sense. Then we've got sessions. Let me revoke all my sessions. Let me go to my other member. That was the first one I looked at. Let me revoke these sessions. And now I think we're logged out. So what we should be able to do now is when we put the protection in, it should bounce us back to the homepage. Anything else we need to fix?

JULIANNA: No, let's protect that route.

JASON: All right. Let's do it. What's my protocol for such a thing?

JULIANNA: Yeah, so what we're going to want to do here is basically use what's called the Stytch member session. We can get a bunch of information with that. I'll send a link in the chat to the session management reference. Okay. I sent it to the private chat. It wasn't working in the other.

JASON: All right. So I'll re-post it here. Then I'll head over to that section of the docs. Make this a little bigger. And -- okay. So, we get the use Stytch member session. That gives us access to the session, at which point we can see what's going on. Okay. So, why don't we just duplicate this straight up on our dashboard for now so that we can just prove that we're logged in. Then we'll get to actually doing stuff within this setup. We'll just do that exactly. For this, I need to bring it in from React B2B. Did I do it? Use member session. Okay. So, now when I go to the dashboard, it says no active session. Great. So, that means we're not logged in, and it should be bouncing us. Then to protect a route in React Router, let's see, I feel like we just did this and I forget what the exacts are. I'm a little less concerned about how React Router works. So why don't we cheat and go look at that cool Stytch example. Is this the one that has the -- I just want the routes. Somewhere down here, there's like an actual protected route thing. Router. Wait, is this not -- where are we? Well, that should -- what are you doing? Stop it. Let's go back here. There was the UI example one, I thought. Pre-built UI example. I think that has the React Router thing in here, if I can find it. I hope. Let's get down to the route. Protected route, this is what I'm looking for. So, here? Oh, my goodness. Please stop. Then we get this protected route, and the way we use the protected route is we wrap the whole dashboard piece inside of that. Yeah, okay. That's right. That's right. I remember how this works now. So, we have our protected route, and we'll have to go back and figure out how all these pieces work. Then in the router, instead of doing it like this, we have the path and say element is protected route. Then we need a sub-route in here for the index. That's going to be the dashboard. So what that means is we're basically putting everything through this protected route layout. So we've kind of got the main layout, and then these pages don't need anything. Then this layout requires authentication before it puts stuff through. And we can see here that it's kind of a pass through. Or it navigates to the log-in page, which we're going to make our homepage. So I need to bring in all the stuff we're actually using, which this is from React Router dom. The use effect has to come in from React. Then from cache in session. Why are you yelling at me? Navigate? Whatever you want, React. Okay. So then, if there's no session, we want to navigate to the homepage, I believe. Okay. So if I did that right, when I go to the dashboard, it will say you don't have a session and it bounces me to home. Now, the other problem I have is that I screwed something else up. Failed to execute push state. Okay. So, something almost worked. What if I just don't do that part? Yeah, we're going to ignore that part because it's an advanced navigation thing. We'll just send you home, and everything is fine. So, not logged in and we go to the -- oh, wait. Oh, no. That's the mismatch because it's not actually called home. I'm holding it together. I promise. So, now we get to the homepage. Good, good. Good, good, good. I think I did that in two places. So, navigate to home. Now when you navigate, you end up at the homepage because you're not logged in. If I log in and go find my email somewhere and I click, and now we don't get a protocol error. I log into my org, and we get a member session. Look at us go! Okay. So, in a relatively short span of time, even with me not remembering how React Router work, we've been able to get, like -- this is an authenticated app. We have the ability to let people log into different organizations and have protected sessions. That's pretty cool. So, Julianna, the next thing we want to do is what?

JULIANNA: Maybe what we can show is using RBAC to just grant resource access to various things. We can start with just like maybe printing it out for the sake of time, but we can also show how that could be used to grant different access levels to different routes.

JASON: Yeah, let's do it. So, I'm going to close these up, and we'll get in here. We've got our session, and then in our member session, I guess I would say current member role. So I want to replace this with -- well, I guess like that. So I want to replace their role with their actual role. And is that the sort of thing I can just grab? Like if I go to session.roles -- hey, this is looking easy. Concat. Is it that easy? Oh, my god, it is. (Laughter) I did use the wrong thing. That's better. There we go. So if we join these, we can see my roles. That happened too fast. (Laughter) Okay. So, then what? What should we do next?

JULIANNA: Yeah, let's create a custom resource that maybe the admin role can access. So we can go to the dashboard to do this. If you go to role permissions -- yeah, okay. So these are the default roles that we have. Like you said, if you create an org, you'll be admin by default. You can also create your own roles here. So maybe you want read only, that sort of thing. For this, we can just do a resource, things you have access to. There's some default ones that Stytch uses. But if you go create new resource, we can create a resource here. Then under actions, you probably want to do, like, create maybe -- yeah.

JASON: We can maybe just do a create and read for the sake of time.

JULIANNA: Yeah, that sounds good.

JASON: Okay. All right. So I have -- we can boop, and you can create a boop or read a boop. Then if I want to -- I guess what do I do next?

JULIANNA: Yeah, so what we're going to want to do is basically look at the permissions that your session has. Then we can use that to determine what you have access to. Did we assign -- oh, we'll need to assign the resource to either the member or admin role as well.

JASON: Okay. So I think what I would like to do is let's have the Stytch member be able to read boops. Then the admin can do both. So, admin can -- let's see. Add a role. Boop. And wild card so we don't have to do it all. Now that means they can do everything within the boop resource. Right?

JULIANNA: Sounds good.

JASON: Okay. So then in here -- let me start closing a few of these duplicates. In here, we can see these, but we don't have any indication of the specific permissions. So would I want it to be -- I guess, how would I go about sort of interacting with this?

JULIANNA: Yeah, let me send you docs on this that we can walk through. I don't know why it's not letting me post to the main chat. But I sent that over.

JASON: Okay. I'll drop this link in the chat. And there we go. Okay. So I have just a hook that I can use. All right. So let me copy this here and do one of these. That does come out of the React B2B. That's where I got it. Okay. And then on our dashboard, we can say is -- oh, whoops -- is authorized. What am I doing? Use Stytch is authorized. Then we get the resource and the actions. I guess in this case, the different one would be create. So then we can say if they are authorized, we can do like an is authorized. Okay. So once we get out here then, now we can see they have the create permission. So they're a super booper. All right. Okay. And then if I were to go and change this -- and I guess we probably don't have enough time to fully get in and delete all this, but what I can do is edit this and let's delete this one, and instead, they'll get boop read. Okay. So they've got the ability to read but not create. So when I come back out here, they are now a regular booper because they do not have permission to create boops. Okay. There's a question about SSO. For SSO, I think we just turn it on, right?

JULIANNA: Yeah, you just turn it on. We have guides for getting different IDPs set up. So if you're using Google Workspace, Okta, whatever it might be, you can just turn it on.

JASON: And where is that in here? I know there's like a section for --

JULIANNA: So, we'll want to make sure under frontend SDKs that we have SSO enabled. I think we do. I think in test, we default all of them enabled. Then if you go back to where you're instantiating that client, you can just add that.

JASON: Oh, so here I would just turn on more things.

JULIANNA: Yep, exactly.

JASON: So I can do O-auth. I can turn on -- so, email magic links, O-auth, passwords, or SSO. When I -- let's just -- yeah, I'm going to save that. Let's go back out here. If I go home -- we haven't configured any O-auth.

JULIANNA: We need more settings there. I can send you --

JASON: So if I go to my O-auth and say let's configure this, test my connection. Embed this URL into your application as a button. Wait. Actually, better question. Given that we probably have about ten minutes left, is this the right thing to show? Or do we want to show something else?

JULIANNA: That's a good question. It will only take like a few minutes to do Google O-auth. We could show that really quickly. I'm not sure that there's anything else that we exactly have time for that's really interesting. I think we got through a good amount of stuff here. So yeah, maybe let's just show this so you can see how easy it is to additional log-in options.

JASON: Okay, great. So, then for me to do that, I embed this URL into your application as a button.

JULIANNA: It'll work with the frontend SDK if you go to visit guide under test your connection. So, if you want to just send me that URL, we can use my GCP account to get this going.

JASON: Okay. Sending it to you in that back channel.

JULIANNA: Umm... one minute.

JASON: So here's the steps. You go to GCP, configure your consent screen, and then you get your credentials. So you need your API key, client ID, et cetera, et cetera. And then the redirect URI, you copy/paste into that field. And then if you want the Stytch SDK to support Google One Tap, then you need that bit as well. And so, that's how that works.

JULIANNA: We have redirect URL set up already. So we hit next. I saved the one you sent me. So you'll need to put client ID and secret in there.

JASON: So I'm going to hide my screen for a second while I grab those details. I'll copy that link. And copy this bit here. Okay. So that's finished, and now if I -- okay, I think I missed something. So let me pull this back up. Because I'm reloading and it's not showing.

JULIANNA: Yeah, I think there's one more thing we need to add. If you go back to in code where you're instantiating, if you want to add O-auth options under -- yeah, add it as an additional object. Then under providers -- yeah. So, you're going to want an array. Sorry, you're going to want providers, and that's going to be an array. If you do B2B O-auth providers dot Google.

JASON: Got it. Okay. So then we come around here. Now I can log in with Google. Let's give it a shot.


JASON: Can only be used within its organization. Oh, yeah. That makes sense.

JULIANNA: My test account.

JASON: Test accounts. And this is actually a really good thing because this is the sort of thing that avoids, like, me being shady, putting up a site that sort of looks like another site and then trying to get you to log in with your Google credentials so I can get access to some of your stuff. You got to be ready to do this stuff for real, and this is good. So you can test, but you can't test outside of your own org, which is the right way to go, I think. So all of that to say if this was my org, if I had set this up, it would allow me to log in. But given that we are not on the same account, we'll just use the email magic link. Then SSO would be the same thing. If I had an Okta account or whatever set up, I could configure it to be the IDP, or the identity provider, for Stytch and it would do the whole thing. That's not hard, it's just a lot of copy/paste this field over to this field and over to this field and this field, and now you're working. But that is great. So, okay. We have probably not enough time to build something, but maybe we can talk a little bit about how a backend would work. We've got these demos. We worked together on kind of building out some demos. I think these are -- I don't know if these are deployed anywhere that you can see. This is sort of the -- it's like kind of a linear clone demo app, right. So it gives you this kind of big purple gradient thing. You can log in. Then when you get your dashboard, you have the ability to add and remove ideas and also manage your team members and all of those sorts of bits. This is set up in two different ways. So, I'll look at the one I know best, which is the headless example. So, once we get -- this is interesting too. In our app, what you and I just did, we were using pre-made Stytch UI stuff, no -- kind of letting Stytch handle everything. In this version, this repo, which let me send a link to this one. There you go, Bruno. In this one, this is done with none of the pre-built Stytch stuff. So everything is built using, like -- let's see if I can even find all these bits. So, everything is kind of pulled out with the Stytch vanilla stuff, but there's none of the React UI in. So this is how you would sort of add Stytch retroactively to an existing React project where you already had your UI built up and all those good bits. The cool part about this one is that we were able to put together a whole backend for it, too. So this is like a Node Express app. If we look at the API, it does a very basic like get an idea, create an idea, all done with the most simplified thing I could think of as an express API. I think it's using SQL Lite. So you can run it locally. Then the schema on it is very, very straightforward. It's the text of the idea, the status of the idea, who created it, and what team they're on. Then out here, as you're doing all of your CRUD action stuff, you can also load your team. This is all done using these Stytch SDKs. This is the Stytch Node SDK. It lets me search for a member, given the organization ID. So I can get the full list, and then you just pass in the Stytch session, which is a cookie. You then get -- I think I simplified the deal so you get the ID name, email, status, roles. You can get your team settings. Your team settings allow you to control whether or not people can send email invites, what auth methods are allowed, what email domains are allowed to join this org, whether or not you can let somebody join the org if they've got the right email domain. This is a really cool one. So on and so forth. So, all of this is like if you wanted to manually control all of it and set all of those pieces, you can do that. Then a lot of this stuff you said, Julianna, is managed through some of the headless components. Not all of it. But the React components will give me the ability to not have to build these manually.

JULIANNA: Yeah, exactly. We'll handle a bunch out of the box for you today. We're continuing to build more things and always love feedback too. If there's something that we're not handling out of the box that you'd like to see us do or other functionality, we always love to hear that.

JASON: Yeah, and this is another -- like, if you want to implement your own redirect flow and you're doing it on a Node app instead of the frontend, this is what the Stytch UI component is doing for you. But we're able to load the Stytch client, check for what types of responses are allowed. So discovery flow, magic links, O-auth. You go there, and you can kind of do all these bits. Then we can do things like get the intermediate token and exchange it. We're saving some cookies and all that good stuff. But the same thing, you're selecting which team you want to be part of. You can switch teams. There's a team switcher. There's the ability to register a new account, the log out. That API-first approach, and then the SDK is wrapping the API makes this feel really nice to work with. We barely scratched the surface with what we were able to do in our React app, but it is pretty cool that in the span of about, what, an hour and 15 minutes, we got a React app stood up that has the protected dashboard route that's handling Google O-auth -- or would be if I had my own credentials in there. It's handling the password magic link email log-in flow, and it's handling roles, where I can quickly sign in and remove roles. So for somebody who wants to take this further and kind of get deeper in here, what should they do next? Where should people go after this?

JULIANNA: Yeah, so you can find a ton of resources on, our doc, all of that. Really encourage people to if they're trying out Stytch, building out, to join our developer Slack. Chris, who has been super helpful here, he's the head of dev success for us. Him and the team are super helpful. We love feedback there. We're happy to work through integrations with you and all of that. I'm also on Twitter. Jason sent it earlier. So, you can feel free to DM me on Twitter as well. Yeah, happy to chat and help you get up and running with Stytch.

JASON: Yeah, and this was super fun. I feel like there's -- it can be kind of like intimidating as somebody who wants to build a side hustle or whatever to get into this whole world. I need to set up multitenancy. I need RBAC. There's all these words, these acronyms that we know are important. Eventually, you need to support SSO if you want to get big clients. So, having something that will just sort of let you get running fast and just sort of makes that stuff go away. Because what I want to focus on as a dev is the idea that I have for my SaaS app, not the boilerplate that makes my SaaS app function. It's also such a -- it just stresses me out when I start thinking about the security of all this stuff. Like, how do I structure the user data, how do I make sure I'm compliant with all the various regulatory things that need to be done with user data? Like, I'm not an expert in that. It's ideal that I don't have to be. My preference is to hire somebody who can do that. Now, I can't afford somebody's salary, but I can afford a tool like Stytch that kind of makes this whole category of problems go away. Anyway, Julianna, anywhere else you want people to go before we wrap this one up?

JULIANNA: No, I think we got it covered. Yeah.

JASON: All right. Well, let me send one more shout out to our sponsors, Nx and Netlify, for covering the captioning. We've had Rachel here with us from White Coat Captioning all day. Thank you again, Rachel, for being here. And thank you all for hanging out. Make sure while you're checking out things on the site that you go and check out the schedule because we've got some really good stuff coming up. This episode next week actually got changed. Brandon is going to come back, I believe, on the 30th. But we've got a great surprise episode that I'll have details on shortly, happening next Thursday. It's going to be a lot of fun. So, make sure your mark your calendars and go just whatever, get on the newsletter, get on the Discord, whatever it is, and make sure you hit that like button. It helps me out, helps more people discover the show, and we can all have a little more fun building stuff for the internet. Julianna, thank you for taking time to hang out with us today. Any parting words for the chat?

JULIANNA: Thank you as well. This was super fun. Yeah, hope we can simplify auth for some people so that they can get back to focusing on building really cool, interesting products.

JASON: Awesome. Well, thank you so much. As always, chat, thank you for hanging out. We will see you all next time.

JULIANNA: Awesome. Thank you.

Closed captioning and more are made possible by our sponsors: