So now let's go ahead and let's authenticate each user trying to access our room. In order to do that, the first thing I want to create is a way to fetch the board using the ID so we can see whether the user has permission to enter that board. So let's go ahead inside of convex, inside of board.vs. Now I'm gonna go all the way to the top here. Actually, let's go all the way to the bottom and let's export const get to be a query from .slash generated server.
So import it from the same place where you imported the mutation. And this query is very simply gonna have arguments that accept the ID, and then that's gonna be v.id boards. And then we're gonna have a simple handler, which is an asynchronous function, which has the context and the arguments. And all this is going to do is get the board using context database get arguments id and return the board and no we are not going to add any authentication here because we're going to use this only to access it through our route handler which we are going to create now and in there we're going to have separate authentication so you're going to see in a second why we need to do it this way so for now just make sure that you have a very simple get query inside of the convex function here. What we're going to do now is we're going to follow the instructions on setting up authentication for LiveBlocks.
So in here in the documentation you have the authentication column. You can use their authentication or you can build your own authentication. So I'm gonna do that using the access token and select nextjs. So let's go ahead and install this package npm install liveblocks-node. I'm gonna go ahead inside of my terminal here and I will shut down convex dev for now and just run npm install at liveblocks slash node.
And then we can do npx convex dev again like this let me just shut all of this down and then what we're gonna have to do is we're gonna have to create an endpoint liveblocks-auth route.ts so let's go ahead and do that. So I'm gonna go inside of the app folder and I'm gonna create a new folder called API and inside of here I'm gonna go ahead and create a new folder which is also going to be the name of our path LiveBlocks-auth and then inside route.ts. So this is the exact same convention as creating client-side pages but instead of page.tsx we have route.ts. So let's go ahead now and let's import live blocks from at live blocks slash node which we've just installed and then in here we're gonna initialize live blocks using new live blocks and then we have to pass in the secret this time so inside of our live blocks config we use this public key but in here we need to use a secret and you can see that inside of this configuration right here it uses a secret key so you need to go back inside of your project here inside of the API keys and this time reveal your secret key and copy it.
So we have to use the secret key here on the backend and let's paste the secret key here like that. Then what we have to do is we have to initialize convex so that we can use convex inside of our route handlers and there is a way to do that. So let's go ahead and import convex HTTP client from convex slash browser and let's also import API from convex generated API And then let's define a convex instance here using new convex HTTP client process.environment.next underscore public underscore convex underscore url like that. So let me just collapse this so you can see how this is supposed to look like and of course to confirm in your environment local that you have next public's convex URL it's supposed to match here and you can add an exclamation point at the end to get rid of the error. So you should now have an instance of convex and live blocks inside of your Next.js route handlers.
So in here, what we can now do is export asynchronous function post, which has the request, which is a type of request. And what we can do here is we can use clerk because we have a middleware file which means that we've used we've protected our entire back-end and front-end with clerk so we can import some useful utils here like auth from clerk next.js and current user from clerk next.js So let's add both of them inside of this post request here. So I'm going to add const authorization to be await auth and I'm going to have const user to be await current user. Like that. If we don't have authorization, or if we don't have the user, in that case, we're gonna return new response, unauthorized, and we're gonna pass in a status of 403.
And then let's go ahead and extract the room that we are trying to join from await request.json. So this is where LiveBlocks is gonna send the room information in. So if you're wondering where are we going to fire this LiveBlocks out throughout, we're going to do that by modifying our LiveBlocks config. So inside of this create client we're going to change this to target to this API route every time the room component loads. So that's how I know that this room is going to be inside of my request.json and of course because that's how it's written right here in the documentation.
So we get the room and then let's go ahead and get the board using that room. So const board is going to be await convex.query API board get and we are very simply going to pass the id as the room itself. And now let's go ahead and check if board?organizationID is not equal to authorization of the current user.organizationID like this return new response unauthorized. Like this. And then let's go ahead and let's actually create the user info which we're gonna pass back to the client So const user info is gonna have a name of user first name and it's also gonna have a picture of user image URL.
Like this. And then let's go ahead and create a session which is going to be live blocks dot prepare session and pass in the user dot ID as the first argument and for the second argument open an object and pass in user info to be user info or you can use a shorthand like this and now we're gonna have these two errors here which you can easily fix by adding exclamation points at the end or you can use aliases like anonymous for example if the name isn't available So you can choose one of those. So either do it like this or add an exclamation point. Or maybe a teammate. And now that we have this, let's check if we have a room.
In that case let's go ahead and do session.allowRoomSessionFullAxis. Let's go ahead and destructure status and the body from awaitSessionAuthorize and return new response body and status. And to make it easier for ourselves to understand what's going on here, Let's do the following. So once we hit the post route, I'm going to go ahead and add a console log here. And I'm going to say out info.
And I'm going to open an object as the second argument for my authorization and for my user like that. So when this endpoint hits, I'm gonna see in the terminal whether I have authorization. Then in here, I'm gonna go ahead and I'm going to check if I have the room. I'm gonna check if I have the board. I'm gonna check the board organization ID using board?organizationID and I'm gonna check user organization ID which is gonna be authorization.organizationID you don't have to do this but I'm just giving you some tips on how you can debug this to see if something goes wrong or why it works in the first place.
And the last thing we can do for example is just check console.log user info here. I like to add this in an object, it's easier for me to see that way. Great. And the last thing here we're going to do is console log. Let's do it just before we return the session.
Let's add status and body allowed. Like that. So I just added a couple of console logs so it's easier for us to follow the flow of what's going on inside of this API route. So now we're gonna go back inside of liveblocks.config.ts and we're gonna remove the public API key. And instead, we're gonna add out endpoint and that's gonna go to slash API slash live blocks dash auth.
So first things first, confirm that this slash API live blocks dash auth matches your new API structure, app folder, API, live blocks dash auth. Make sure you don't have any typos. Otherwise this is going to be a 404 route. So first things first, let's check if we have this inside of our network tab at all. So I'm going to go ahead and search for live blocks slash out to confirm that that's gonna be loaded here once I refresh.
Let's take a look and there we go. You can see how it's pending and it received back a token. Perfect. And you can see how we have the payload with our room ID. And now because of all of those console logs which we've added, you can go inside of your server terminal and in here where you're running npm run dev you're gonna see all of that useful information.
So let's take a look at it from the start. Let me just go ahead and find where this is starting. Alright, so first I have the AuthInfo. You can see that I have the authorization. That is great.
And I have the user model. That is great. And let's take a look at my authorization which is important so your authorization object should have the organization ID I also have the organization role so in case you don't have organization ID or organization role which you can also confirm a bit lower here. I think we created a custom object. Let me just scroll a bit down.
There we go. You can see that my board organization ID matches my user organization ID. So that's why I allow this user to visit this board. So in case for some reason you don't have that you can always visit clerk and inside of your JVT token just confirm that you have the organization ID passed and I also have the organizational role passed for example. Even though I'm not exactly sure that this JVT template relates to what I do in my backend.
I'm not entirely sure. Great but basically if in your console log right here you can see this allowed, you can see the status 200 and inside of here of course you don't have any errors you should be able to see this completely. So now what I'm gonna do is I'm gonna copy the URL from here and I'm gonna go ahead and create a completely new user and see if I can visit that board then. Alright, so I'm in a completely new account and if I paste that board URL Let's go ahead and see what happens. It looks like I can still access this but we can see that authentication did fail So our API route is working and our authentication is working, but I may be doing something wrong So we do have unauthorized but for some reason we still have access to this right here.
So I'm gonna go ahead and debug this a bit. So let's try this. So find the inside of your API live blocks out where we do return new response unauthorized. Try and also give it a status of 403. Like that.
And let's see if that's going to change anything. If I refresh here, let's see, anything new from the error? Unauthorized 403, so it definitely is working. Oh, and it seems like the WebSocket server has closed. I think this is actually okay.
The reason we can still see these things is because they are hard coded. So usually what we're going to do next is we're going to attempt to load the information of the presence of the users but none of that is going to work because we are not authorized. So I think that for now this is actually completely okay. I'm gonna research later if there is a way to redirect the user if we are unauthorized. But for now I think this should be just fine.
Great! So we just wrapped up and added the authorization to our project and let's go ahead and see what happens. I think we can confirm this even further by then going inside of the client here. So we did this and let's go ahead now and we have to extend our liveblocks.config.cs so our info has the name and the picture remember because inside of our router.cs here let me just remove all of these console logs. I don't need them anymore.
So we confirm that this works. Oh yeah, so in this user info we have name and picture. So we need to add that to our type script inside of LiveBlocks. So let's quickly go inside of LiveBlocks.config.ts right here and let's find user meta right here. So I'm going to remove these comments inside.
I'm going to add an optional ID to be a type of string and I'm gonna get info to be an object which will have name which is an optional string and picture which is an optional string as well like this great And let's see if there is a way for us to see if we can render the authenticated user. All right, so we, yes, we did this, that is fine. Oh, and then we can use, use the self hook. So let's try that out very quickly. So we have to use that somewhere inside of our canvas.
Let me do inside of a room, my apologies. So inside of this. So let's go inside of canvas here and let's just, this is already marked as use client. Perfect. So let's go ahead and import use self from live blocks config.
And let's see if we can get that here. So what does the documentation say? We should be able to export name from useSelf Is it? Oh, useSelf then we can get me, me.info Like that Name does not exist Let me just try and write X. How about we just mark this as info in general and console.log info.
So now let's check this out. If I go here, so right now I'm in a place where I shouldn't be able to see anything and it looks like it's working. You can see how my board is just infinitely loading because I get 403 forbidden because I'm in that other account. So I'm gonna go ahead and log out now and I'm gonna go back in my old account. Alright so let's try it out.
I'm back here and let's see. There we go! You can see how here it finally loads and you can see how nice our client-side suspense loading component in there is. There we go. My name is please know the same person I'm logged in with and you saw what happened if I try to Enter this board using another user so you can see how now we have this nice loading indicator because we are Authenticating our user perfect And you can see how it happens right here.
Looks very smooth. So I'm gonna try it just one more time by logging out and going in another account. Alright, I'm in a new account here and if I paste that previous board it never loads for me. Perfect. And I have a bunch of 403 forbiddance and you can see that I can never console log that user self hook information.
Perfect. So this is now officially working. We successfully added authorization to our live blocks. And one thing that I want to do now is confirm that if I invite this user which currently gets 403 to my organization they should then be able to visit this. They should no longer get a 403.
So how about we do that? I'm gonna go and invite myself. Alright so I just went back and there we go I can now join this organization and we have the board here and if I click here let's take a look there we go I can successfully see my information my name is Antonio from another account perfect so we just confirmed that all of those things are working Also if you're wondering where you can invite people, you can just click invite members or click manage organization here and add the email and select the role of the user you want to add. Beautiful. So this is officially working.
We wrapped up the authentication for our live blocks. And now we are ready to start working on this information about the board and then add the list of participants, then add our toolbar and start doing some cursor matching here. Great, great job.