Files
egutierrez eff5771b03 feat: jwt_generate, jwt_validate, password_hash, password_verify
Fase 2 del issue 0010 — auth core:
- jwt_generate/validate: HS256 manual con crypto/hmac + crypto/sha256
- password_hash/verify: wrappers de golang.org/x/crypto/bcrypt (cost 12 default)
- JWT rechaza alg != HS256 para mitigar ataque 'alg=none'
- hmac.Equal para comparacion constant-time de firmas
2026-04-18 17:39:00 +02:00

55 lines
1.3 KiB
Go

package infra
import (
"strings"
"testing"
"time"
)
func TestJWTGenerate_ReturnsThreeSegments(t *testing.T) {
claims := JWTClaims{
Subject: "user-1",
ExpiresAt: time.Now().Add(time.Hour).Unix(),
}
token, err := JWTGenerate(claims, "test-secret-0123456789abcdef")
if err != nil {
t.Fatalf("JWTGenerate error: %v", err)
}
parts := strings.Split(token, ".")
if len(parts) != 3 {
t.Fatalf("esperados 3 segmentos, got %d en %q", len(parts), token)
}
for i, p := range parts {
if p == "" {
t.Fatalf("segmento %d vacio", i)
}
}
}
func TestJWTGenerate_FillsIssuedAtWhenZero(t *testing.T) {
claims := JWTClaims{
Subject: "user-1",
ExpiresAt: time.Now().Add(time.Hour).Unix(),
}
before := time.Now().Unix()
token, err := JWTGenerate(claims, "s")
if err != nil {
t.Fatalf("JWTGenerate error: %v", err)
}
after := time.Now().Unix()
parsed, err := JWTValidate(token, "s")
if err != nil {
t.Fatalf("JWTValidate error: %v", err)
}
if parsed.IssuedAt < before || parsed.IssuedAt > after {
t.Fatalf("IssuedAt %d fuera del rango [%d,%d]", parsed.IssuedAt, before, after)
}
}
func TestJWTGenerate_ErrorsOnEmptySecret(t *testing.T) {
_, err := JWTGenerate(JWTClaims{Subject: "x"}, "")
if err == nil {
t.Fatal("esperaba error con secret vacio")
}
}