1package webterm
2
3import (
4 "context"
5 "net/http"
6 "net/http/httptest"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/coder/websocket"
12 "github.com/stretchr/testify/require"
13)
14
15func TestRotationRevokesViewsAndCookies(t *testing.T) {
16 ctx, cancel := context.WithTimeout(t.Context(), 5*time.Second)
17 defer cancel()
18 token, err := NewToken()
19 require.NoError(t, err)
20 h, err := NewServer(ctx, Settings{}, token, func(ctx context.Context, terminal *Terminal) error {
21 if err := terminal.Flush(); err != nil {
22 return err
23 }
24 <-ctx.Done()
25 return ctx.Err()
26 })
27 require.NoError(t, err)
28 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.Host = Address; h.ServeHTTP(w, r) }))
29 defer server.Close()
30 conn, _, err := websocket.Dial(ctx, "ws"+strings.TrimPrefix(server.URL, "http")+"/ws", &websocket.DialOptions{HTTPHeader: http.Header{"Origin": {Origin}, "Cookie": {cookieName + "=" + token}}})
31 require.NoError(t, err)
32 defer conn.CloseNow()
33 conn.SetReadLimit(64 << 20)
34 _, _, err = conn.Read(ctx)
35 require.NoError(t, err)
36 views := func(credential string) *httptest.ResponseRecorder {
37 r := httptest.NewRequest(http.MethodGet, Origin+"/views", nil)
38 r.AddCookie(&http.Cookie{Name: cookieName, Value: credential})
39 w := httptest.NewRecorder()
40 h.ServeHTTP(w, r)
41 return w
42 }
43 require.JSONEq(t, `{"active":1}`, views(token).Body.String())
44 renewed, err := h.RenewToken()
45 require.NoError(t, err)
46 require.NotEqual(t, token, renewed)
47 require.Equal(t, http.StatusUnauthorized, views(token).Code)
48 for {
49 _, _, err = conn.Read(ctx)
50 if err != nil {
51 break
52 }
53 }
54 require.Error(t, err)
55 h.Wait()
56 require.JSONEq(t, `{"active":0}`, views(renewed).Body.String())
57}