oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1package docs
2
3import (
4 "bytes"
5 "encoding/base64"
6 "encoding/json"
7 "net/http"
8 "net/http/httptest"
9 "testing"
10 "time"
11)
12
13func TestHomeResourceReturnSurvivesSetupAndRefusesTamper(t *testing.T) {
14 _, n := navigationFixture(t)
15 now := time.Unix(1900000000, 0)
16 n.now = func() time.Time { return now }
17 const target = "/d/private-resource?view=compact"
18 w := httptest.NewRecorder()
19 if !n.rememberReturn(w, target) {
20 t.Fatal("return intent refused")
21 }
22 cookies := w.Result().Cookies()
23 if len(cookies) != 1 || !cookies[0].Secure || !cookies[0].HttpOnly || cookies[0].SameSite != http.SameSiteLaxMode || cookies[0].MaxAge != 600 {
24 t.Fatal("unsafe navigation cookie")
25 }
26 c := cookies[0]
27 r := httptest.NewRequest("GET", navigationOrigin+"/account/home", nil)
28 r.AddCookie(c)
29 if got := n.returnPath(r); got != target {
30 t.Fatal("resource lost across setup", got)
31 }
32 raw, _ := base64.RawURLEncoding.DecodeString(c.Value)
33 if bytes.Contains(raw, []byte("private-resource")) {
34 t.Fatal("resource stored as readable cookie bytes")
35 }
36 raw[len(raw)-1] ^= 1
37 bad := *c
38 bad.Value = base64.RawURLEncoding.EncodeToString(raw)
39 tampered := httptest.NewRequest("GET", navigationOrigin+"/account/home", nil)
40 tampered.AddCookie(&bad)
41 if n.returnPath(tampered) != "/" {
42 t.Fatal("tampered return accepted")
43 }
44 other := *n
45 other.origin = "https://another.docs.example.com"
46 if other.returnPath(r) != "/" {
47 t.Fatal("other team return accepted")
48 }
49 duplicate := r.Clone(r.Context())
50 duplicate.AddCookie(c)
51 if n.returnPath(duplicate) != "/" {
52 t.Fatal("ambiguous return accepted")
53 }
54 now = now.Add(600 * time.Second)
55 if n.returnPath(r) != "/" {
56 t.Fatal("expired return accepted")
57 }
58}
59
60func TestHomeResourceReturnValidatesSealedPathAndLifetime(t *testing.T) {
61 _, n := navigationFixture(t)
62 now := int64(1900000000)
63 n.now = func() time.Time { return time.Unix(now, 0) }
64 for _, v := range []homeReturnIntent{
65 {"https://other.example", now, now + 600},
66 {"//other.example", now, now + 600},
67 {"/auth/start", now, now + 600},
68 {"/d/ok", now + 1, now + 600},
69 {"/d/ok", now, now + 601},
70 } {
71 payload, _ := json.Marshal(v)
72 sealed, err := n.sealer.Seal("docs.home-return.v1:"+n.origin, payload)
73 if err != nil {
74 t.Fatal(err)
75 }
76 r := httptest.NewRequest("GET", navigationOrigin+"/account/home", nil)
77 r.AddCookie(&http.Cookie{Name: homeReturnCookie, Value: base64.RawURLEncoding.EncodeToString(sealed)})
78 if n.returnPath(r) != "/" {
79 t.Fatal("unsafe sealed navigation accepted")
80 }
81 }
82}
83