![Introduction to Serverless Functions](https://static.frontendmasters.com/assets/courses/2020-08-25-serverless-functions/thumb.webp)
Check out a free preview of the full Introduction to Serverless Functions course
The "Handling the Identity Token & Roles" Lesson is part of the full, Introduction to Serverless Functions course featured in this preview video. Here's what you'd learn in this lesson:
Jason demonstrates how to use a JSON Web Token (JWT) to check that the code within a serverless function can only run for a user that has a specific role, and demonstrates how to change the role of a user within Netlify for the app.
Transcript from the "Handling the Identity Token & Roles" Lesson
[00:00:00]
>> Have somebody was being mischievous, they could figure out what our serverless function was. And then they could just skip this UI altogether, and they could just post to that serverless function, which we don't want. We wanna control access all the way, and so what we're gonna do is we're gonna modify our admin a little bit.
[00:00:20]
And in addition to controlling access to the page, we're also gonna include the access token, in what we send to our serverless function. So let's grab out the access token, from window.netlifyIdentity.currentUser, and then that's gonna give us a token. So I'm grabbing out the currentUser's token, and we're gonna use the access token part, which is the JSON web token, the jot that we just looked at.
[00:00:57]
Then I'm gonna add in our our fetch call, I'm gonna add some headers. And what I wanna send is an authorization header, and that is going to be a Bearer token. Which I'm not 100% sure if there are other types and that's why you include Bearer in the front, but this is a really common thing that you'll see that the token gets prefixed with Bearer.
[00:01:25]
So that's how we're gonna do that. So now we have prefixed our access token with Bearer, we're passing it in the authorization header. And what that means is now our serverless function is gonna get that authorization token. That's super cool, so if we go back to our add movie, I'm going to comment this part out for a minute, because I wanna play with the tokens before we start saving things.
[00:02:01]
So instead, let's just comment all of this out actually, so doesn't give us errors. And what we're gonna do with this, is we're gonna look at the event headers. So let's just console log(event) again, and we're gonna return the status 200 and work in progress. So now that we've got this running, I'm just gonna submit something.
[00:02:28]
And I think I can just submit empty, so let's see if it'll let me do that. Yeah, so that does what I want. We should see in here if I scroll down yeah, that we've got this authorization header that came in, and we can see our token. So if we take this token, and we bring it over to jot.IO, should be the same token.
[00:02:52]
It is, well kind of, it's it's a newer version of the same token, that has the email app metadata, user metadata, excellent. So that's exactly what we want, so there are a lot of ways that you can parse a JSON web token. We are gonna take the easy way out, because nullify functions, nullify identity are part of the same system.
[00:03:14]
We actually just handle that for you, so we pass in context, and so if we look at this context object and run the same thing. Let me just submit this function. And then let's come back here and look. We can see that we get a whole bunch of stuff, we get some objects and things like that.
[00:03:38]
But then we get this clientContext and inside clientContext, we get some information about the Identity service. That is pretty cool if you wannna do some dynamic stuff, like if you wanted to change the role of someone using serverless functions, you can do that. And we'll look at some examples of that a little bit later on, that are pretty fun.
[00:04:00]
But then we also get this user. And so this user includes all that information, we get the app metadata, the user metadata, the user ID. And that way we don't have to parse the JSON web token, we can just use this object. So we're gonna do that, and the way that we're gonna to do that is in our function body.
[00:04:25]
Let's just revert all this stuff that we did here. All right, so I'm gonna get this out of there, and then let's re enable all of our logic. Okay, so we're back to where we started. We we have a handler, and we're getting out the form data, and we're submitting that to hasura.
[00:04:50]
So before we do all that, I wanna grab out the user, and we're gonna get that out of clientContest, cuz that's where we found it before, right? That's where it was in this object. We've got clientContext, and then we have a user. So I want this user object, and then what I'm gonna do, is I wanna check if we have a logged in user.
[00:05:16]
So we'll create a variable called isLoggedIn, and that's gonna check if we have a user. And we have a user.app_metadata, right? And then I'm going to check we'll check if the roles will be user.app_metadata.roles or an array. Then in here we're gonna check if we're not logged in, or our roles don't include admin, then I wanna return a different thing.
[00:06:02]
I want to return a statusCode, a 401, and I wanna return a body of unauthorized. So, does it make sense, what we just did here? Does anybody have questions? Just to walk through it from the top, what's happening, is we are passing in that user identity. So our admin function now includes an identity token.
[00:06:29]
It's showing someone, or showing our app who the person is making this request. Inside of our serverless function, we are grabbing that data that was sent in with the serverless function to figure out who our user is. So first we're making sure that they are in fact a user.
[00:06:49]
So if an invalid token or no token gets provided, then this would come back as false. Then we're checking whether or not they have roles. So if they have roles, then we are going to use those otherwise, we have an empty array. And then, we just check, are they logged in?
[00:07:07]
And do they have the admin role? If not, we're gonna say that they're not authorized to do this thing. If so, we'll let them do it, so now, that I've done this, we make sure it's saved. Let's take a crack at this, I'm gonna to try to add our last movie.
[00:07:25]
So let's go to movies dot.json over here. And I'm gonna copy this out, here's our last one. Let's drop it in, copy the title, get this tagline, And our poster. Nope, got a 401. So we're not allowed to make this change, and if I go look at our data here, we can see that it didn't get added.
[00:08:02]
So, now our function is gated, our function does not allow someone to make this call, unless they have the appropriate role. So let's go give this user that role, I'm gonna edit, let's let's go back out here. I'm in the frontend masters-serverless function, and you can get there by running ntl open.
[00:08:21]
This will take you right to your console. Once I get there, I'm clicking on Identity and I'm looking at my user. I'm gonna click on this user, and then I'm gonna hit Edit. And then here, I'm gonna add a role of admin, and click that button. So now I have an admin user, so let me save that.
[00:08:39]
Okay, so now that I've done that, when I come back out here, and I log out, let me start the server again. Okay, so I'm logged out, now let me log back in. We are logged in. And then I'm going to, in the console here. Let's console.lognullifyIdentitycurrentuser, and let's grab that token.
[00:09:22]
And let's go and look at a jot.io again. Look at that, now we have a role in our app metadata, we've set a role of admin. And that means that we've officially authorized one user to make decisions about what's in our database, this user is allowed to post to our app.
[00:09:43]
So if I go back in to the app itself, and let's add that one more time. Let's try to add this this movie, so I'm gonna add it. Give our title. Here's our tagline. And here is our poster. We get a 200, and if I go back out to the front There it is, In The Boop.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops