 Hi everyone, nice to meet you. I have a few questions for you. So who here knows JWTs? Knows them, uses them, cool. Who here knows how JWTs were born? How they came to life? Yeah, good. Okay, so the rest of you that don't know how JWTs were born, you're going to learn today. Isn't that cool? I think that's awesome. But then again, I like to talk about these things. And you're also going to see your first JWT. So I hope you enjoy your time with me today. And let's talk about JWTs. But before I get started, let me introduce myself. Hi, I'm Jess. You can call me Jess. Jessica is too formal. So hi. Only my mother calls me Jessica, I think. I work at Auth0, which is part of Octa. And we are an identity platform. Basically, this means that we make it as easy as possible for you to implement the authorizations and authentication flows on your web apps, apps and APIs or whatever you need to do an authentication flow. As my host said, I have a podcast in Brazil, my colleagues that do the podcast with me here today. I'm so excited. Thank you. And I do Git Vicious, which is a Git study collections card. So if you need help with Git, go there. It might help you. And you can find me on most social networks under the handle, just in parallel. So disclaimer, first things first. Usually I call JWTs. JWTs, I say the three little letters. But if you come from an English speaking country, you probably heard the name Jot. That's the name of JWTs. Where I'm from is usual to use the three letters. And I'm going to be speaking JWTs or Jots throughout this talk. So keep that in mind. Now disclaimer over. And it's going to be some cold at the end, so don't worry. So it's impossible to talk about Jots or JWTs without speaking about the JSON object signing encryption, which is an amazing effort to create a collection of standards and patronizations about the web, and specifically JSON objects. And today we're going to speak about one RFC. That's our main focus. That's the RFC 7519. That's commonly known as the Jot specification. And that's going to be the things that we're going to talk about. It's going to be in there. And usually a JWT is a standardized string that represents some information. So it conveys some meaning depending on your systems and your situation. And so let's break it down. So JSON is the object, is the way that we're going to structure the information we're going to carry from 1.A to 1.B. Web is where this information is going to be carried over. So it has a space constrained environment. So that's how it's going to outline most of the things that we do with JWTs. And token usually is a unique identifier and that is specific to context. So it can only convey meaning depending on context. And if you've never seen a JWT before, I know some of you already have. So this structure will be familiar to you. But at the first glance, this looks like a random sequence of characters, letters, numbers, and other characters. But if you take a closer look, it actually has a three-part structure, the header, the payload, and the signature. So let's break this down a little bit more. So the header contains information about the token itself. What type of token it is, what algorithms were used for signing and creating that token. So you basically take a JSON object for us in Python, which I love. It is a dictionary kind of information structure. And you encode it into base 64. And notice the word is encoding, not encrypting. So anyone that knows how to decode a base 64 string knows how to get this information back. The second part is the payload. That's the coolest part, or at least one of those coolest parts. That carries information about a given resource. If we are talking about a logging scenario, this would be information about the user, for example. You might have information about me in a hypothetical scenario. So my name, my last name, and when I created that set of informations and what is the subject, that would be the subject of the token. Well, a user, in this case, me. And it is important to notice that both the payload and the header are only base 64 encoded. And each part of this JSON object, or this dictionary, if you prefer, it is a what we call a claim. So each key value pair is a claim. It is the most basic structure inside of JWT. And we have three types of claims. Why not? Right? The first type are the reserved claims. These come from the job specification. So these are standardized by the job specification. You can have a subset of the claims in the specification, or all of them. It depends on each case. And will depend on your case. And the reserved claims come from the specification only. And information like who is the subject of the token, who created the token, when the token was created, and what is like the expiry date of the token. Good. And the second type are the public claims. Those are standardized in a way by IANA, one of the organizations on the Internet. And they idealized for us to have some sort of interoperability in between systems. I love the word, even though it's very hard to say in English and in Portuguese, too. So the idea is that everyone would speak the same language when creating, when using claims they are standardized by IANA. So, for example, instead of using first name to refer to the first name of the user, we'd use given name. Instead of using family name, instead of using last name, we would use family name. And so on and so forth. And guess what? This list is extensive. That is a lot of public claims that you can use already. But in case you need a very specific claim for your systems to work, there's another type of claim that you can use. And those are the private claims. They are particular to your system and your situation. And they can be anything that you want, really, anything. And as long as you keep in a valid JSON format or dictionary, and we know that we can validate these kind of things in Python in a very easy way, you can have any information in there. But the more information you have, the bigger the output stream you're going to get. So try to be mindful of the information that you put on the JSON Web token. And try to keep it only the relevant data in there. And you're going to see a little bit, you know, in a little bit, why? Now, the signature. I left this part for last. Well, because it comes last. And because it's a little bit different from the header and the payload. The signature takes the header and the payload into account. And it passes this information inside of an algorithm to, well, sign the token. And, well, here I have an example of an algorithm that has 256. It only takes a secret together with these information from the payload and the header. And, well, this secret is actually not as good. It usually would be something like this, a random string generated by secret generators. Please. This is only an example. Don't use this in production. But the idea is the same. And there are two types of algorithms you can use. The IHS 256, my Portuguese almost spilled, is a symmetrical algorithm. It only takes a secret both for signing the token and for verifying or validating the token. In Python, depending on the package or library that you are using, it would mean that you would probably decode the token, even though the code is not the correct term for verifying a token. There are the type of algorithms that you have, and that's the one that I like the most, the asymmetrical algorithms. And you can notice here we use two different keys for asymmetrical algorithms. One key for signing, that's the private key, and a public key for verifying the token. And the cool thing about this is the public key, you can share it with everybody else. So in case you ever sign a token, somebody can check whether or not you signed the token, because there is a way for you to share the public key for people to validate the token. And there is a format to do that. Part of the Jose, the JSON object signing and encryption, is JSON web key that comes from a different RFC, the 7517. And it specifies the format, also a JSON object, for you to share the public key. And if you never see one, it looks a little bit like this. Of course, it's longer, I shortened it for it to fit on the slides. And the cool thing about this is because keys are bound for by mathematical properties, you need to know each parameter to generate a key, and what is the relationship between the public and the private key. But another cool thing, you don't need to know all of these things about the mathematics and the functions for creating the key. Most packages and libraries today, they already take care of that for you. And if you're following OIDC or interact with the API and systems that follow OIDC, they probably have a well-known endpoint that you can retrieve these set of keys. So you can just send the endpoint link for the package, and they'll be fine. The package will know what to do. Now, let's see some code, because why not? So if you are dealing with JWTs, you probably want to verify it. And I'm using PyJWT or PyJot, a library that a colleague develops and maintains. And this is an example token, so keep that in mind. It's not a real case token. I created just for this talk. And if you import JWT, that is from PyJWT, and you create your token as a string, you're going to be able to validate it. And there is a couple of things that you can do while validating your tokens. But the simplest case is to import JWT, pass along the string of your token, and use PyJWT, or in this case, JWT object, to decode the token by passing along the token string, and passing along the key or secret, in this case, it's a secret, because this token was generated using a symmetric algorithm that I already know, and it's super secret, as you can see. And then you can pass what algorithms were used for signing the token. And I cannot code without making typos, so you can see there in the recording too. So once you decode it, if everything is successful, you're going to see the payload of the token on your screen. And you can save that into an object for using that later if you need it. Now, if you don't know everything that is to know about a token, for example, you don't know what algorithm was used for signing the token, you can get that information by using a method called get unverified header in the case of PyJWT. And you pass along your token, use that method, and it should reply to you another dictionary with all of the information of the token. And there I go typing wrong things again. And once you get that, you can put that into object and use that on the previous step that we already seen for making your code a little bit smarter. I always do that because you never know. Maybe a token has a different type of algorithm, you never know. So we save that in a header data object there because I'm very particular about the name of my variables. And then you can call the code again. And if everything goes well, and I know it's going to go because I recorded this once, there I go my secret again. And keep in mind that if you're doing your code, you're probably going to store your secret on a variable, not just type it out like that, especially maybe in a file that reads that you read it. And then you can use the header data again for making your code a little bit smarter. Always try to do that, an advice, just in case. And then you go again getting the information from the user. I feel so sorry for you. But let's say that what if something goes wrong? I always show you the happy path, everything worked. But if something goes wrong, what do I do? I don't want an error is just blowing up in my face whenever something goes wrong. So in this case, this token was expired. So once I tried to decode it or validate it, it would show me an expired signature. And PIDWT, like all the other packages that I've worked with, they have their so you can import and try and accept that error in the most friendly way possible. Usually, you would do that so that you could log that error for some for logging purposes and discovering why I'm wrong with your program or your system. So there I have my accept and I'm just spinning because I want to show you what is happening. And if I can type things right, it would be nice. Unable to decode the token and whatever I got from it. And if everything goes right, and it will, let's see. Ta-da. Signature has expired. So that's how you know you probably have to get a new token because that token was expired. Now, this is a different token, as you probably can notice because of the size. And because if you are dealing with tokens that were signed with asymmetrical algorithms, you're probably going to have a little bit more work to do. That is importing a way for reading keys. In this case, I used an SSHRSA key and I'm reading the public key so that I can validate my token. Notice that I'm using the public key to validate the token and not the private one. So for reading the key, you have to do a little bit of extra steps. This key is in a file in my computer, not in an endpoint, but it could be in an endpoint if you want it. And JWT in this case has a lot of functions for reading public keys, which is nice. You can read any type of public keys you want. And you have to encode it. And then you can pass that into the decode function once more, instead of a secret, now a key for getting the information of the user. And there I go again. Token, key, typos. Yes. Thank you. Auto-complete is wonderful. Algorithms. And this time I didn't use that trick for getting the algorithm from the token header, but I could if I wanted to. Notice the different algorithm now is RS256 and everything worked and I got the information from the user. Now, where do you find JWTs in the wild? And that's the most important question probably. So access tokens are the most common ones, especially if you're talking about Python, because we deal with APIs all the time. So access tokens are the idea way for you to get access to a protected API, but access tokens doesn't have necessarily to be JWTs. It could be some other type of token. But if you're following the latest standards that is anywhere seen on the block, not part of the Jose, but I thought it was important to mention to you that was authored by Vittorio Bertacci, a principal architect about zero after much work. You now can have an RFC to use as a basis for using JWTs as access tokens. So that's a very good read. I would truly recommend it. Then you have ID tokens. And ID tokens are cool because they are always JWTs. And the important thing is it can take a little bit out of the work of doing two requests to your back end for getting the information of the user. So once your user login, your back end would reply with an ID token with information from the user, like profile picture, user preferred name, and things like that. They'll make your life easier for showing, or at least the front ender life easier for showing the information of the user. Now, speaking of tokens, you may have word of refresh tokens. But refresh tokens aren't the JWTs. That's why I'm not talking about that here. And that would be an entirely new talk, so maybe next year, who knows. And finally, a few tips and advices, how to be safer with JWTs. Don't store JWTs in local storage. And don't do that because that opens you up for a type of a vulnerability in an attack called XSS, that's cross-site scripting, my God, these two words. But the idea is for you to be safer, don't store that in local storage. If you need to validate your JWT, put that step on the back end if you can. All right? And start on in memory for validation purpose. Once the memory is flushed, no problem there. And try not to verify access tokens on the front end. If you need to verify an access token, do that in the back end. That should be your responsibility of your back end, not your front end. Don't put sensitive data in this ability. And this is a tricky one. Because, well, if I'm putting the information from the user on the ID token for displaying that on my front end, how can I not put sensitive data? So what I'm talking about here is actually, for example, credit card information. Do not put, like, the numbers of the credit card in there because anybody that can decode a base 64 will be able to retrieve that data. And you don't want that data lying around everywhere. Tools. Because we love tools. Let's say you are working with JWTs and you need to debug a JWT. JWT.io is a tool that we developed at OutZero. And you can debug your token on our web browser. So you can access on your phone, paste it there, and you can see the claims inside of JWT. You can verify it if you want to. So it's very useful for figuring out, for example, if you're implementing tasks, why are my tasks not working? That's really helpful too. And the second one, if you want to more in-depth content about JWT, I truly recommend the JWT Handbook. It has a lot of examples, user cases, and things like that. And how to be safer with JWTs. So if you want a longer read, go ahead and download it. Finally, that was all for today. If you have questions, find me in the hallway. Thank you. Oh, we still have time. Okay, so folks, we have some time. So some Q&A for Jess, I think maybe we can have three questions. Do we have anything remote, remote questions? I don't think so. He's not raising his hand. No? Okay. Hi. I was going to ask from my experience, what would be your preferred tactic for invi-dating the JWTs? Because this is actually a real problem. You don't want to let users always use them until they just expire. So what's your preferred tactic for invi-dating them? Well, see, if they are expired, they shouldn't be able to use it, because they should be validifying the JWT in one of the verification steps. I mean, before they expire. Oh, yes. That's a tricky question, because once the JWT is out in the wild, you cannot call it back. So probably what you would have to do is make a step on your end for some type of JWTs, but that's hard. We can have the discussion longer offline. Hello. Hi. Anna Wilson. Hi, Janet. Great talk. Thank you very much. I know what you said about not storing the tokens in local storage. Yeah. When I was starting learning about JWTs, I saw that advice, and also not to store them in cookies, because that's vulnerable to a different problem. Why do you keep them? Well, it depends. Why do you want to keep them? So that the user can be authenticated on their next request? Well, if they are going to be authenticated in the next request, probably the way to do it would be using cookies, but there are different types of cookies that you can have, and probably there is a safer cookie that you can use. I haven't reached out. Find me later that I can send you. Cool. Thank you so much. Thank you. So is this actually a good idea to take the header from an unverified JWT and use it as the header? Because doesn't this actually introduce a potential vulnerability if you are using different key schemes? I mean, both symmetrical and asymmetrical in your application? Well, the thing is, getting the unverified header is a way for you to know what algorithm was used, and by the algorithm you can know which type of key you have to use. Yeah, but the thing is that if you would actually do, if your application would implement both symmetrical authentication and asymmetrical in two different places, then you can use the public key, you can recreate your own JWT and send it to a different API that, you know, should supposedly use the symmetrical one only, but if it would reuse the same code and, you know, getting the header from the JWT token, then you would be vulnerable to, you know, someone could basically forge the JWT token. So you control the way for creating the token and you're using the public key, is that it? Yeah, attacker can actually create, yeah. I mean, I could create my own JWT. No, yeah. Public key, yeah. Yes. But, well, if you are creating your JWT with public keys, we should not be doing that. So my point is that if you are showing this on a slide, the problem is that someone could use it incorrectly, right? So that, my point is just, it's good to point out that there is this potential issue here. Yes. You should probably match the algorithm to the expected one. Yes, you should do that. In this case, I didn't show the example, but we'll make the code longer. There are very, well, three steps that you have to do. It's good to add it at the end of the, of the, when you show the issues, right? Okay, thank you. I'll note that on the next one. Thanks. We might have one more time for one more questions, or I think we can just close and if you have anything else to discuss and she will be in the hallway. Yes. If you have another round of applause for Jess.