diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index 9ac6fb9..2d3deab 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -889,11 +889,12 @@ func TestPendingStates(t *testing.T) { t.Error("Consume of an unknown state = true") } - for i := range maxPendingStates { + for i := range maxPendingStates - 1 { if err := p.Add(fmt.Sprint("s", i), now); err != nil { t.Fatalf("Add %d: %v", i, err) } } + // "first" was consumed but has not expired, so it still counts. if err := p.Add("over", now); !errors.Is(err, ErrTooManyPending) { t.Errorf("Add past the bound = %v, want ErrTooManyPending", err) } diff --git a/internal/auth/cookie.go b/internal/auth/cookie.go index df00244..6dffb34 100644 --- a/internal/auth/cookie.go +++ b/internal/auth/cookie.go @@ -200,7 +200,9 @@ func (p *PendingStates) Add(state string, now time.Time) error { expired++ } p.order = p.order[expired:] - if len(p.states) >= maxPendingStates { + // The bound counts every unexpired state, consumed or not: a consumed + // state leaves states at once but order only when it expires. + if len(p.order) >= maxPendingStates { return ErrTooManyPending } expires := now.Add(p.ttl)