add jwt creating and parsing

This commit is contained in:
2025-12-18 10:48:27 +02:00
parent 3b74f5c43d
commit 597000f222
4 changed files with 105 additions and 0 deletions

28
internal/jwt/parse.go Normal file
View File

@@ -0,0 +1,28 @@
package jwt
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
)
func parse(
tokenStr string,
method jwt.SigningMethod,
key any,
) (jwt.Claims, error) {
t, err := jwt.Parse(tokenStr, func(tok *jwt.Token) (any, error) {
if tok.Method.Alg() != method.Alg() {
return nil, fmt.Errorf("unexpected signing method")
}
return key, nil
})
if err != nil {
return nil, err
}
// check validity twice: invalid token may return nil error
if !t.Valid {
return nil, fmt.Errorf("invalid token")
}
return t.Claims, nil
}

49
internal/jwt/service.go Normal file
View File

@@ -0,0 +1,49 @@
package jwt
import (
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
)
type Service struct {
signer Signer
expiry time.Duration
}
func NewService(signer Signer, exp time.Duration) *Service {
return &Service{
signer: signer,
expiry: exp,
}
}
// Generate creates a new JWT token for a given user ID and
// returns the token string along with its JTI(JWT IDentifier).
func (s *Service) Generate(userID int) (string, string, error) {
jti := uuid.NewString()
claims := jwt.MapClaims{
"sub": userID,
"jti": jti,
"exp": time.Now().Add(s.expiry).Unix(),
"iat": time.Now().Unix(),
}
token, err := s.signer.Sign(claims)
return token, jti, err
}
// Validate verifies the JWT token and extracts the user ID and JTI(JWT IDentifier).
func (s *Service) Validate(token string) (int, string, error) {
claims, err := s.signer.Verify(token)
if err != nil {
return 0, "", err
}
sub := int(claims.(jwt.MapClaims)["sub"].(float64))
jti := claims.(jwt.MapClaims)["jti"].(string)
return sub, jti, nil
}

8
internal/jwt/signer.go Normal file
View File

@@ -0,0 +1,8 @@
package jwt
import "github.com/golang-jwt/jwt/v5"
type Signer interface {
Sign(claims jwt.Claims) (string, error)
Verify(token string) (jwt.Claims, error)
}

View File

@@ -0,0 +1,20 @@
package jwt
import "github.com/golang-jwt/jwt/v5"
type HMACSigner struct {
secret []byte
}
func NewHMACSigner(secret []byte) *HMACSigner {
return &HMACSigner{secret: secret}
}
func (s *HMACSigner) Sign(claims jwt.Claims) (string, error) {
t := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return t.SignedString(s.secret)
}
func (s *HMACSigner) Verify(tokenStr string) (jwt.Claims, error) {
return parse(tokenStr, jwt.SigningMethodHS256, s.secret)
}