Files
terminalShop/pkg/auth/jwt.go

86 lines
2.3 KiB
Go

package auth
import (
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"time"
"github.com/golang-jwt/jwt/v5"
gossh "golang.org/x/crypto/ssh"
)
// Claims represents the JWT claims
type Claims struct {
UserID uint `json:"user_id"`
Email string `json:"email"`
Username string `json:"username"`
jwt.RegisteredClaims
}
// JWTManager handles JWT token generation and validation
type JWTManager struct {
secretKey string
tokenDuration time.Duration
}
// NewJWTManager creates a new JWT manager
func NewJWTManager(secretKey string, tokenDuration time.Duration) *JWTManager {
return &JWTManager{
secretKey: secretKey,
tokenDuration: tokenDuration,
}
}
// GenerateToken generates a new JWT token for a user
func (m *JWTManager) GenerateToken(userID uint, email, username string) (string, error) {
claims := Claims{
UserID: userID,
Email: email,
Username: username,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(m.tokenDuration)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
Issuer: "terminalshop",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(m.secretKey))
}
// ValidateToken validates a JWT token and returns the claims
func (m *JWTManager) ValidateToken(tokenString string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (any, error) {
// Verify signing method
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(m.secretKey), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
// GetSSHKeyFingerprint returns the MD5 fingerprint of an SSH public key
// This matches the format shown by `ssh-keygen -lf ~/.ssh/id_rsa.pub`
func GetSSHKeyFingerprint(pubKey gossh.PublicKey) string {
hash := sha256.Sum256(pubKey.Marshal())
return "SHA256:" + hex.EncodeToString(hash[:])
}
// FormatSSHPublicKey formats an SSH public key in authorized_keys format
func FormatSSHPublicKey(pubKey gossh.PublicKey) string {
return string(gossh.MarshalAuthorizedKey(pubKey))
}