Securing Xano (@nocodebackend) for Automation with Make (@make_hq) and Zapier (@zapier)

How to secure Xano API endpoints called from Make or Zapier using a lightweight API-key system. The presenter builds a reusable AuthWithApiKey function that checks headers against a database table of valid keys, then tests it in Postman to confirm correct keys succeed and bad ones return 401/403 errors.
Chapters
So this question comes from the Xano community talking about authorizing make.com to make a call into a Xano endpoint. I think this is a great use case for Xano where you can compose it into one of these other workflow systems like Zapier or like Make or like even code that you might be running on another server. And you can have Xano take care of some concern that involves, you know, doing complex data manipulation and working with Xano database. Whatever it might be. Now, when you're doing this kind of thing, it probably behooves you to use more of an API key type method where you have, you know, one key or a set of keys that you're allowing the other machine to use to authenticate itself. But you don't want to use the same kind of, you know, username, password, give a temporary token that's built into Xano. So Xano provides you, okay, so I can add API endpoints, start from scratch, do test, And the, and here is where I might either want to have, uh, be able to use built-in XAMPP authentication. Now, the tricky thing about XAMPP's built-in authentication is it uses cryptography, and that can be very, very fast, but it has some side effects. One is that it will, in the normal course of events, you'd sign in with a username password, it would create a token for you, and then that token is something you'd pass through the authorization header., but that, and XANA will take care of authenticating that for you, but it will only do it as long as that token is still valid. Now, you could set the expiration date to be relatively short and then it'll die, or you can set the expiration date to be a long one, but that creates its own kinds of problems because then you can't revoke it. It becomes a token that's gonna be usable by anyone who happens to get their hands on it. And when we're making API keys, it kind of benefits us to want them to be a little more terse and also to be something that we can revoke at a later time. So as a result, we don't necessarily want to use the built-in authentication that comes with Xano. So let's say, we'll say save here. And because if we were to make a built-in, use built-in authentication from Xano, we would use something like the, you know, the security functions where we can create an authentication token, the kind that goes built in with Xano. And here we can set what the expiration time is going to be. The tricky thing is we can't actually revoke it. So it's good for as long as this expiration time is. So either it's temporary, we need to keep reissuing them, or it is long-term and irrevocable, which creates a big old security hole. So what's the alternative? Let's not use this. And delete. Great. So instead, what we want to do is use an API token. That is going to be something that we have control over. So we would probably do something along the lines of this where we would say, you know, let's just do a new relation. I'm going to say let's create a variable and we'll call it, you know, a token and we'll call it, you know, 12345678, right? Just some string that like I know and you know, but the third party doesn't know. And then we can make sure that the request that came in is going to make use of this. And I can say plus, and I can do a, you know, I can do a check, right? Where I can do that by using a security function, which is under utility. It's called precondition. And in the precondition, we can set up a test. And this will, precondition is going to allow us to continue and be happy only if the test passes. It will, and it will set an error if the test fails. So here what I want to do is we want to say that the token is equal to the underneath the environment variables, and this is actually where things get kind of interesting, we can take a look at the headers. And the, in fact, let's, let's, let's step back for a second here. Let's, we'll say this is going to be, uh, the error type will be unauthorized in the event this fails, but we'll come back to it. Let's, let's take a look at what these are. Here we're going to say, let's take a look at the headers to to do, and that's gonna be under, well, let's just do a utility function and we will do a stop and debug of our headers underneath environment and taking a look at the HTTP headers. Save. Great. So now I'm going to, in order to do this, we wanna look at it from the outside. Run debug isn't nearly as useful when you're looking at the headers are gonna come in with a web request. So what we're going to do is we're gonna go over to the publish And I'm just gonna say publish it, which will make it publicly accessible. Copy this endpoint URL and go over to Postman. Postman's a great little tool for testing out web requests. And I'm gonna say send. And now you can see the body that came back. It says it came back with a stop and debug, and the stop and debug has a certain payload. And the payload is actually all of these headers I would've sent over, right? Except encoding, postman, from token, et cetera. So what if we did authorization? Let's do authorization using an API key. And classically, that's going to be based on a key called like x-api-key. And I'll say 12345, right? And I will say here, let's send that. See, now it shows. And now basically our Xano has received an x-api-key. Of 1, 2, 3, 4, 5. Now I want to really do something with that. Then what I could do here is say data manipulation and I would say create variable and I could say, see, and I will say this is gonna be coming from the HTTP headers,.x-api-token. What's it called? Key. I'll say save and I'll say stop and debug, not HTTP headers, but the receive token. And good, good, good, good. Okay, so let's do a publish of that again. And let's see how it looks when we actually receive it through Postman. Okay, so now, so basically every time I send something with x-api-key of 123345, it knows that it came back as 123345. So let's bring this down to the next problem here, which is we want our precondition to make use of that. So xAPI key. Remember, we can use dot syntax in Xano to get a member when we know that member is going to exist. And of course, if there is no xAPI key, then we'll explode using something else. And we have it set here that in the event, you know, that in the event the key does not match, remember if the, if it's, if the test fails, then it will say bad API key and it will send me back an unauthorized, which I think is a 401 or a 403. I will do publish. Now let's go see what we, over in Postman. Oh, so it has a stop and debug in it. And yep, there it is. Okay, let's get rid of that. And publish and publish. Okay, good. Now it's getting a very different kind of error. 404 not found. Why would it say 404 not found? It's called test get, get. Oh, the var one. Okay. The reason it's doing that is because down here it's saying var one. So let's just have it say hello error. Okay. That'll probably work there. And then let's also turn on the precondition. So that, look, it will say hello there in the event that it's successful. And it will say, and it should fail out if the token was not matched. Cool. Let's do publish. Publish. Send. Now it says bad API key. The reason it says bad API key is because the API key I sent is 123345, and the API key it's looking for is 12345678. So what if I tell Postman to use 12345678? I say send. Oh, and it gives me a good answer. Okay, so now we have the crux of how authentication can work, right? We have a variable, it receives, it returns the, you know, we, we, we, which is gonna be the one token we want to use. It's going to get the received token here and then compare the two to say, does this match this? And if it does, hooray, it'll give you a good answer. Now, that's fine for, but it has two problems. The first is we've hardcoded the token, and the second, perhaps more severe, is we've done it only in one endpoint. So what happens later on when I wanna make something else? I wanna create another API endpoint. And I call it, you know, test_get_2, right? And do I have to go repeat all that code? And the answer is basically no. So what I can do here is go to my test_get and say, let's grab a few of these things. Uh-huh. And these guys here, this token, token, token, we're going to say use a very cool little new piece of functionality in XAML called ConvertToFunction. I can take all 3 of those things. I'm going to say, you know, right? And then what that does is combine them all into auth with API key. And this becomes a new little function. And the cool thing is this function doesn't require any inputs and frankly doesn't even really use any outputs. It's just going to basically throw in the event that I don't have a good API token, right? So let's go, let's go back here. I have, you know, this auth API key, publish this, publish. And now I can run my testget again and I'm just gonna make it a bad key. See, and it gives me a bad key error. If I put in a good key, it puts in a good key error. That's really convenient. So now I've got this guy and now the next thing I'm going to do is go up to, is say back and say, well, what about using testget2? And testget2 right now of course works you know, all the time, right? It'll ignore the header entirely, but let's set it with a bad API key and it still says null. So now what I can do is just to add a custom function, which will include, and hey, what did I call that thing? A API, AuthWithApiKey. Cool. That little search thing for Ctrl+F, by the way. So now you see it takes no inputs, but it will die in the event that it doesn't work. So I go into here and I set, go into AuthTest2 and I run it again and see, hey, it says bad API key and then I'll say good API key. Basically I'll just say give me not very much interesting information at all. When— right, right now it returns a func one, which it doesn't really need to do. We can just say return string success. Publish that. Publish. Don't need to run debug because the nature of this. And we'll say run and it says success, right? Again, if I just have a bad API key, okay, that was problem number 1. Problem number 1 is how do we use the same thing across multiple endpoints? You can just drop this in and it will actually not need any more information. I can then go do other things or whatever it might be after this in my function stack because it will not bother me anymore with it. So that's great in terms of being able to use it across many of my endpoints. It'd be even nicer if it could be outside function stack, but it's inside the function stack. It's one line, it has neither inputs nor outputs. I can drop it in and forget about it. And then that way everybody's going to use the same code. But the second problem that I have, remember how I talked about how the, one of the problems with those, you know, cryptographic tokens that Xandon knows how to use is that they require, is that they, they create the potential of a security hole if they last forever. Now of course I can manually turn this over in here, but what if I want to have like a rotating list of good keys that I want to make use of? I could put that into an environment variable, I could put that into Redis, but you know, database is actually kind of good for this job. So let's just make a new one. We'll call it, you know, auth_keys and we'll have no CRUD endpoints for it. Thank you. And I will just call it, API key. Now this is cool. So what we're going to do here is we're going to say, you know, we'll put in the old one that we had, which is one— actually, we'll make sure we don't even use the old one. That way we'll know 6789. And, and by the way, there's, there's no reason why it has to be any, you know, particular set of key— of, you know, you know, letters, numbers, whatever. It could be anything you want it to be. All these API keys will work. As long as they are still set to be successful in here. And that way we can allow multiple to exist and you can delete them at any time. You can even have additional properties with them. Like if you want to have, you know, what, what, you know, you know, permission or whatever other payload you want to have go along with it. And that's for, you know, more advanced stuff for a future video or what have you. But the idea here is that I can have an API key and I could go back to my, you know, API and go back down to my YouTube and go to my test. And well, we'll just go to TestGet for a second and we'll say, I don't know why this is not yet published, but oh, this thing, don't worry about it. We'll go back in the Auth with API key. And, and here, instead of saying, well, we, we know that we received a certain token from the header, but what do we want to do with it? And we're going to do instead, we're just gonna do a database request where we're going to get a record from auth_keys. We're not matching on the ID, we're gonna match on the API key itself where it equals received_token. See, that way we're going to see if there is a good API key that matches the code that we just got and we will say save. In fact, There's an even better way of doing this. Let me pause it for a second. It's something that not as many people use in Xano is a, a database request and called has_record. See, instead of actually returning the whole record, this returns as true or false based on whether it exists. And for our purposes right now, that's all we really care about. I'm gonna say API key and I'm gonna say the value is gonna be the receive token. Cool. And now this guy doesn't even need to exist 'cause we don't need that API token. And then the, and the precondition is actually much simpler now. Precondition no longer needs to be that. The precondition is just going to be that whether or not we found the auth key is 1. This is just going to be a true or a false. And we will just ask whether it is true. It only works if it is found. By the way, me typing in true sort of automatically detects this is supposed to be the boolean true. And that, that should have basically the same effect. I don't know why it's running a GetAllVariables in here. I don't care about that. Right, so now it will check what we got from API key. It will run this if it has a record and it will give me a precondition. Fantastic. We'll say save that and we will say publish that and publish. One of the very cool things here is that this now gets automatically applied to all of my endpoints all at the same time. Right? I don't need to do— I don't need to go edit each of those endpoints based on the change I just made. So let's send this. Why it's complaining about this route. Oh, I see why. Okay. So let's trash that. Let's trash that. Right? No response. Publish. Publish. Yeah, that makes better sense. And now we will go back over to here. So I send. Okay, now it says bad API key. Now remember 12345678 in the previous version of the video? Hey, that worked. Oh wait, but it doesn't work anymore. Why doesn't it work anymore? Because if I go back over to my database, look at my auth keys, I don't have that. So let's put in this guy instead. Copy that and use that in my xAPI key. Send. See, now it works. Furthermore, I could use anything else that was also in here. Right, so it doesn't need to look like this little numbers with dashes thing. It can look like whatever else I need. Great. But if it doesn't look like it, or if it has any corruption inside, I just took out 2 characters in the middle, now it says I'm bad again. So this now gives us a great deal of flexibility on both dimensions. We have centralized We've centralized the concern of how to authenticate our endpoints by putting them into a single function that really only has 3 steps here. The first step is to extract the received token from the HTTP headers. And by the way, you can call the header key whatever you want. x-api-key is a convention. People know to look for it, and it's much easier to use than bearer authentication because that way you don't have to have that additional keyword in your authorization header., but you can do it either way. It's just a question of doing some more text manipulation. You just check to make sure that it exists in your database, which allows you to have multiple API keys going all at the same time, and just by deleting them from that database, you can invalidate one if it gets too old or you're worried it's compromised or anything along those lines. And then finally, you can set up this precondition so that to make sure that it only will fire when, when it works. So I actually think this is great for people who are using like the free plan to work with like the original, you know, use case of how do I do this with Make? Because it allows you to securely have a conversation with Make without having to go set up users or using Xano as your central store of truth or any of that stuff to do the data manipulation part that it's really, really good at. And that, and by being able to create this sort of central concern and be able to have multiple endpoints that are all doing that job, and being able to have rotating tokens, it all gets much easier to work with. And that allows us to extract the power from Xano in a way that allows the very no-code way to do it on the easy path. All right. We've done the hard things the easy way. Hopefully this is helpful to you. And this is the kind of thing we do all the time over at StateChange. But I hope on the YouTube session, it was useful for you today.










