fix: review findings (async SQS dispatcher, backoff, batch insert, shutdown order, pagination, HMAC) + loadtest fixes; v0.1.6

This commit is contained in:
“Naeel”
2026-08-16 18:24:09 +04:00
parent 090cedca67
commit 3fedf9317c
27 changed files with 581 additions and 122 deletions
+34 -9
View File
@@ -2,6 +2,8 @@
package middleware
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"log/slog"
"net/http"
@@ -12,11 +14,10 @@ import (
//
// authTestMode (env AUTH_TEST_MODE, дефолт false):
// - true — принимается любая строка без пробелов (для локальных тестов);
// - false — структурная проверка JWT (sub + exp), как в старом коде.
//
// В новой архитектуре подпись JWT не проверяется (как и раньше): внешний
// периметр обеспечивает платформа, полная валидация — на стороне шлюза.
func Auth(authTestMode bool, log *slog.Logger, next http.Handler) http.Handler {
// - false — проверка JWT: sub + exp; если задан hmacSecret — обязательна
// HS256-подпись (HMAC-SHA256, env JWT_HMAC_SECRET). Без секрета —
// структурная проверка (периметр обеспечивает платформа).
func Auth(authTestMode bool, hmacSecret string, log *slog.Logger, next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
header := r.Header.Get("Authorization")
if header == "" {
@@ -38,7 +39,7 @@ func Auth(authTestMode bool, log *slog.Logger, next http.Handler) http.Handler {
return
}
if err := validateJWT(token); err != nil {
if err := validateJWT(token, hmacSecret); err != nil {
log.Warn("auth: invalid token", "remote", r.RemoteAddr, "path", r.URL.Path, "reason", err.Error())
http.Error(w, `{"error":"invalid token"}`, http.StatusForbidden)
return
@@ -60,13 +61,37 @@ type jwtError struct{ msg string }
func (e *jwtError) Error() string { return e.msg }
// validateJWT проверяет структуру JWT: три части, корректный payload, sub и exp.
// Подпись НЕ проверяется — см. комментарий пакета.
func validateJWT(token string) error {
// validateJWT проверяет структуру JWT (sub + exp) и, если задан secret,
// HS256-подпись. Без secret подпись не проверяется — см. комментарий Auth.
func validateJWT(token, secret string) error {
jwtParts := strings.Split(token, ".")
if len(jwtParts) != 3 {
return &jwtError{"not a JWT: expected 3 parts"}
}
if secret != "" {
var header struct {
Alg string `json:"alg"`
}
headerBytes, err := base64.RawURLEncoding.DecodeString(jwtParts[0])
if err != nil {
headerBytes, err = base64.StdEncoding.DecodeString(jwtParts[0])
}
if err != nil || jsonUnmarshal(headerBytes, &header) != nil || header.Alg != "HS256" {
return &jwtError{"JWT must be HS256 when JWT_HMAC_SECRET is set"}
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(jwtParts[0] + "." + jwtParts[1]))
expected := mac.Sum(nil)
sig, err := base64.RawURLEncoding.DecodeString(jwtParts[2])
if err != nil {
return &jwtError{"cannot decode JWT signature"}
}
if !hmac.Equal(expected, sig) {
return &jwtError{"JWT signature mismatch"}
}
}
payload := jwtParts[1]
switch len(payload) % 4 {
case 2: