07341aa89f
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
47 lines
1.8 KiB
Markdown
47 lines
1.8 KiB
Markdown
---
|
|
name: jwt_generate
|
|
kind: function
|
|
lang: go
|
|
domain: infra
|
|
version: "1.0.0"
|
|
purity: impure
|
|
signature: "func JWTGenerate(claims JWTClaims, secret string) (string, error)"
|
|
description: "Codifica y firma un JWT con HMAC-SHA256 (HS256). Retorna el token en formato header.payload.signature. Setea IssuedAt automaticamente si viene en cero."
|
|
tags: [jwt, auth, token, hmac, sign, infra]
|
|
uses_functions: []
|
|
uses_types: [JWTClaims_go_infra]
|
|
returns: []
|
|
returns_optional: false
|
|
error_type: error_go_core
|
|
imports: [crypto/hmac, crypto/sha256, encoding/base64, encoding/json, errors, time]
|
|
params:
|
|
- name: claims
|
|
desc: "claims del JWT (sub, iss, aud, exp, iat, custom). Si IssuedAt es 0 se rellena con time.Now()"
|
|
- name: secret
|
|
desc: "clave HMAC para firmar. No debe estar vacia. Obtenerla de env var o pass_get, nunca hardcoded"
|
|
output: "token JWT firmado en formato base64url header.payload.signature"
|
|
tested: true
|
|
tests: ["genera token valido con claims completas", "setea IssuedAt si viene en cero", "error si secret vacio"]
|
|
test_file_path: "functions/infra/jwt_generate_test.go"
|
|
file_path: "functions/infra/jwt_generate.go"
|
|
---
|
|
|
|
## Ejemplo
|
|
|
|
```go
|
|
claims := JWTClaims{
|
|
Subject: "user-123",
|
|
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
|
|
Custom: map[string]any{"role": "admin"},
|
|
}
|
|
token, err := JWTGenerate(claims, os.Getenv("JWT_SECRET"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
w.Header().Set("Authorization", "Bearer " + token)
|
|
```
|
|
|
|
## Notas
|
|
|
|
Impura — usa `time.Now()` para el claim `iat` cuando no viene fijado. Implementa HS256 sin libreria externa (solo stdlib crypto/hmac + crypto/sha256). Solo soporta HS256: para RS256/ES256 se crearia una funcion separada. El secret debe tener al menos 256 bits de entropia (32+ bytes aleatorios) para resistencia real. NO apto para escenarios multi-servicio donde se necesita clave publica/privada — usa RS256 en ese caso.
|