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
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user