package infra import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "errors" "time" ) // JWTGenerate codifica un JWT firmado con HMAC-SHA256 (alg: HS256). // Si claims.IssuedAt viene en cero se setea a time.Now().Unix(). // Retorna el token en formato "header.payload.signature" con los tres segmentos // codificados en base64url sin padding. func JWTGenerate(claims JWTClaims, secret string) (string, error) { if secret == "" { return "", errors.New("jwt_generate: secret vacio") } if claims.IssuedAt == 0 { claims.IssuedAt = time.Now().Unix() } header := map[string]string{"alg": "HS256", "typ": "JWT"} headerJSON, err := json.Marshal(header) if err != nil { return "", err } payloadJSON, err := json.Marshal(claims) if err != nil { return "", err } enc := base64.RawURLEncoding headerPart := enc.EncodeToString(headerJSON) payloadPart := enc.EncodeToString(payloadJSON) signingInput := headerPart + "." + payloadPart mac := hmac.New(sha256.New, []byte(secret)) mac.Write([]byte(signingInput)) sigPart := enc.EncodeToString(mac.Sum(nil)) return signingInput + "." + sigPart, nil }