We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Today, let's have a look at how you can use JWT Authentication in Go. We are going to use it in combination with Labstack Echo (my preferred tool for creating web servers with Go).
Let's define a simple webserver supporting JWT Authentication like this:
package main
import (
"net/http"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/pieterclaerhout/go-log"
)
const secret = "secret"
type jwtCustomClaims struct {
Name string `json:"name"`
UUID string `json:"uuid"`
Admin bool `json:"admin"`
jwt.StandardClaims
}
func login(c echo.Context) error {
username := c.FormValue("username")
password := c.FormValue("password")
if username != "pieter" || password != "claerhout" {
return echo.ErrUnauthorized
}
claims := &jwtCustomClaims{
Name: "Pieter Claerhout",
UUID: "9E98C454-C7AC-4330-B2EF-983765E00547",
Admin: true,
StandardClaims: jwt.StandardClaims{
ExpiresAt: time.Now().Add(time.Hour * 72).Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
t, err := token.SignedString([]byte(secret))
if err != nil {
return err
}
return c.JSON(http.StatusOK, map[string]string{
"token": t,
})
}
func accessible(c echo.Context) error {
return c.String(http.StatusOK, "Accessible")
}
func restricted(c echo.Context) error {
user := c.Get("user").(*jwt.Token)
claims := user.Claims.(*jwtCustomClaims)
log.InfoDump(claims, "claims")
name := claims.Name
return c.String(http.StatusOK, "Welcome "+name+"!")
}
func main() {
e := echo.New()
e.HideBanner = true
e.HidePort = true
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.POST("/login", login)
e.GET("/", accessible)
r := e.Group("/restricted")
config := middleware.JWTConfig{
Claims: &jwtCustomClaims{},
SigningKey: []byte("secret"),
}
r.Use(middleware.JWTWithConfig(config))
r.GET("", restricted)
e.Logger.Fatal(e.Start(":8080"))
}
Looking at the code, there are several endpoints defined:
/login
: can be used to get a JWT token based on your login credentials/
: an endpoint which doesn't require authentication/restricted
: an endpoint which does require a valid JWT authentication token
The server will register itself on port 8080
and we're ready to go.
You can start the server like:
$ go run server.go
You can then use the /login
endpoint to get a token:
$ curl -s -X POST -d 'username=pieter' -d 'password=claerhout' http://localhost:8080/login
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiUGlldGVyIENsYWVyaG91dCIsInV1aWQiOiI5RTk4QzQ1NC1DN0FDLTQzMzAtQjJFRi05ODM3NjVFMDA1NDciLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxNjEwMzgzNTU0fQ.JqJ4x2yPXOmxJB1n4GqpfKnIMyorX2zF7kbWbfchX4c"}
You can then use this token to access the restricted URL:
$ curl http://localhost:8080/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiUGlldGVyIENsYWVyaG91dCIsInV1aWQiOiI5RTk4QzQ1NC1DN0FDLTQzMzAtQjJFRi05ODM3NjVFMDA1NDciLCJhZG1pbiI6dHJ1ZSwiZXhwIjoxNjEwMzgzNTU0fQ.JqJ4x2yPXOmxJB1n4GqpfKnIMyorX2zF7kbWbfchX4c"
Welcome Pieter Claerhout!
In addition, the server log will show you the contents of the authentication token:
claims &main.jwtCustomClaims{
Name: "Pieter Claerhout",
UUID: "9E98C454-C7AC-4330-B2EF-983765E00547",
Admin: true,
StandardClaims: jwt.StandardClaims{
Audience: "",
ExpiresAt: 1610383647,
Id: "",
IssuedAt: 0,
Issuer: "",
NotBefore: 0,
Subject: "",
},
}
The complete working implementation can be found on GitHub.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.