* This is an automated transcript. Please excuse inaccuracies.
Hi, my name's Sebastian, I'm the product manager here at 8base. If you like this video, please like it as well as subscribe to our channel it really helps us grow. So, in this tutorial what we're going to be talking about is how you can authenticate devices using API tokens and some of the different resolvers that we can actually create to handle things like device registration.
You know very often when we think of authentication, we think of it in the context of a user needs to authenticate to my app, so then they can go in and perform the actions that they need to perform. However, it's not uncommon that if you're dealing with connected devices like an IOT device maybe even a VR headset or a registration kiosk per se that you actually need the device or the application itself authenticated, so that then users can use that application or the device itself can perform the task that it needs to perform.
So, let's jump into this tutorial it's all on GitHub. I'm just going to go through it with you, so we can explain it all step by step and I hope you find this valuable.
So, the first thing that we're going to do is, we're going to go down in the tutorial which I will make sure is in the video description below. So, what we're going to do is we're going to have a device which is really just going to be our laptop. Essentially, we have a few scripts that we'll be able to run that will execute calls to our Graph QL API on an 8-base workspace, as well as when we register the device, save an API token that we get passed back. So, what I'll do is I will copy only and head back over to S code and then just directory, orioles, cool and drop that right in there. Downloaded, so check this out. Cool. And then I'm just going to folder here in… cool now we got it.
All right, so just to quickly break down the device application that we built- the tutorials are really not about that, but just to give it some context. Essentially, we have this folder here called, “Device” where in our package.json file, we have a command called “exec” which is going to run, we're going to hit our index.js file under course. Now very simple we pass this an argument and take that argument and find the right function that we are, the function name that we passed it and then these functions are really what we're going to be. So, register device, read activity and send activity. This will allow us to register the device as we're expecting to, and then we can just run a query and a mutation to show that we can receive and send device authenticated make sure that the right records are coming back and forth.
So, with that said, we also have a simple storage system of essentially reading and writing object values to a json file, as well as in our utils we have an API module which we were using to communicate with our Graph QL API. So, there's encode comments for all this stuff- feel free to peel through it when you're going through the tutorial, but it's very straightforward.
The only thing that we're going to have to change in this device repo is API endpoint that you connect into, you'll want to make it your 8base workspace; so, in just a minute we'll update that property.
Now if we go back to the tutorial we can see that it is, telling us a little bit about that device structure that we just went through, telling us to switch out the 8base API or workspace API and then it gets to setting up the back-end which is the more important part.
Now if you don't already have it installed all you want to do is install the apes command. Essentially, you'll be needing to use this both to import the schema that we'll be using for the tutorial, as well as then to deploy the custom resolver that we're going to write that will allow you to register your device. So, I already have it installed, but all you'd have to do is run NPM install global 8base CLI or you could use yarn whatever package manager you prefer over. Then once you are inside the project change into the server directory. So, then what I'm going to do is I'm going to go ahead and change into my server directory so server. And right in here if we look at it, we can see that there's the schema.json file. Now this is going to be a really simple and effective way of bootstrapping our application by using the import tool to import these tables that we'll need for the sake of this tutorial. That is registration codes devices and data entries- I think that's what we we're calling. It is just something that we can read and write data from to make sure that our device is able to do it as well.
Now if you haven't already run 8base login and that will authenticate your command line. However, what I'm going to do is I'm going to run 8base configure so that I can select the workspace that we'll be interacting with. So, it is called- it's up here… device tokens tutorial that's it, cool.
All right so now this project is connected to device tokens tutorial and the next thing that our tutorial is asking us to do is run 8base import the schema.json file; so that one right there. Let's go back here and run this command to make sure that is it all in our workspace 8baseimport-fschema.json. Awesome! Now this should just take a minute but I'll come right back when it's done cool so that was faster than I expected just 17 seconds great.
So, now that we've imported that we're actually going to go over to 8 base workspace that we're dealing with and be there for a little bit as we set up the rest of the back-end that we need to have set up. So, if I go back here and I go to my device token tutorial workspace. Now if I go to my data and I refresh it we're going to see that we have a few different tables now inside our workspace. So, the first one is data entries which is very simple. It is a table that stores a record which has a value and those are related devices. The devices are essentially going to be sending these values to our API and saving those.
Devices is the record we're actually going to use to track any device that's being authenticated. Obviously as you'd have a user record in your database this is going to be the device record. And so, we're giving it a name it has many data entries- exactly. It has one registration code which we generate to be able to authenticate these devices. And then also has an API token to it- the token we're going to have to generate and that will be the credentials able to pass back and forth. And then finally we have registration codes which have that one-to-one relation devices, then they take a text input essentially to um use a password when you sign up.
So, very straightforward data model. Now let's see what it asks us to go and do next.
So, what we're going to have to do after that is go into defining roles and permissions. So, if we go back here and we go to our app services go to roles we're going to add a new role and we're going to call this the device role. So, any device that gets registered is going to have this role associated with it you can add a description if you like up to you. So, now if we go “add role” and then click into this role we're going to go ahead and pretty much just turn off everything. So, let's go here- no records, no record, no records… this is an improvement we can make which is effective to turn everything off. But we're almost there in three, two, one- done. Awesome!
So, now with all those off we're starting from a complete of setting up our permissions for the device role. And what we're to want is to, really the device is only going to have to deal with data entries and its own record device. Everything else is going to be handled on server-side logic without permissions being checked. So, with data entries that's a record that we're going to actually want devices to create data entries and only read the data entry needs to that it has created. So, let's make sure that we allow create data entry.
Now if we were dealing with the users table right, we could just say, “user's records” right; so, any record that the user created they could see. But with devices it's different right and so if we were actually click into this we could see that that generates a custom filter to where it says, “Hey, for the data entry whoever it was created by if there are id equals the id of the logged in user, then they can see that record.” Well we have another dynamic variable that we're going to be able to use here called “Requesting API Token” and that's how we're going to be able to build this bridge of actually scoping which records a device can see or any other entity that works within your use case. So, what we can do is take this right here copy it over or let's write it out. I'm actually just going to copy this piece right here. I don't have to type it out and I'm going to delete the rest of this. So, we are on that data entries table here right. And so, every data entry belongs to a device so we're going to look at the device and then every device has an API token if it's registered. So, then we're going to look at the API token and then we're going to say, “For the API token if the token value equals the requesting API token, then that's the filter that we're going to allow that that user to have.” Pretty straightforward but works really well.
So, drop that in there now we can go back to here and see that okay well when it comes to the devices table, which records does the device have access to. We in this case only want to give it access to itself. So, what we're going to do is we're going to go back in here and read to a custom filter. And now that we're on the devices record, we can just say, “We know it has an API token, we know that API token has a token and then we know we want to equals the underscore requesting”- that's why I don't do it- API and spell that right, I think that’s cool. So, once again this will scope it down to where it's only able to read its own. Now save that and we're also supposed to drop that in for custom filter. We'll check that and yep we're good there- cool. There's a lot more to learn about roles and permissions. I will also add a documentation link in the video description, but for now know that this dynamic variable requesting API token is the feature that allows us to essentially say, “When a device is using that API token to authenticate, we can use that to then scope the records in our custom roles and permissions.” Cool.
So, with that set up, now we actually are going to go back over to VS code and deploy our serverless function, our registered device function. Now with basic crud operations that we need as well as subscriptions are just automatically generated by the API. So, when we want to create our data entries or read our data entry, update them whatever that is our API is already ready to go. But in this case, we kind of have this custom one we say, “Hey, we want a registered device register a device and there's a few different things that need to be coordinated for that effort.” So, we're going to use this resolver to accomplish that. So, let's hop back to vs code and read through that resolver function. I'm going to close devices here and I'm going to open server and I'm going to go in to the register device schema.graphql file.
So, first off pretty simple we have a mutation and we have it's called “Register Device” and accepts a code which will be a string value, returns its result which is the id; can be the id of the device as well as an API token and that's the token we're going to have to store on the device. So, pretty straightforward, GraphQL schema- let's now look at the handler. So, we have just a couple basic constants up here. When we look at this registration code query, this is how we're going to check whether or not the code exists. When we look at the create API token mutation, this is actually how we are going to create the API token as well as associate with that token the device role.
So, you can see here that we are connecting the role device to the API token once it's created, so that API token has the right permissions associated with it. Then we are doing this “create device mutation”, where when we create the device, we are giving its name, we are giving an API token and we are connecting it to the registration code; and there's a reason we're doing that and which we'll see in a minute.
So, pretty straightforward when the event or when the trigger runs when the function runs, we get the code off the data. We then get back a registration code running, the registration code query and identifying it by the code that was passed in. Now if no code was found it was an invalid code, we just are going to return an error that says, “Hey, this one was submitted but it wasn't found no code found error” or no code found there- exactly.
Next, we're going to see that well if the registration code was found, but if it has a device associated with it then it's already been used right. So, then we're going to say, “Hey, the submitted code was already used code assigned that's another error.” But if neither of those, we're going to assume the code is valid and then what we'll do is we'll say okay well now we're going to create an API token. So, we go ahead create that API token, give the token itself a unique name using the code that was passed in. Then once that's done, we're going to use all the information that we've got at this point to create our device. So, we're going to pass in the code id, we're going to pass in the token id and we're also going to give the device a name which you could come up with any name you feel. So, here we're just going to use device, underscore and then the code that was passed in. Then just a little console statement, so we have something in our logs that say, you know the token with was added to the device with this id at this time and then we are returning the id and the API token.
So, pretty straightforward function but this is going to coordinate all those efforts that we've been discussing.
So, all I'm going to do here now is run 8base deploy and this is going to package and deploy this function to the workspace. So, once this is done deploying, I will be back.
Awesome! So, that just finished deploying now we're actually have to jump back really quickly into our roles and permissions and update one thing. Essentially, when we are registering a device the device is unauthenticated. So, we need to make sure that that specific Graph QL operation has public access on our API. So, what we can do is hop back over to our 8base workspace and go back to our roles, and here we're going to go in and click on our guest role.
Now the guest role essentially defines what are the public resources. So, someone's making an API request without any authorization header, what are they able to do. And if we go into our “apps” tab here and scroll down, we can see that on the API the custom resolvers that we push to our Graph QL API will pop up. And so, what we're just going to do is click on register device to make sure that now we have public access to our registered device. Then what we're also going to do is go into settings and just take our workspace endpoint. We have to add this to the project so start testing out our device.
So, let's go back to the tutorial and see and yeah, we're already at the testing phase cool. So, let's jump back into VS code and go into our API module on the device, source, bills, API drop in this value. Cool. So, now it knows which API to connect. So, what I'll do now is I'll just change back into the devices or the device directory and I'm also going to run NPM install to make sure we have all our these installed. Cool. And then if we look at our tutorial it's going to tell us which commands, we're going to test.
So, what we'll do is first we'll go in and test that if we don't have permission if we're unauthenticated to read data. Then we'll register the device. And then we will send some data. Then we'll read that data and at that point we'll know that, “Hey, we successfully went through the entire flow that we're trying to accomplish,”
So, to make sure that we'll be able to register our device let's go in and actually create our first registration code which is going to be registration codes add, don't select new device because there are none at this point. We're going to say, one, two, three, four, five our code. Add that row in the database now let's hop on back and start going through flows. So, first off and we can just look at the names of our functions right here because these are the ones we'll be doing. So, let's run NPM- run exec -[unintelligible 18:39] - activity. And cool, you don't have permission to perform this operation because we're not registered or we don't have any API token. Look here in storage you can see that we just have an empty object; so, let's then run register. So, NPM, run exec and we're going to call register device one, two, three, four, five and here we go.
Okay so I know what happened there so essentially what's happening is that in this workspace we have it set up to where it's just deleting records, but not destroying them so our unique validation is still triggering. So, what we can do is we can hop right on back to our workspace and go update this code for a code that we most definitely have in use. So, let's say, six, five, four, seven, two, eight, nine. And I'm going to copy that so I don't have to remember it, we'll submit those changes. That code is now updated. So, go back to our command line tool, drop this in paste it and let's now register this device here we go cool. So, it said, “Adding the storage. Device is registered”. And if we go into our file here, we can see that our API token and the id of the device have now saved.
But now if we run that same command that we did earlier read activity, it's going to say, “Hey there's no data.” So, let's actually send some data to our API- extend the activity and activity. And then 1 to 120. Do another one just for fun 110. So, entry saved to device with that id awesome.
Now when we go ahead and run our read activity you can see that our device has been authenticated, it's getting the data back and forth and it's using that API token which created for it and associated with the right record. And what's important about this too is that where we create another device the roles and permissions feature that we're using that request an API token, the devices would not be able to see the data that either one is sending or perform operations on records that they're supposed to.
So, this is a really powerful tool if you're essentially, building this a fleet of IOT devices or you're having connected devices that might have access to AdSense data. You'll really want to use this type of system or a tool like this to scope down the records that these authenticated entities actually perform operations.
So, I hope you found this video helpful. If you did, please once again subscribe to the channel, it really helps us grow. And I look forward to seeing you in the next one. Thank you so much and have a great day.