Generation and Verify JWT token in golang

Use HS256 or RS256 to sign and authorization is common JWT methods

Create the JWT token

 1package util
 2
 3import "github.com/golang-jwt/jwt/v5"
 4
 5// retrieve JWT key from .env file
 6var privateKey = []byte(os.Getenv("JWT_PRIVATE_KEY"))
 7
 8// generate JWT token
 9func GenerateJWT(user model.User) (string, error) {
10	tokenTTL, _ := strconv.Atoi(os.Getenv("TOKEN_TTL"))
11	//log.Println(time.Now())
12	//log.Println(time.Now().Add(time.Second * time.Duration(tokenTTL)))
13	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
14		"id":   user.ID,
15		"role": user.RoleID,
16		"iat":  time.Now().Unix(),
17		"eat":  time.Now().Add(time.Second * time.Duration(tokenTTL)).Unix(),
18	})
19	return token.SignedString(privateKey)
20}

Validate the JWT

 1// validate JWT token
 2func ValidateJWT(context *gin.Context) error {
 3	token, err := getToken(context)
 4	if err != nil {
 5		return err
 6	}
 7	_, ok := token.Claims.(jwt.MapClaims)
 8	if ok && token.Valid {
 9		return nil
10	}
11	return errors.New("invalid token provided")
12}
13
14// check token validity
15func getToken(context *gin.Context) (*jwt.Token, error) {
16	tokenString := getTokenFromRequest(context)
17	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
18		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
19			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
20		}
21
22		return privateKey, nil
23	})
24	return token, err
25}
26
27// extract token from request Authorization header
28func getTokenFromRequest(context *gin.Context) string {
29	bearerToken := context.Request.Header.Get("Authorization")
30	splitToken := strings.Split(bearerToken, " ")
31	if len(splitToken) == 2 {
32		return splitToken[1]
33	}
34	return ""
35}

If use RS256 to sign and verify JWT token

  • generation the PKI
1# The makefile
2.PHONY: cert
3cert:
4	openssl genrsa -out cert/id_rsa 4096
5	openssl rsa -in cert/id_rsa -pubout -out cert/id_rsa.pub
  • use the private key to sign token
 1package main
 2 
 3import (
 4	"fmt"
 5	"io/ioutil"
 6	"log"
 7	"time"
 8 
 9	"github.com/you/client/internal/pkg/token"
10)
11 
12func main() {
13	prvKey, err := ioutil.ReadFile("cert/id_rsa")
14	if err != nil {
15		log.Fatalln(err)
16	}
17	pubKey, err := ioutil.ReadFile("cert/id_rsa.pub")
18	if err != nil {
19		log.Fatalln(err)
20	}
21 
22	jwtToken := token.NewJWT(prvKey, pubKey)
23 
24	// 1. Create a new JWT token.
25	tok, err := jwtToken.Create(time.Hour, "Can be anything")
26	if err != nil {
27		log.Fatalln(err)
28	}
29	fmt.Println("TOKEN:", tok)
30 
31	// 2. Validate an existing JWT token.
32	content, err := jwtToken.Validate(tok)
33	if err != nil {
34		log.Fatalln(err)
35	}
36	fmt.Println("CONTENT:", content)
37}
  • use the public key to verify
 1package token
 2 
 3import (
 4	"fmt"
 5	"time"
 6 
 7	"github.com/dgrijalva/jwt-go"
 8)
 9 
10type JWT struct {
11	privateKey []byte
12	publicKey  []byte
13}
14 
15func NewJWT(privateKey []byte, publicKey []byte) JWT {
16	return JWT{
17		privateKey: privateKey,
18		publicKey:  publicKey,
19	}
20}
21 
22func (j JWT) Create(ttl time.Duration, content interface{}) (string, error) {
23	key, err := jwt.ParseRSAPrivateKeyFromPEM(j.privateKey)
24	if err != nil {
25		return "", fmt.Errorf("create: parse key: %w", err)
26	}
27 
28	now := time.Now().UTC()
29 
30	claims := make(jwt.MapClaims)
31	claims["dat"] = content             // Our custom data.
32	claims["exp"] = now.Add(ttl).Unix() // The expiration time after which the token must be disregarded.
33	claims["iat"] = now.Unix()          // The time at which the token was issued.
34	claims["nbf"] = now.Unix()          // The time before which the token must be disregarded.
35 
36	token, err := jwt.NewWithClaims(jwt.SigningMethodRS256, claims).SignedString(key)
37	if err != nil {
38		return "", fmt.Errorf("create: sign token: %w", err)
39	}
40 
41	return token, nil
42}
43 
44func (j JWT) Validate(token string) (interface{}, error) {
45	key, err := jwt.ParseRSAPublicKeyFromPEM(j.publicKey)
46	if err != nil {
47		return "", fmt.Errorf("validate: parse key: %w", err)
48	}
49 
50	tok, err := jwt.Parse(token, func(jwtToken *jwt.Token) (interface{}, error) {
51		if _, ok := jwtToken.Method.(*jwt.SigningMethodRSA); !ok {
52			return nil, fmt.Errorf("unexpected method: %s", jwtToken.Header["alg"])
53		}
54 
55		return key, nil
56	})
57	if err != nil {
58		return nil, fmt.Errorf("validate: %w", err)
59	}
60 
61	claims, ok := tok.Claims.(jwt.MapClaims)
62	if !ok || !tok.Valid {
63		return nil, fmt.Errorf("validate: invalid")
64	}
65 
66	return claims["dat"], nil
67}

Reference