A Working Solution to JWT Creation and Invalidation in Golang
Tags: go, jwt, authentication
Published: 2020-01-25 22:31:41

---
title: A Working Solution to JWT Creation and Invalidation in Golang
published: true
description: Discovering how to invalidate a JWT after logout
tags: #go #jwt #authentication
cover_image: https://thepracticaldev.s3.amazonaws.com/i/nf6ozqenf1xlvl8bzpfo.jpg
---

###**Before you proceed**
This is **part 1** of the two-part series.
This part solely focused on creating a JWT that has no expiration date. While this seems cool, it can have security issues. For example, in the event that the JWT is hijacked. If this happens the only remedy in this article is, when the authenticated user logs out, the token will be revoked and can't be used any further(by either the hijacker or the user). So the user can obtain a new one when he login again.

In **part 2** of this series, Two tokens will be used:
- Short Term Token: also known as access token(usually 15 mins)
- Long Term Token: also known as refresh token(usually 1 week)
This approach is more secure compared to the above. 
Once the article is ready, the link will be provided here.


###**Introduction**
Whenever JWT is mentioned to be used for authentication, there is this question that is always asked by developers that have experience using it: 
**when a user logout, what happens to the JWT?** 
That question is a nightmare.

What this article solved: Once that user logs out, the JWT used is invalidated that very second! Without waiting for any **expiration time** if any was set when the token was created.
 

Using my Github account as a case study. I don't get logged out except I explicitly trigger the logout button. 
When using JWT, many have advocated that the token should have a short time span(15min, 20min, etc), the token should be revoked often time than not, blah, blah, blah. 
Think about it, if a token lifespan is short, say 10mins, it means, after that period, you will be logged out and need to log in again😡. Except for applications that require that(payment applications, etc), I see no reason why I should go through this pain. 

Solutions to the JWT discussion before now from this [reading](https://dev.to/_arpy/how-to-log-out-when-using-jwt-4ajm), include:

1. Set a reasonable expiration time on tokens
2. Delete the stored token from client-side upon log out
3. Have DB of no longer active tokens that still have some time to live
4. Query provided token against The **Blacklist** on every authorized request.

**Issues from the above-mentioned solutions:**
1. What if you set the expiration of 1 hour for a JWT, then the user login, then logout after like 1 minute or so? What it means is, that JWT will be valid for an additional 59 minutes; ample time for a hacker to **do his thing💀**, in the event that the user JWT was hijacked. 

2. About **Blacklist** stuff. This is what that means: Once a user logs out, add the token he used to a **blacklist table** in your database(Redis preferably). So once the user wants to perform a request that requires authentication and provides that token, then blacklist table will be queried to check if a token has been created before by that user and have not **expired**, if found, don't allow the user to get away with his mischievous act, hold him right there✊. 
While this approach seems cool, it has obvious downsides:
When creating the token(during signup or login), I must specify a time when the token expires in my code. When that time elapses, the user will be forced to login again. I definitely don't want this.
You might argue that you can create a token that does not expire right? Well, what it means is that your **blacklist table** will soon have "zillions" of rows of JWT tokens not used by anyone, and you cannot afford to delete any because a user might wait patiently and reuse a token he has been saving for like a year now, just to test the integrity of your application🧐.


**This is what this article is all about:**
1. We want a type of application in which the user does not try to access his account after a few minutes or hours and discover that he is logged out because we are trying to protect them from hackers💀. 
Don't get me wrong, it all depends on the time of application. For instance, my banking application logs me out after say 5min of inactivity, which is a good use case.
2. We want an application in which, when the user chooses to logout, he does so, and can't try to use that same JWT he used before logging out for any authenticated request. He should not be allowed.
3. We don't an application that has "zillions" of rows of blacklisted JWTs. Total no! I mean, why waste resources?

So this is what we want:
**An application that can keep the user logged in forever except the user chooses to explicitly logout. I don't know about you, but this is how I 
use my Twitter, Github, and so on.**
To achieve this in your application, this piece is for you. Especially when you want to use JWT.

**This is the trick I used:**
I created a database table called **auths**, the table has three columns: **id**, **user_id** and **auth_uuid**. Pay attention to the **auth_uuid**. It is created from **uuid**. UUID stands for a **universally unique identifier**. When a user login, a JWT is created. The **user_id** and **auth_uuid** are used as **claims for that JWT. The **user_id** is the id of the user who attempts to login, while the **auth_uuid** is created using a helper package called: [twinj](https://github.com/twinj/uuid). When a user logs out, the created row(of the user_id and the auth_uuid is deleted from the auths table). What it now means is, though the JWT has not expired, it cannot be used to make any further requests on behalf of that user. 
Reason: because part of its **claims** are deleted. For that user to make any authenticated request again, he needs to login, which will create a new JWT for him then also a new row is added to the **auths** table, with the **user_id** and a brand new **auth_uuid**. Take note that a new **uuid** is created for each JWT according to the code implementation you will below.
If what was explained above is not clear, please look at the example below where it was demonstrated. 


##**Building**
Consider a simple **Todo Restful API with Authentication**.


###**Basic StepUp**
a. From any location, you prefer in your computer, create a directory called **manage-jwt**
``` mkdir manage-jwt```
b. Change to that directory 
```cd manage-jwt```
 Then initialize **go modules**:
```go mod init manage-jwt```

c. Environmental variables. 
We will store all our environmental variables in **.env** file.
From the root directory, create the .env file:
```touch .env```
{%gist https://gist.github.com/victorsteven/6b04204ddbdb73f60958526a89c8aa1d %}



###**Creating JWT**
From your project root directory(path: manage-jwt/), create the **auth** package(directory), then the **auth.go** file
```mkdir auth```
```cd auth && touch auth.go```
{%gist https://gist.github.com/victorsteven/3ca3241097350cfa857278dd7c1f056d %}

From the file above, we created the JWT with the **UserId** and a **AuthUuid**, as seen in the **AuthDetails** struct. We also have functions that verify the token and extract the **UserId** and the **AuthUuid**.


###**Wiring the Models**
From the root directory, create the **model** directory. This is where we will have our database initialization and all database related stuff.
```mkdir model```

**a. Let's create the base_model.go file.**  
```cd model && touch base_model.go```
{%gist https://gist.github.com/victorsteven/13a6c92b4c9c2cf3e16e2e8617cd3781 %}
From the above file, we have the **Initialize** method and an interface that is a collection of our model methods we will define soon.

**b. Create the user model**
``` touch user.go ```

{%gist https://gist.github.com/victorsteven/7b44db366eccfe20e24a58769eb0f6f6 %}

We have methods that validate the email, create a user and get a user by email.
Since the sole aim of this article is about **jwt**, we left implementation as basic as possible.

**c. Create the todo model**
```touch todo.go```
{%gist https://gist.github.com/victorsteven/00ace9788aa76dd1af9d0665df0173ac %}
As seen in the above file, we just have the **CreateTodo** model, since we are focused on JWT.

**d. Create the auth_uuid model**
```touch auth_uuid.go```
{%gist https://gist.github.com/victorsteven/4682e7013e4058501aa09a4c7f74386c %}

We functionalities to **create**, **get** and **delete** the **uuid** and the **user id** associated with the **jwt**. For instance, the **CreateAuth** method is used in the **Login** controller function(this will be defined later), the **auth** created have the **AuthUuid** and the **UserId**. These are then used as **claims** when creating the JWT.
Whenever a request is made that requires authentication, the **FetchAuth** method is called, which lookup the **auths** table and check for the **auth_uuid** and the **user_id**. If they exist, the next line of action is taken(such as Creating a Todo, Logging out the user, etc).
The **DeleteAuth** method is used to delete the **auth_uuid** and **user id** from the **auths** table. This happens during logout, thus, rendering that JWT **useless😪** because it cannot be used for any other request. Ever!.
 
Take note that the JWT is not deleted. It still exists, but it is invalid because the **claims** used to form it are no more. What actually made this possible is the **uuid**. Since the uuid is unique at its creation, there is little or no chance of having the same **uuid** in **auths** table. Even if that eventually happens, the **user id** is ever unique. We can't two or more same **user id** in the **auths** table. 
This is how the uuid table looks like:
        
| id  | user_id  | auth_uuid                             | 
|-----|----------|---------------------------------------|
| 1   |    1     | 83b09612-9dfc-4c1d-8f7d-a589acec7081  | 
|-----|----------|---------------------------------------|
| 2   |    2     | 14033612-df45-sdf3-137d-dfsdfd32243d  | 

So, when the **DeleteAuth** method is called, the row that matches the parameters provided is deleted. Then no further request can be carried out with that JWT again because the **auths** table will always be checked👨‍✈️.


###**Wire up the Signin Service**
Before any authenticated request is made, the user needs to the signed in. This is where the **CreateToken** function from the **auth** package is called.

From the root directory, create the **service** directory:
```mkdir service```
Then, create the **signin_service.go** file:
```cd service && touch signin_service.go```
{%gist https://gist.github.com/victorsteven/ba56d80efe40de15261ecbf1951f44f4 %}

This would simply have been done without an interface. The purpose of defining the method in an interface is to enable us to mock it when writing test cases.
Observe that we passed as parameter the **AuthDetails** struct which defines the **auth_uuid** and the **user id**; which are used as **claims** when creating JWT.


###**Wire up the Controllers**
From the project root(path: /manage-jwt), create the **controller** directory(package).

**a. The User Controller**
Create the **user_controller.go** file
```cd controller && touch user_controller.go```
{%gist https://gist.github.com/victorsteven/3b245dabcfba588ba955dcc19a451dd0 %}

Keeping things super simple, so as not to distract the main purpose of the article. 

**b. The Login Controller**
A user can login after he has signed up(been created).
Create the **login_controller.go** file

``` touch login_controller.go ```

 {%gist https://gist.github.com/victorsteven/d3d08927af2189a5fa5be6db3554a8a2 %}

As seen in the file above, we have both the **Login** and the **LogOut** functions. 
Observe in the **Login** function that we created a new **row** in the **auths** table when we called **CreateAuth** method, we then passed its return value to the **SignIn** method, which calls the **CreateToken** function.
So now, we have a JWT and a **row** in the **auths** table that has the **auths** and the **user id** used as claims when creating the token.

From the **LogOut** function, called the **DeleteAuth** method that deleted that **row** created in the **auths** table, thus rendering the JWT useless. 

Note: Remember that before you logout, you must be authenticated, so you must add to the header of your request a valid JWT.


**c. The Todo Controller**
Create the **todo_controller.go** file. 
``` touch todo_controller.go ```
{%gist https://gist.github.com/victorsteven/169001bc55cfc9d3b097d6ed6ad6a74b %}

Creating a todo requires a user to be authenticated. From the **CreateTodo** function, we extracted the JWT claims(particularly AuthUuid and the UserId). We then checked the validity of those by calling **FetchAuth** method. If everything goes well, we then proceed to create the todo. 


### **Routing and Starting the Application**
Let's connect everything together and fire up the application.
From the root directory, create the **app** directory:
```mkdir app ```

**a. Routing**
Then create the **router.go** file:
```cd app && touch router.go```

Observe that we called a middleware we have not created yet and we used a **router**. We will create these shortly.


**b. The StartApp function**
Still, in the **app** directory, create the **app.go** file:
``` touch app.go```
{%gist https://gist.github.com/victorsteven/786365cb33ca343cef61ec2747c3a2ae %}

The above file defined the **router** variable referenced in the **router.go** file. It also called the **Initialize** method(defined in the model), for the database connection. We called the **route()** function and also started the application.

**c. The Middleware**
From the root directory(path: manage-jwt/), create the **middlewares** directory, then the **middlewares.go** file
```mkdir middlewares```
```cd middlewares && middlewares.go```
{%gist https://gist.github.com/victorsteven/220834e53352e64be278095ff935e9b0 %}

The **TokenAuthMiddleware** function help to protect routes that require authentication.


**d. The main.go file**
It is time to finally test our hard work💪. From the root directory, create the **main.go** file and call the **StartApp** function defined above:
```touch main.go```

{%gist https://gist.github.com/victorsteven/e844e2e3c2c1c3db0cd2eeec97244b76 %}

Then run:
```
go run main.go
```
Your app should be on fire🔥 if you followed the instructions above.




###**Testing with Postman**
Let's try our hands on some endpoints

a. **/user endpoint:** for creating a user(signup). Provide an email address to be signed up.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/e6f6tlh9urgzvccku9w4.png)

b. **/login endpoint**
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/cy9y3zup6rsdgj2ij129.png)


c. **/todo endpoint:** Let's create a todo with the token generated above.
This token will be added in the **Authorization: Bearer Token**

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/wjinux6mvdmgs0cedmsu.png)

d. **/logout endpoint** 
To logout, you must be authenticated, so add the above token in the **Authorization: Bearer Token**

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/znpj1duqfsjp5vm1lag8.png)


###**Bonus**
a. The API is deployed is to **heroku**. You can test using: 
https://manage-jwt.herokuapp.com.

b. **Test Cases** are added for the above functionalities, get the Github repository [here](https://github.com/victorsteven/manage-jwt) and run tests from the root directory using:
```
go test ./...
```

c. Circle CI is used for Continuous Integration.

d. The application is already dockerized. You can run it on docker if you wish. Setup is found in the [repo](https://github.com/victorsteven/manage-jwt).


###**Conclusion**
So, there you have it. The JWT monster has been trampled on our feet, as we can invalidate it at any time if we wish.

Get the repository [here](https://github.com/victorsteven/manage-jwt), which you can star to track any new update.

Test the API in production using the url: https://manage-jwt.herokuapp.com.

Happy Forcing JWT to be useless at will🤣.

Follow me on [Twitter](https://twitter.com/stevensunflash) to get notified of current releases.

Also, follow here on dev.to

Thank you.