package auth import ( "context" "testing" "time" "github.com/alicebob/miniredis/v2" goredis "github.com/redis/go-redis/v9" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func newFailingSessionRedisClient(t *testing.T) *goredis.Client { t.Helper() client := goredis.NewClient(&goredis.Options{ Addr: "127.0.0.1:1", MaxRetries: 0, DialTimeout: 10 * time.Millisecond, ReadTimeout: 10 * time.Millisecond, WriteTimeout: 10 * time.Millisecond, }) t.Cleanup(func() { _ = client.Close() }) return client } func TestSessionStoreRotateRefreshSuccess(t *testing.T) { mr := miniredis.RunT(t) client := goredis.NewClient(&goredis.Options{Addr: mr.Addr()}) t.Cleanup(func() { _ = client.Close() }) store := NewSessionStore(client) ctx := context.Background() require.NoError(t, store.SaveRefresh(ctx, "old-jti", "old-hash", time.Minute)) require.NoError(t, store.RotateRefresh(ctx, "old-jti", "old-hash", "new-jti", "new-hash", 2*time.Minute)) _, err := store.GetRefresh(ctx, "old-jti") assert.Error(t, err) value, err := store.GetRefresh(ctx, "new-jti") require.NoError(t, err) assert.Equal(t, "new-hash", value) } func TestSessionStoreRotateRefreshRejectsMismatch(t *testing.T) { mr := miniredis.RunT(t) client := goredis.NewClient(&goredis.Options{Addr: mr.Addr()}) t.Cleanup(func() { _ = client.Close() }) store := NewSessionStore(client) ctx := context.Background() require.NoError(t, store.SaveRefresh(ctx, "old-jti", "old-hash", time.Minute)) err := store.RotateRefresh(ctx, "old-jti", "wrong-hash", "new-jti", "new-hash", 2*time.Minute) require.ErrorIs(t, err, ErrRefreshTokenMismatch) value, getErr := store.GetRefresh(ctx, "old-jti") require.NoError(t, getErr) assert.Equal(t, "old-hash", value) _, getErr = store.GetRefresh(ctx, "new-jti") assert.Error(t, getErr) } func TestSessionStoreUsesMemoryFallbackWhenRedisUnavailable(t *testing.T) { store := NewSessionStore(newFailingSessionRedisClient(t)) ctx := context.Background() require.NoError(t, store.SaveRefresh(ctx, "old-jti", "old-hash", time.Minute)) value, err := store.GetRefresh(ctx, "old-jti") require.NoError(t, err) assert.Equal(t, "old-hash", value) require.NoError(t, store.RotateRefresh(ctx, "old-jti", "old-hash", "new-jti", "new-hash", time.Minute)) _, err = store.GetRefresh(ctx, "old-jti") assert.Error(t, err) value, err = store.GetRefresh(ctx, "new-jti") require.NoError(t, err) assert.Equal(t, "new-hash", value) require.NoError(t, store.Blacklist(ctx, "access-jti", time.Minute)) revoked, err := store.IsBlacklisted(ctx, "access-jti") require.NoError(t, err) assert.True(t, revoked) }