From eacc0b5dc9b91436bb3a2eb8d9b26fba33f0ed56 Mon Sep 17 00:00:00 2001 From: perp Date: Mon, 3 Jun 2024 13:51:42 +0100 Subject: [PATCH] Add JWT encoding & decoding --- cmd/main.go | 4 ++++ internal/jwt/decode.go | 29 +++++++++++++++++++++++++++++ internal/jwt/encode.go | 36 ++++++++++++++++++++++++++++++++++++ internal/jwt/jwt.go | 17 +++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 internal/jwt/decode.go create mode 100644 internal/jwt/encode.go create mode 100644 internal/jwt/jwt.go diff --git a/cmd/main.go b/cmd/main.go index d28c7ab..f0a4594 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,6 +22,7 @@ import ( "git.supernets.org/perp/gopay/internal/config" "git.supernets.org/perp/gopay/internal/context" "git.supernets.org/perp/gopay/internal/database" + "git.supernets.org/perp/gopay/internal/jwt" "git.supernets.org/perp/gopay/internal/router" "github.com/rs/zerolog/log" ) @@ -37,6 +38,9 @@ func main() { cfg := config.Parse(content) config.SetupLogger(cfg.Log) + // Create JWT + jwt.New(cfg.Auth.Secret) + // Create database db := database.New(cfg.Database) diff --git a/internal/jwt/decode.go b/internal/jwt/decode.go new file mode 100644 index 0000000..635747a --- /dev/null +++ b/internal/jwt/decode.go @@ -0,0 +1,29 @@ +package jwt + +import ( + "github.com/golang-jwt/jwt" + "github.com/rs/zerolog/log" +) + +// Decode a token +func Decode(token string) (*Claims, error) { + // Create token claims + tokenClaims, err := jwt.ParseWithClaims( + token, + &Claims{}, + func(token *jwt.Token) (interface{}, error) { + return secret, nil + }, + ) + + // Found token + if tokenClaims != nil { + // Map to claims struct & if ok & valid then return + if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { + return claims, nil + } + } + + log.Err(err).Msg("Could not decode JWT claims") + return nil, err +} diff --git a/internal/jwt/encode.go b/internal/jwt/encode.go new file mode 100644 index 0000000..4013cde --- /dev/null +++ b/internal/jwt/encode.go @@ -0,0 +1,36 @@ +package jwt + +import ( + "fmt" + "time" + + "github.com/golang-jwt/jwt" + "github.com/rs/zerolog/log" +) + +// Encode a token +func Encode(id int) (string, error) { + // Get time + now := time.Now() + + // Create claims + claims := &Claims{ + jwt.StandardClaims{ + IssuedAt: now.Unix(), + ExpiresAt: now.Add(time.Hour * 12).Unix(), + }, + id, + } + + // Create token claims + tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + + // Sign token with secret + token, err := tokenClaims.SignedString(secret) + if err != nil { + log.Err(err).Str("id", fmt.Sprintf("%d", id)).Msg("Could not encode JWT claims") + return "", err + } + + return token, nil +} diff --git a/internal/jwt/jwt.go b/internal/jwt/jwt.go new file mode 100644 index 0000000..dd2f6f2 --- /dev/null +++ b/internal/jwt/jwt.go @@ -0,0 +1,17 @@ +package jwt + +import "github.com/golang-jwt/jwt" + +// JWT secret +var secret string + +// JWT claims +type Claims struct { + jwt.StandardClaims + ID int `json:"id"` // User ID +} + +// Set the JWT secret +func New(sec string) { + secret = sec +}