Check out a free preview of the full Build Go Apps That Scale on AWS course
The "Creating a JWT" Lesson is part of the full, Build Go Apps That Scale on AWS course featured in this preview video. Here's what you'd learn in this lesson:
Melkey introduces JSON Web Tokens (JWTs), which are a URL-safe way of representing secure token-based authentication information between two parties. A CreateToken function generates the JWT and returns it as a string. The chapter_2 branch can be used as a starting reference for this lesson.
Transcript from the "Creating a JWT" Lesson
[00:00:00]
>> What we're gonna do in this last part is set up JSON Web Tokens. I'm not an expert on JSON Web Tokens. I don't claim to be, nor do I want to be, but what is a JSON Web Token? A JWT is essentially that. It is a URL that is containing information specific to the person accepting or the system accepting this request.
[00:00:30]
So we have a blue portion, green portion, and a red portion. The blue portion is the algorithm. What do we use to create an hash RJWT because they're hashed, right? We don't want information to be leaking left-right and center. So what is the algorithm? Which is in the JSON of ALG and HS256 is one of the more popular ones to hash your text representation or essentially hash your payload and signature.
[00:00:59]
Payload is information that you wanna give it. It could be anything. It could be the user ID, it could be his admin. It could be X, Y, Z. It's a payload that you create that you can use to transfer information between the requester and your backend system, and then the most important part is the signature.
[00:01:16]
This signature is incredibly important. Forget to take away anything from JWT's signature part. The reason for that is if you get a request from a different JWT, someone like a bad agent or a bad actor inserts their own JWT, you wanna make sure that you're only accepting requests from jots that you create, that you sign.
[00:01:35]
So typically, the signature is based off of a string, which is again, is like a hash that you create and store very, very secretly. They do not touch or store in code or whatever. And basically, what any parsing library will do is it will check the signature and identify did this essentially come from me or another third party?
[00:01:57]
If it's third party, you wanna remove it. You don't want that in your code at all. And why this matters, I mean, I think everyone here has an understanding of how these works. But basically, client asks our backend, our backend gives the token. This token is our JWT, our jot, and then whenever our client wants super secret routes, we take that token, we check it out, validate it, and then we either give it a protected resource or not.
[00:02:25]
Right, I mean, not too groundbreaking. I kept it fairly simple. You can go crazy with this. And there's actually a very good article here from Medium, again, this is gonna be in the resources, so this is all gonna be attach. And this is essentially what I'm going to follow to create our JWT, but essentially how to use this package how you create your token and how you can parse them, okay?
[00:02:51]
I take it one step further because I cradled middleware around our routes, so it starts to look a little bit gnarly, especially the method signatures. And passing an index function and the method chain, but TLDR, this is kind of how it's done, or just a good resource of how it's done, okay?
[00:03:12]
Cool, so let's go cd back into our lambda. And the very first thing we're gonna need is another last package is go get github.com/golang-jwt/jwt/v5. We get that package installed, we're gonna go ahead and import it. So github.com/golang-jwt/jwt/v5. I'm gonna create a function called func CreateToken. And this is gonna accept a user of type user, and all it's gonna do is return a string, okay?
[00:03:52]
And this string is gonna represent our JWT, the job that we're gonna basically assemble right now. So now what we wanna do, is now is time.now. So what is the current time we're executing this function, which is essentially gonna be when a user logs in? We get the current timestamp, and then we create expires, push back, validUntil, and this is where we assign how long is this token good for?
[00:04:18]
You typically talk to the good, you have short term tokens, long-term tokens. This is a whole different topic that we can definitely get into. But for now, I'm gonna say that this token is good for one hour. Is that the best practice? Depends on what are you using it for.
[00:04:31]
But it is what it is. I'm gonna do one, whoops. So one hour, and I'm gonna convert that to Unix, okay? And now we're gonna assemble the payload of our JWT and this is also considered as claims, right? I'm gonna bring in our JWT. I'm gonna do new, sorry jwt.MapClaims, okay?
[00:04:59]
It's gonna be a struct, and this is where we put in the fields that we want to put in. So this is information that we require, like the payload that we're interested in. So here we're gonna put user, and it's gonna be user.username, just to have something in there and then expires, which this is important because we're gonna parse that in our validation logic and our validation middleware.
[00:05:21]
I'm gonna expires, is going to be valid until, okay? One hour from the time it's issued, that's how it's gonna be good if it's a second over, it's expired, okay? So now let's assemble this token, so JWT. I'm gonna do a new token, new with claims, that's gonna take the method.
[00:05:40]
So the signing method, what's the algorithm we're using to sign this JWT? And the most important, not important, the most famous one, the most popular one is HX256. Don't know what that algorithm means. People, PhDs, theorists know, I'm just using this, right? I just know it's secure, it's good, it's popular, and we can put in our claims and nil.
[00:06:04]
Nil for no additional features, no additional information to be appended to our claims here, okay? Next is this part, this is a wonky part. This is basically where you want to store your secret and not what I'm doing. Do not do what I do right now. This is a secret that should be stored in AWS secrets or something else, in a .env file.
[00:06:27]
I'm just using this just so we can get the ball rolling here, but secret is the signing method. That important thing I was pointing at, this is the signing method, so keep it secret, and then so we're gonna do tokenString. And I believe this returns an error, yes it does.
[00:06:45]
We're gonna do that token, and we're gonna SignedString. And this SignedString is gonna take a slice of bytes, and we're gonna put in the secret. So now we basically signed our token with this last piece of information. I'm gonna say if error does not equal to nil, what I'm gonna do is, which could be to return an empty string, okay?
[00:07:08]
And we can log in internally like, hey, there's an error or hey, something's going on. But for our case, we just return an empty string, otherwise we're gonna return tokenString, okay? And this tokenString is that assortment that LongHashed will create. And right now, this is gonna include our claims, when it expires, and the signing method.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops