Getting Started #
In this article I am going to show you how to create and parse JWT tokens extracting information from them in the beautiful language of Go using the go-jwt package.
This article presumes the following:
- You know how to program in Go.
- You know what JWTs are and how they work (this is not an article on JWT itself š¬).
Setup #
I highly recommend following this article and trying out the code yourself. The complete example code can be found in this github repository.
Start by creating a new project using go mod init <your repository path>
.
go mod init github.com/gurleensethi/go-jwt-tutorial
Adding the go-jwt package #
I will be using the go-jwt package to create and parse JWT tokens.
go get -u github.com/golang-jwt/jwt/v4
At the time of writing this article the latest version for this package is v4
, check for the latest releases on the go-jwt's github repostiroy.
Creating JWT Token #
When creating JWT token's we need a secret key, so start by defining a new key.
package main const key = "my secure jwt key" // š func main() { }
main.go
To create new tokens we use the jwt.NewWithClaims
function.
package main import ( "fmt" "log" "github.com/golang-jwt/jwt/v4" ) const key = "my secure jwt key" func main() { token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{}) // š jwtToken, err := token.SignedString([]byte(key)) // š if err != nil { log.Fatal(err) } fmt.Printf("JWT Token: %s\n", jwtToken) }
main.go
Let me break this down for you:
- NewWithClaims takes two parameters, a signing method and claims. Claims is the actual data that the JWT token will contain.
- jwt.NewWithClaims doesn't create the new token, you need to call the
SignedString
function passing it the secret key to get the actual JWT token. - jwt.RegisteredClaims are the common/standard JWT claims that are usually present in a JWT token payload such as
iat
(token issue time),exp
(token expiry time) and many more. I highly recommend checking our the source code for RegisteredClaims here.
Creating token with data #
The code until now creates JWT token but it doesn't contain any user provided data. It is simple, instead of providing the jwt.RegisteredClaims
as the payload, you will embed jwt.RegisteredClaims
in another struct with additional information, lets call it UserClaim
.
type UserClaim struct {
jwt.RegisteredClaims
ID int
Email string
Name string
}
Use this UserClaim
as the second argument to the jwt.NewWithClaims
function.
token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{
RegisteredClaims: jwt.RegisteredClaims{},
ID: "1",
Email: "[email protected]",
Name: "First Last",
})
I am going to refactor the JWT token creation process into a separate function called CreateJWTToken
, below is the complete code.
package main import ( "fmt" "log" "github.com/golang-jwt/jwt/v4" ) const key = "my secure jwt key" // Data that will be in the token type UserClaim struct { jwt.RegisteredClaims ID int Email string Name string } func main() { jwtToken, err := CreateJWTToken(1, "[email protected]", "First Last") if err != nil { log.Fatal(err) } fmt.Printf("JWT Token: %s\n", jwtToken) } // š func CreateJWTToken(id int, email string, name string) (string, error) { token := jwt.NewWithClaims(jwt.SigningMethodHS256, UserClaim{ RegisteredClaims: jwt.RegisteredClaims{}, ID: id, Email: email, Name: name, }) // Create the actual JWT token signedString, err := token.SignedString([]byte(key)) if err != nil { return "", fmt.Errorf("error creating signed string: %v", err) } return signedString, nil }
main.go