JWT in Golang Tutorial

Kacper Bąk
4 min readDec 7, 2022

--

Photo by Shubham Dhage on Unsplash

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. It is typically used to authenticate users and pass information such as user roles and privileges.

JWT is used to securely transmit information between parties, such as authentication and authorization data. It is also used to verify the integrity of the data being transmitted. JWT is a compact and self-contained way to securely transmit data, making it an ideal choice for applications that require secure communication.

To learn how to use JWT, you can start by reading the official RFC 7519 specification. You can also find tutorials and resources online that provide step-by-step instructions on how to use JWT. Additionally, there are libraries available for various programming languages that make it easier to use JWT.

To create a method in Golang that will send an authorised request, you will need to use the JWT library for Golang. You can use the library to generate a JWT token, which you can then use to authenticate the request. You can also use the library to decode the JWT token and extract the payload.

The most popular library for handling JWT in Golang is the jwt-go library. It provides an easy-to-use API for generating, signing, and verifying JWT tokens. It also provides support for various algorithms, such as HMAC, RSA, and ECDSA.

The easiest way to see how the JWT Token works is to use this code snippet

package main

import (
"fmt"
"github.com/dgrijalva/jwt-go"
)

func main() {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"foo": "bar",
})
tokenString, err := token.SignedString([]byte("secret"))
if err != nil {
fmt.Println(err)
}
fmt.Println(tokenString)
}

Output:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIifQ.dtxWM6MIcgoeMgH87tGvsNDY6cHWL6MGW4LeYvnm1JA

Which header is:

{
"alg": "HS256",
"typ": "JWT"
}

And payload data is:

{
"foo": "bar"
}

The most popular site for decoding tokens is jwt.io.

Having already had some basic token, we can move on to validating it. To do this, I have written a simple handler that will allow us to check that the token we provide is valid.

To do this I will separate the logic into two directories, endpoints and jwt, in one I will keep the logic responsible for endpoints and in the other the logic responsible for JWT.

I will import these two directories from the main.go file

├── endpoints
│ └── validate.go
├── go.mod
├── go.sum
├── jwt
│ └── jwt.go
└── main.go

main is the entry point of the application, I’m creating a new router, adding basic endpoint, and starting the server which will be listening for requests

func main() {
r := mux.NewRouter()
r.HandleFunc("/validate", endpoints.Validate).Methods("POST")
log.Fatal(http.ListenAndServe(":8080", r))
}

The function Validate in endpoints validates the JWT token. I’ll get the token from the request, then I’ll Validate the token and return the proper header for each scenario.

func Validate(writer http.ResponseWriter, request *http.Request) {
token := request.FormValue("token")
j := jwt.NewJWT(token)
valid, err := j.Validate()
if err != nil {
log.Println(err)
writer.WriteHeader(http.StatusInternalServerError)
return
}
if !valid {
writer.WriteHeader(http.StatusUnauthorized)
return
} else {
writer.WriteHeader(http.StatusOK)
}
}

JWT contains struct that contains the JWT token, NewJWT method which creates a new JWT struct, and Validate method which validates the JWT token. If there will be an error, the token must be invalid.

type JWT struct {
Token string
}

func NewJWT(token string) *JWT {
return &JWT{
Token: token,
}
}

func (j *JWT) Validate() (bool, error) {
_, err := jwt.Parse(j.Token, func(token *jwt.Token) (interface{}, error) {
return []byte("secret"), nil
})
if err != nil {
return false, err
}
return true, nil
}

With such an application, it is possible to check that the tokens given to JWT are correct.

Examples of errors resulting from the wrong JWT (you should get one in the console if you enter the token incorrectly).

signature is invalid

token contains an invalid number of segments

unexpected end of JSON input

If you want to check with the help of a terminal, here is the curl command:

curl --location --request POST 'localhost:8080/validate?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o' -v

You can easily download the entire project from here and test it from here: https://github.com/53jk1/go-base

In conclusion JWT is a forward-looking technology that is being used in many industries to provide secure authentication and authorization. It is also being used to provide secure communication between different systems and applications. As the technology continues to evolve, it is likely that JWT will become even more widely used in the future.

If you are looking for a secure and reliable authentication and authorization solution, then JWT is a great option. It is easy to set up and use, and it is free to download from the repository. So why not give it a try and see how it can help you secure your applications and systems?

--

--