* fix(security): harden auth and credential handling (HH-444) * fix(security): address HH-444 review blockers * fix(security): close remaining HH-444 review blockers --------- Co-authored-by: Rogee <rogee@ipao.vip>
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/redis/go-redis/v9"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gochat/gochat/internal/config"
|
|
"github.com/gochat/gochat/internal/model"
|
|
)
|
|
|
|
func TestJWTAccessTokenUsesConfiguredMinuteExpiry(t *testing.T) {
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 15, RefreshExpiryHours: 168}
|
|
service := NewJWTService(cfg)
|
|
|
|
pair, err := service.GenerateTokenPair(&model.User{Base: model.Base{ID: 7}, Provider: "email"}, 3, "agent")
|
|
require.NoError(t, err)
|
|
require.WithinDuration(t, time.Now().Add(15*time.Minute), pair.ExpiresAt, 2*time.Second)
|
|
}
|
|
|
|
func TestRefreshRotationRejectsReusedToken(t *testing.T) {
|
|
cfg := &config.JWTConfig{Secret: "test-secret", AccessExpiryMinutes: 15, RefreshExpiryHours: 168}
|
|
store := NewRefreshTokenStore(nil, cfg)
|
|
ctx := context.Background()
|
|
|
|
require.NoError(t, store.StoreForClient(ctx, 7, "browser", "old-token"))
|
|
require.NoError(t, store.RotateForClient(ctx, 7, "browser", "new-token"))
|
|
valid, err := store.ValidateForClient(ctx, 7, "browser", "old-token")
|
|
require.NoError(t, err)
|
|
require.False(t, valid)
|
|
}
|
|
|
|
func TestWSTicketIsOneTimeAndExpires(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
t.Cleanup(func() { _ = rdb.Close() })
|
|
store := NewWSTicketStore(rdb, 5*time.Second)
|
|
ctx := context.Background()
|
|
want := WSTicketClaims{UserID: 7, AccountID: 3, Role: "agent", Provider: "email"}
|
|
|
|
ticket, err := store.Issue(ctx, want)
|
|
require.NoError(t, err)
|
|
got, err := store.Consume(ctx, ticket)
|
|
require.NoError(t, err)
|
|
require.Equal(t, want, *got)
|
|
_, err = store.Consume(ctx, ticket)
|
|
require.ErrorIs(t, err, ErrInvalidWSTicket)
|
|
|
|
expiring, err := store.Issue(ctx, want)
|
|
require.NoError(t, err)
|
|
mr.FastForward(6 * time.Second)
|
|
_, err = store.Consume(ctx, expiring)
|
|
require.True(t, errors.Is(err, ErrInvalidWSTicket))
|
|
}
|