Building Hoist (ep 3) - Creating a Node.js Express API that can talk to the Auth0 Management API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
let's build an api my name is ben decry this is building hoist episode three in the last two episodes we integrated sanity's headless cms and auth0's authorization next episode we're going to be integrating stripe but before we can get to that point we need an api an api that our application can talk to in order to communicate with your zero management api and with the stripe api let's get straight into it before we get started i just want to do a quick shout out to all sierra for letting me create these videos as part of my work hoist isn't a north zero product but they're really keen to see it succeed and maybe even use it one day i also want to let you know about a hackathon that they're running from the 7th until the 9th of august there are going to be thousands of dollars worth of prizes and swag given away and we're partnering with the likes of digitalocean versailles ionic gatsby aws and microsoft if you want to find out more there's a link in the description below at the end of the last episode we got to the point where we had the sanity headless cms integrated this gave us the program listing down at the bottom here and the actual program pages some image manipulation and resizing and also currently still only available on the 404 pages we created three plans that people could subscribe to the next logical step is to implement a payment and subscription mechanism which we'll be using stripe for but we'll do that in the next episode because before we get to that there's a little bit of preparation that i want to do with all zero integration we already have a login mechanism we're going to need to find some way of linking that user to the stripe customer id in the stripe system we could implement that through another database or maybe even put that into sanity but in this case what i'm going to do is simply use the app metadata section of the user object in auth0 let's have a look and see what that looks like if we open up the user here we can see there's a user metadata and an app metadata section these allow us to store information against this particular user profile the user metadata is for things like user preferences things that the user potentially has read write access to so we don't want to store things like the stripe customer id in here because we don't want the user being able to change their own stripe customer id their vulnerabilities down the track if we choose that option we can put it in the app metadata though the app metadata area can't be updated by the user but only by another application that has access to the auth0 management api if we look on the apis tab over here every new tenant automatically has the auth zero management api set up as an api and if we look inside we can see that the machine to machine connections we don't have any clients yet that are able to talk to the api so let's do that first thing we need to do is actually create another api for our express api that we're going to be creating we'll give this name hoist api and we need to give an identifier now normally what we do is we create something like localhost port uh not 8000 that's the gaspi application port 3000 standard port that most npm applications run on we would then configure gatsby's or zero integration to specify this identifier as the audience for the token which means that the token that gets sent back to our gatsby application can actually be used by gatsby or react to talk to our api now this identifier doesn't actually need to be the domain that our api runs on it can be any domain in fact it can be any string by convention we'll give it a domain though for us to be able to specify in the audience what i'm going to do in this instance here so i'm actually going to change this to be what i anticipate the api to be in our qa or staging environment and that way when we go into production or go into staging when we push it into a public hosted environment they'll be ready to go and i won't need to create another api configuration in auth0 so i suspect it's going to be dev dot api dot hoist dot earth so we'll just put that in i'm going to stick with the rs256 algorithm create that and we're pretty much done at this point in terms of the configuration on auth0 we've got the example express app here so let's go ahead now and jump into the console and create a new project so we'll go back up into the main projects directory and we'll make a directory called hoist api this is a brand new project i some people will store their apis and their applications in the same code repository i prefer to keep them separate because then it also means that it makes it easy for me to be able to deploy them to separate environments my plan for this project is to continue having the gatsby app hosted on netlify but to deploy the api on verscell let's go into the hoist api directory now and the first thing we need to do is we're going to need to install some modules over here so we can see we need express express jwt and jelly ks rsa so let's install these we'll initialize a new npm project here and then we'll install express express jwt and jw ksrsa while that's loading in the background oh that's don't worry we're just going to start a code environment here js code there we go so the first thing we'll want to do is create a new file and i'm just going to do a very box standard express app here i'm not going to go into the best practices in terms of how to break it down all i want to do is get to a point where the react app is able to send data into the auth0 api so we're going to create an index js file here for us to define the entire express application so let's jump back into the code here i'm just going to copy all this and paste it into our editor here and we'll have a look now what this is doing we're requiring the express module and from that we're instantiating a new application we're also bringing in the express jwt module and the jwk srsa module the expressjwt module allows express to examine the bearer token that gets sent in with requests which will contain the json web token and it exposes to us this method here that allows it to evaluate that token and use a secret to verify whether or not the signature is valid the secret is defined in a well-known url endpoint so the dot well known here is used by a number of different systems authorization and the oauth 2 protocol is just one of them and if you go to jwks.json at dot well known on any standards compliant identity provider you'll find something that looks a little bit like this and in here you can see that we have a couple of public keys and these can be used to verify that signature using this to define the jwks or the json web key set uri allows this jwks module to pull the secret out and pass it back into the jwt function the jwt function also receives an audience which is the audience for the api itself this is to verify that the token is actually intended for our api and not some other system it also receives an issuer which is the name or the url of the identity provider endpoint for us that's our hoist dev url here and a list of algorithms the result of this object here is stored in jwt check which we can pass directly into the entire application to protect every single endpoint the alternative to that is we can also put it into the second parameter here of any of the app.get or app.post endpoint definitions which would allow us to if we remove this secure just specifically this endpoint here we then had app dot get just the root directory for example and we passed into that a function with a request and a response and we did a request.json and return an object with a message of okay and close that off here this endpoint here is now publicly accessible whereas this one here is going to require authorization now remember how i said that the audience was just an identifier in our case here we're running on localhost but our audience is still going to be dev.api.hoist.earth so let's now create our first endpoint we don't really want one called authorized we want an endpoint to manifest a new stripe customer so let's do that we'll put it into a user directory manifest stripe customer we've got jwt check in there already so this can only be called with a valid access token which will contain inside it information about the or zero user which we can use for this linking we don't really want to send this response here what we want to do instead is make a call to the management api to update the user with a new stripe customer id in order to be able to call the auth zero management api we need to do two things first thing we need to do is get a json web token that allows our api to talk to the management api this can't be the same access token because the access token generated by the user logging into the hoist application only allows the hoist application to talk to the hoist api so we're going to need to create a new access token for the hoist api to talk to the author management api this is going to be a machine to machine client and we're going to be using standard credentials just a username and password essentially for authenticating to or zero in order to get that json web token back now there's an easy way to go about this we could go over and have a look in the management api documentation we can also simply jump into the management api here and go to the test tab if we click on the create an authorized test application it's actually creating an application for us called the all zero management api test application and in here it's going to give us some code that we can use to get the json web token that we're after so let's copy this here and we'll paste this into here and essentially what we're doing is we have our client secret defined here client id these are automatically inserted in to the live documentation from auth0 because it knows which client we're working with so if we run this now we should be able to make a request to the manifest stripe customer endpoint we'll have to provide in a bearer token so we'll do that and we should get a console log out when we're in the application here and see the json web token returned so if we save this for now and we run node index.js the application is now listing on port 8080 let's change that to 3000 so we'll save that and restart the service here if we just come in and test we do have something happening so we've got an ok coming through here which is the test function we put in earlier so that's working fine if we made a request however to this endpoint then we should get and no authorization token was found so let's jump into our gatsby application now and create a request that will pass the correct token in so let's put this into the account.js file we know at this point they're already logged in and all we want to do for now is to create a request that will allow the api to get the token we're not going to do much more in the gatsby app today so we'll come up here we've already got the user coming in from auth0 and we're going to need to get the access token as well so we'll request get access token silently this will fail if those if the user is not logged in which at this point they should be anyway but it'll fail silently which means that it allows us to continue operation but know that they're not logged in and we don't have access to an access token let's define a function called create customer and we'll call that get access token silently the call to this is going to return as a token so let's just log that for now we'll need a way of calling this method so let's create a button down here and if somebody clicks the button we'll do an on click and we call create customer so let's save that we're reloading down here jump back to our application and into the account page so we'll need to log in down here and now we have this create customer button so let's pull up our console here so we can see what's going on in the logs clear that out and click on create customer and we have here a token that's coming back now this doesn't look like a json web token that's because it isn't this is an opaque token and it's used purely to call the end point that provides the user info so we need to configure our gatsby application to pass in the extra audience being our api that we need the token to be valid for so we'll do that down here in the gatsby browser where we defined the various parameters here for the author provider we'll give give another one audience the value of this one is going to be our dev.api.hoist.earth so let's just put that in for now and we'll break these out into environment variables later if we just hit save and log out and log back in again in fact gatsby is reloaded in the background and is now asking us to authorize because our audience has changed we have to reauthorize now this is happening because we're running our application in a local host environment when we go into a production environment this wouldn't come up for our users so i'm just going to accept yes to this one let's clear this log again and hit create customer and now we have a json web token let's just have a quick look at this and see what's inside so we can see in here that it was issued by our tenant the subject here ending in 7379 is my user id and we can see back here in hoist earth the 7379 is the subject that's passed into the access token we can see the audience is for both the api and the user info endpoint so this is the access token passed back via auth0 when the user logged in we can use this to talk to our api now so we come back into the accounts page here we know the token is working for us so using fetch we're going to make a call to the hoist api now let's define the api domain in our enviro environment variables it's something that react app is going to need to know about so let's put the gatsby prefix in front of it we'll call this the host api and we know that that's going to be localhost so we'll save that i'm just going to reload gatsby in the background so that we can start bringing that new environment variable in and then here we're going to fetch from process.nbc from the api and we will add on to this the endpoint that we just created which is manifest stripe customer now by itself this is going to send a get request which is fine but we need to add the token into the headers so we're going to pass a second object in here which is the options that we're going to give to fetch and one of those option types is headers and in headers we want to provide the authorization header which for a json web token is a bearer token which we pass in like this assuming everything's okay we're going to get a response back which is going to be of type json and then that json we will just send to the console log that hit save on that and we'll run this again now i'm expecting an error at this point because we have a cross origin request block let's have a look at the api again so one of the issues we have is we're making a request from port 8000 port 3000 this is going to create a cross origin request which by default is blocked for security purposes so we'll need to add in here a new module we're going to install cause by default when we implement calls it's going to allow any origin to make a request to the api because we're also securing the endpoints with json web tokens that doesn't concern me too much but it's something we might be addressed in the future so up here we want to now pull in cores and then after the app is initialized here we're going to use cause so let's save that restart node jump back over to our browser let's clear these and run create customer again so we're making a request here now and passing in the token let's have a look what's happening so we're getting an access token out here this is the console body log we've received the token and as part of that is the access token this access token which comes all the way down to there is the token that we use to talk from our api to the management api several chords inside this one so here we see the issuer against is our auth0 tenant the subject here is different though the subject now starts with i and ends in w now if we look over in the api app the author applications here we have this one here the start of i and if we go all the way over into the w so this is actually a reference to the application that's connecting so we can tell here that the subject is our application it's not our user it's the api the audience is now for our management api which is the slash api v2 running on our tenant now we have this token here we can use that to make the request what i'm going to do first is i'm going to convert this into a promise because down the line i imagine we're going to need to make more requests to the management api i don't want to duplicate this code as much so now as a result of running this request rather than throwing an error or console logging let's change this so we actually resolve or reject the promise so if the promise now completes we'll be returning the body but passing it beforehand so it'll actually be a json object that gets returned so then in our endpoint down here we can call the get management api json web token method which returns as the entire response we know the token is the access token element on that response we can use that token to make a request to the management api so let's copy this part here again and we'll need request in here so now let's have a look to see what kind of request we actually need to make we'll jump back in over here and we'll actually look at the management api documentation now and if we jump down to the user section we have a updater user so we want to make a patch request to api v2 users followed by the id so the request here is going to be to api v2 users followed by the subject of the user which is passed through in request.user this is one of the other things that the express jwt module will do it'll automatically inject the broken down user information from that json web token that gets passed into that initial request to our api it'll add that in as the user object on the request that gets sent in to any of our endpoint functions here there's a patch request so we'll change the method there and we need to add an authorization header again json web token it's a bearer token and the token we're passing in is the token we received up here and finally the body that we need to send in is going to be the app metadata that we want to set and this can be any arbitrary json we want to store a stripe customer id so i'm just going to call it stripe customer already now for now we don't have any value to put in there that'll come in the next session so that i can see whether or not it differs for each user i'm just going to put the subject straight back in and finally because we're sending json through the body we just need to define that json is true and the request down here is uh doing the reject or resolve that doesn't make sense anymore so i'm just going to revert that back to the previous format we had where we just throw the error or return the entire body back to the browser finally we need to restart our api we should be able to jump back over here let's just clear these out hit create customer and we get a response back now saying invalid token this is actually the response from auth 0's management api back to our api which then being returned to our gatsby application the most likely reason for this is that the token is not allowed to update the user record so let's jump back over to auth0 and we'll have a look at the auth0 management api it's the api we want to deal with and have a look at the connections we've got in the machine to machine section so the test application here starting i ending in ew that's the actual client that we're currently using to connect now technically we'll want to create a separate application in here for our api we'll get to that but for now we can test this by making sure the permission for this connection here allows us to update the admit data so we'll just select this one here we'll come down we'll hit update and now we should be able to jump straight back here without any changes to the api hit the create customer and get a positive response back which is the information that is now stored in the auth zero against the auth zero user and we can see here the app metadata comes through and in fact if we look at the users now we'll be able to load up our user and see down in the app metadata section that the new stripe id has been saved in there and we've actually just used the auth0 subject for now so this is good we need to do a little bit of cleanup but we've got the end-to-end process of the data now flowing so let's clean up a couple of things we want to come to the applications we've got these test applications already and these were created automatically by author whenever you create a new api it will automatically create a test application for you and for the auth 0 management api one isn't created automatically when you create your account but when we went into the test tab and created the client from there that's what was created from here so this is the one that our api is currently connecting to i'm going to clean this up slightly and give it a different name we'll save that and if we come back to our applications here this test application here we're not going to use so i'm just going to remove this so i'll copy the name which is requested for the deletion now we have our applications cleaned up we've just got the hoist api and the hoist hoist earth main application in fact let's rename this to voice api dev and the main reason for this is that when we're logging into systems it'll come up as the name the hoist earth name will definitely come up when we're trying to log in and it's just for us to know when we're developing to have this assurance if we're on the development site and certainly we're logging into the production tenant that there's an issue somewhere finally we want a little bit of cleanup in the code here so let's create a an environment variable for the auth0 aspects of the configuration so we need an alt zero domain we need an auth zero client id and we want the alt zero client secret let's grab these so the all zero domain is this part here the client id is this one here and the secret is in here let's save that and finally in order to be able to use them in our application we're going to use the dot end module and to use that we simply add one line at the top we require the dot enter module and the response from that directly is the dot end object and we can call the config method on that and the default is that it will pull everything out of the dot inf directory and make that available in the process.n object we can now replace all instances of the auth zero domain the same with the client id now in fact here we're generating a string for the body i'm going to use json.stringify instead so this is easier to read i'm not going to modify this one here because the audience will come to a cleanup later so let's save that and we'll just start it up again and make sure that everything's still working as expected we come in to here i'll remove let's edit the user and we'll remove the data from here again now let's just hit the create customer endpoint we get a positive response over here and if we refresh the user information we get the stripe customer id again with the auth0 subject one final test i'm going to log out and i'm going to log in with a new account so we now have access to the account section we can see that we have a different subject here now ending in 898 b if we look at the user in the system we can see the new user account has been created but there shouldn't be a stripe user id just yet and if we now hit the create customer on the left hand side we should get a positive response on the right and if we refresh this user we'll get the add metadata updated with the stripe id which will contain this user id ending in 898 b which is right here okay i think we're in a good position for the next stream it'll be released in about a week and i'm very excited to have thor shafe from stripe joining me for that in that we're going to be extending on the work that i've done today to connect to the stripe api create a customer we'll also be defining products in the stripe dashboard and linking up the plans that we have on our site to the products in the stripe site so that users were able to create ongoing subscriptions i look forward to seeing at that one i hope you have had fun and thanks for joining me hey are you a web developer do you care about security and privacy are you interested in the internet of things and what about videography and streaming well these are just some of the things that i talk about on my channel there's a couple of videos over here that you might be interested in but until next time thanks for joining me and have fun you
Info
Channel: Ben Dechrai
Views: 937
Rating: 4.8095236 out of 5
Keywords: node.js express, node.js & express from scratch, express api, express api tutorial, express api authentication, jwt authentication, jwt authentication node js, jwt token authentication web api, node.js express tutorial, node.js express api, auth0 api authentication, auth0 express jwt, auth0 node js express, auth0 react express, managment api, auth0 user metadata, auth0 user management, auth0 user managment, api authentication node express, node js express api authentication
Id: smMsWpxrrVE
Channel Id: undefined
Length: 27min 49sec (1669 seconds)
Published: Sun Jul 19 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.