package auth import ( "context" "strings" "time" "github.com/golang-jwt/jwt/v4" ) type Claims struct { UserID string `json:"user_id"` Username string `json:"username"` jwt.RegisteredClaims } type TokenManager struct { secretKey string } func NewTokenManager(secretKey string) *TokenManager { return &TokenManager{ secretKey: secretKey, } } func (tm *TokenManager) CreateToken(userID, username string) (string, error) { claims := &Claims{ UserID: userID, Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString([]byte(tm.secretKey)) if err != nil { return "", err } return tokenString, nil } func (tm *TokenManager) ValidateToken(tokenString string) (*Claims, error) { token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) { return []byte(tm.secretKey), nil }) if err != nil || !token.Valid { return nil, err } claims, ok := token.Claims.(*Claims) if !ok { return nil, jwt.ErrSignatureInvalid } return claims, nil } func ExtractToken(ctx context.Context) string { // Extract token fromAuthorization header authHeader := ctx.Value("Authorization") if authHeader != nil { header := authHeader.(string) if strings.HasPrefix(header, "Bearer ") { return strings.TrimPrefix(header, "Bearer ") } } return "" }