Using JWTs with Xano (@nocodebackend)

Ray Deck explains how JWTs work in Xano: the three-part format (header, payload, signature), the difference between signed (JWS) and encrypted (JWE) tokens, and how to decode and validate them using public keys from a JWKS endpoint. He walks through extracting fields like email, checking expiration timestamps, and debugging with Xano's built-in tools.
Chapters
Let's talk about JWTs. You've probably heard the term a bit around. These are tokens or strings that are used usually for authentication purposes. And really what they are are signed payloads that can be sent over the web and then verified using some new techniques that are relatively standard and easy to work with. Xano uses JWTs under the covers for its own built-in authentication. A lot of other systems do as well. And you can use these tokens to usually get through the authentication process for various third-party services. But it can be helpful to look underneath the covers, because sometimes you're in a position where you need to interpret somebody else's JWT, and sometimes you're in a position where you want to create your own, and understanding how they are and why they work can be really, really helpful. So the, um, let's start by looking at what a JWT, a JSON Web Token, looks like. There's a wonderful tool called jwt.io, which is, I think, by Auth0, um, that will, um, let you, you know, just take it apart. And you'll find that they're almost always in these, you know, the encoded using strings and using letters and numbers and what have you. This is an encoding that's called Base64. So they take just the original bytes of the encrypted or signed payload. And they, instead of like giving you the direct bytes, they turn it into uppercase and lowercase letters, that's 52 different possibilities, right? 26 letters in the alphabet times 2 plus 10 numbers plus, you know, a couple of other characters to get up to 64 possibilities, which has the interesting characteristic of being 2 to the 6th power. So you can send 6 bits with every character as opposed to 8 bits that you'd usually do in a byte. And that's one of the reasons why Base64 stuff is going to be a bit more verbose. It's longer, it takes more characters to convey this way.. But the, but the key to it is that just encoding is not encryption. You can look inside it anytime you want. In fact, Xano even has built-in filters that are called base64_decode that can be used to look at this. But for us to get an understanding of how the JWT works, let's just take a look at here in jwt.io. This is actually an example package that came from, came from state_change_user a while ago. That was from FlutterFlow authentication. This was called an ID token, something you can get after you've logged in to FlutterFlow using its Integrated Google Auth, right? So this is a Google token. And it has 3 main parts. And you'll notice that each part is Base64 encoded, and then separated by a dot. So whenever you're looking for JWT, look for the dots. If you just try to Base64 decode the whole thing, it won't work because the dots will confuse it. But if you separate it based on the dots, you can see there are 3 different sections to it. And the first section we call the header. And you'll notice that each section usually starts with an ey. This is a characteristic of the fact that under the covers, it's encoding a JSON object. That's why it's called a JSON Web Token. And basically, this little curly brace and this little quotation mark, you know, the first bits of those are going to always be an ey. So whenever you see an ey at the beginning, we're often talking about JWT, or certainly something we can decode with JSON after the fact. And it's going to contain a few things that are relatively important. The first is going to be what algorithm is it using to sign this particular token. This algorithm is is actually the thing that trips up the most people. And if you were to go back over to Xano, and you want to say, well, I have one of these tokens, let's go decode it. Well, let's go to— we're going to go create a new function, we're going to use a security function. And we're going to say, let's decode a JWT token. Now, You'll notice this thing says JWT. It has all this stuff to it. We're about to talk about like, you know, how the, the, the signature algorithm works. And you'll notice that here we have JWE and JWS. You're like, wait, neither of these things say JWT. What's going on here? And the reason is that Xano is a little bit particular about this stuff and actually supports the two of the big ways that you can manage JWT. There's what we would usually call JWT, which is a signed token. Which is not encrypted, right? So the information in it isn't secret, but it's signed. And so that you can confirm its, its provenance. And we'll talk about how to do that by using the algorithm and verifying signature in just a second. And the second is what's called an encrypted token. And the GWE for encrypted, GWS for signed. So if I do GWS decode, it will just tell me, okay, what are the you know, what was the signature that was used for it. Whereas if I were to say, JWE decode, it will need to know if I go to go here to security, and I go to JWE decode, you'll notice it wants the, the, the, the actual key, they need to actually decode the, the, the underlying token, right, so that way, you can unlock it like it's a, you know, secured and and completely private message. Xano uses that for the internal authentication, but it's not something the vast majority of systems use. I would encourage you to focus on using the JWS instead of the GWE. The GWE is cool, we can run up the score, but JWS is going to be what you're using when you're talking with Google or Microsoft or any of these other services that use these kinds of tokens, and it's going to make your life a lot easier if that's what you're using as well. So let's focus on, you know, taking out the GWE and we'll focus on the JWS. The point we were about to get into was this idea of the algorithm, right? The algorithm, which is the way this thing is going to get signed. And so you're going to have a payload here in the middle, right, which is your data. And that data is the information that's, you know, really you're sending over that's important, saying, hey, who you are, what's your identity, like you are test@test.com, that kind of business that we're using to actually identify or provide information that is going to be useful going over the wire. And then we have this blue part, which is what we call the signature., and the signature, uh, we is how you can verify that the token that was created came from whoever it was supposed to have come from. And this is important because that way Google can send over, hey, here's token created by Google. And the token was created, um, this is what the IAT is. It was issued at, uh, a certain time. And this time is a Unix timestamp. Um, and you can see here that jwt.io will show me what it is, but it also gives me an expiry, which is this is when you should ignore it. When the token is no longer any good. This is super helpful because that way Google can send out a token, can say, okay, well, this token goes with this person and this person is authorized. And I will respect this token and use it as a key to like, I don't know, redeem for services or whatever until this expiration point. And if someone's walking around with this token after that day, that's fine, but it's not going to verify this is who they are. So this idea of it's good as of this time, is good until this time. And then the other information about who's going with it, and maybe like what permissions they have, or whatever it might be, is going to be what we're sending over in the JWT. And that's what you're going to send back to Google for the purpose of getting, you know, like the next level of token or authentication or whatever. And then this information need to confirm actually came from Google. Right? Because otherwise, anybody can sort of, you know, scribble down their name on a piece of— scribble down somebody else's name on a piece of paper. How do you know, like, what's the equivalent of having that signature at the bottom of that piece of paper that says this actually came from Google? That's what this blue part is about. That's what the verify signature part is about. And the— and this brings us all back to the algorithm thing we're talking about at the beginning, because that is the way that we can confirm. So what happened was somebody made a key and that set up what was called a private key and a public key. Their private key is what they use. So they create this piece of text, which is this little bit of JSON here. They then use their private key to create a signature of this particular string, which is a message that only they, or at least, you know, without a whole lot of math, that only they were really able to easily create. And then it is something that you can verify using a public key. And the public key is actually where the other part of this thing comes in, because you can't, you know, this RS-256 refers to the RSA algorithm for creating public-private keys. And they said they use that, and you can go find the public key that you can use to verify this blue text using this, what we sometimes call a KID in change, but is actually a key ID. And the, the key ID is usually something that is stored in a known website. And I'm just going to, you know, copy this over to here and say, right, so here you can see this is the Google API's list of known keys that you can use to validate a, you know, one of these tokens that will have come from Google. And so you know that you can use this algorithm. You know that you're going to use this key, 545. And by the way, it's an old key, so 545 isn't even a valid one anymore. But you can see here, this is also in JSON format. This here is your key, and this here is the value. This is actually the, what's called PEM-encoded the public representation of the public key that you can then use to validate this is actually an okay token. So if you're using RSA and you're going to use the kid to validate it, and then you're going to be able to look at the data inside, how do you do all this in the context of Xano? And Xano kind of rolls these ideas together of Base64 decoding it, of looking at what's inside the payload, but also validating the signature and making sure that you are before the expiration date. It does it does this all at once inside this JWT decode. And so you have, you put in the text of the token. So if I were to say, go over to here, I could, you know, copy up, you know, the, the text of the token into it. Of course, you can just do it with a variable. You can give it the key. And the key is actually going to be what came from here, right? So if I were to copy this URL, and I were to say, alright, let's just do a quick external API request to this particular site. And I just put this before. And I say run that, run that. And I don't even need to worry about that. And then I say enable the variables that way we can take a look inside. Request. And I can take a look at my, the response that came back. And you can see what happened is I have a key and I have a value and I have a key key, and I have a value. And if I want to, I could probably take, you know, one of these, these values from inside here. And if I could, you know, tell the JWT code to please just use api1.response.result., you know, whatever that key is. Now, it still wouldn't work because this key actually doesn't go with the key that was sitting inside the JWT. And so it'll just say it's invalid. Right. Oh, sorry, it had a space in there. So we'll fix that. And also probably more commonly, instead of doing it that way, you'll probably do something like a— just use a GET because you're going to get it based on the, the actual key ID, right, that you're looking for. But I'm just going to hardcode it for a second. Right, and then it's unable to verify the token. So what happens is it will refuse to decode and work with this token unless it's able to do all the things, unless it's able to, one, read it as JWT, to, you know, confirm that's using the same. And then using this algorithm, and using whatever public key you just passed to it, they might have gotten from Google APIs, that you're able to then you know, just confirm that it works. But you don't have to. Now, one of the things you might have noticed looking at this, like, huh, well, this is just like 3 pieces of JSON that are connected together. So if you're in a position where you're having some trouble getting this thing to authenticate, you're just trying to keep on moving with your development. Another thing I recommend doing is— don't recommend doing this for production, but is a useful thing to do to sort of make sure you're not getting stuck on all this validation stuff when you're working with the JWTs for, you know, like confirming something came from FlutterFlow, what have you. If I were to just quickly create a variable, and that's going to be the— I'll say it's called JWT. And I'm just gonna— that didn't work. Copy this, copy this, and paste. Expand it, you see lots of stuff in here, right? So that's my JWT for a second. You know, and I just throw a little stop and debug in here to make sure that I can see it. GWT, right? And then if I were to just say rerun and show me the GWT, right? Lots of text. Well, a thing I can do in here, it's actually kind of cool, is I can like say, let's take a look at create variable and then call it pieces. And it's going to be equal to JWT, right? With a filter of split. And split allows me to take a single string and knock it apart using some known character. In this case, we're going to use a dot because we sort of discovered that 3 parts of JWT are connected with those dots. So we'll say update to that. We'll say save that. And then when we run, and in fact, what we're going to do here is just say my stop and debug should tell me about the pieces instead of telling me about the whole JWT. Run. Okay, cool. So now I know I have these 3 pieces, which are just like the, the, you know, color-coded pieces I have here, here, and here. Now, the 3rd one, the message, that's kind of hard to work with. The whole point of the reason you might be doing the split is because you're having trouble verifying the message. But we can take a look at what's inside these first 2, which can be super, super helpful to make sure we're going to do the right things with it. So inside here, we would then say, well, let's take the pieces and let's create a variable and we're going to call it header. And it's going to be equal to pieces.0, which is the first part in pieces. And then we're just going to say it's a base64 decode. And then we also know that it's JSON encoded underneath that. So we can stack our filters. Say first JSON decode, first base64 decode, and then say, just give up the game. We're going to JSON decode it. Okay. So if I got my header, da da da da, and if I do my stop and debug and say, let's take a look at the header instead. Right, so I'm gonna make my— so I've got my JWT, right? I broke it into pieces with dots. And now I've got the header. Cool. Now you can see those are the 3 pieces to it, right, the 3 components, the algorithm, the kid, and the type, just like we saw over here at jwt.io. Now, because I can do that in the header, that, that's actually really convenient. Because when you're later trying to dynamically work with this, like, you know, verifying a Google token or something, you're going to want to be be in a position where you can find out which key ID you're supposed to use. And so taking the JWT, splitting out the header, and then being able to look up the key ID so you can dynamically figure out the right thing is a super useful trick to have in your bag. Now, the other thing we can do is we can actually take a look at all of that payload stuff without having to go through the JWT function in Xano as well. And we do that by taking the second part of the piece. So we're going to create a variable.. And we're going to say, we're going to call it payload. And it's going to be equal to pieces[1]. Oh no, not, not square brackets, right? You're not in JavaScript. All right. So pieces[1]. And then we're going to do the same two things we did before. We're going to base64_decode. And we're going to JSON_decode it. Excellent. And you're going to, you know, rerun that. Oh, sorry, this time we won't look— not look at the header, we'll look at the payload. Cool. See, now you're able to see all this stuff. And this is just available to you now as an object, right? So if I just want the person's email, then I can do something like create variable, email, and well, I can just sort of grab that, and I can say let's grab it from payload, and we're gonna just define the subpath of, and then we'll look for their email, right? So payload.email, which I really didn't need to do the whole subpath thing just to get the.email part, did I? And then I can confirm that what I have in email is just in my stop and debug is just using email. So cool, right? So now we have access to the information inside the payload without having to go through the core Xano function of doing the GWS decode. The GWS decode is going to be most useful to making sure that like, well, one, of course, it takes care of these steps all at once. But the most important thing it's going to do is validate, right, that the blue part of this message actually goes with the origin that we think it's supposed to go with, i.e., it's actually something we can verify using this particular key ID, which presumably we should have only been able to get from a known domain like googleapis.com. Okay, so hopefully what this is doing is giving you a good sense of what's, what's inside one of these JWTs, right? It looks like a big blob of text, but you can always look at, you know, bust it open using a nice tool like jwt.io. Io, and you can also open it up in your function stack by splitting it and then starting to do the Base64 decode and JWS decode. And then you can validate it. You know, this is really where it pays its bills. You validate it using the correct ID and also using the correct algorithm, right? So, you know, you saw, see here how it has a few different values, which are the P, which is for probabilistic RSA, the HS256, which you're almost never never going to use because it's what's called a symmetric algorithm. It doesn't have a private— it doesn't have a public key. Both sides basically need the private key to validate it. And then RSA, which you're going to use much more. In fact, of all of these, you're most likely to be using either RS-256 or ES-256. RS refers to RSA, which is a, you know, it is based on using very large prime numbers, and ES, which is Under the covers, actually the same technology that like Ethereum uses for its cryptographic signatures and crypto. It will sort of draw a curve. And then there's like a very specific way that you draw a line through that curve. And this is actually more secure if you had a choice than using RSA. But RSA has been around for longer. And so it's one that's more likely to be used. This PS, which is probabilistic RSA, which isn't as common near as I can tell, but is, but can be kind of a handy way to use RSA RSA and like sort of, you know, throws a little bit more randomness into it just to make it more secure. Otherwise RSA is an older standard, it's a little bit less secure than like, um, ECDSA, which is the ES one. And then HS, which is one you're almost never going to use because it's symmetric. Um, now somebody else might use, uh, HS and you will be bringing that in, but, uh, you'll find in generally the, one of the big benefits here is using public private key encryption, which is, you know, a whole other topic. And then, you know, how much the, the, these are largely going to be okay for you. So this would be how you do it to validate it, to make sure that's good, to make sure that the, you know, issuance, the expiration date, everything's lined up. And then it will basically fail out if it's not going to validate it, and it will continue if it is allowed to validate it. But you can also decompose it by using the approaches that we just talked about. In here. There is an additional way you can use JWTs to create your own authentication system, or, and some people will require you to create JWTs on your own. But I think that can be the topic of our next video on the subject. So if you've got questions about how to be making use of JWTs, and what they are, and how to be validating the key IDs for the various services that are out there, you know, please drop a question in the comments. And if you got, you know, more in-depth questions about it, please check out StateChange, where we work on the hardest 5% of these things every single day. Till next time.










