feat(auth): argon2id пароли + session store (sha256 токена)

This commit is contained in:
2026-07-03 19:50:11 +07:00
parent 3bd237d562
commit 12b7945efc
6 changed files with 203 additions and 11 deletions
+56
View File
@@ -0,0 +1,56 @@
package auth
import (
"context"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"errors"
"time"
"github.com/google/uuid"
)
var ErrNoSession = errors.New("auth: no such session")
type SessionStore interface {
CreateSession(ctx context.Context, userID uuid.UUID, tokenHash string, expiresAt time.Time) error
GetSessionUser(ctx context.Context, tokenHash string) (uuid.UUID, error)
DeleteSession(ctx context.Context, tokenHash string) error
}
type Sessions struct {
store SessionStore
ttl time.Duration
}
func NewSessions(store SessionStore, ttl time.Duration) *Sessions {
return &Sessions{store: store, ttl: ttl}
}
func TokenHash(token string) string {
sum := sha256.Sum256([]byte(token))
return hex.EncodeToString(sum[:])
}
func (s *Sessions) Create(ctx context.Context, userID uuid.UUID) (string, time.Time, error) {
raw := make([]byte, 32)
if _, err := rand.Read(raw); err != nil {
return "", time.Time{}, err
}
token := base64.RawURLEncoding.EncodeToString(raw)
exp := time.Now().Add(s.ttl)
if err := s.store.CreateSession(ctx, userID, TokenHash(token), exp); err != nil {
return "", time.Time{}, err
}
return token, exp, nil
}
func (s *Sessions) Validate(ctx context.Context, token string) (uuid.UUID, error) {
return s.store.GetSessionUser(ctx, TokenHash(token))
}
func (s *Sessions) Destroy(ctx context.Context, token string) error {
return s.store.DeleteSession(ctx, TokenHash(token))
}