oficina / home Public

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

Plain git — no account needed to clone.

Download

Download this file

1package connect
2
3import (
4 "net/http"
5 "net/http/httptest"
6 "net/url"
7 "strings"
8 "testing"
9)
10
11func oauthTarget() string {
12 return "https://keymail.example/oauth/authorize?" + url.Values{"client_id": {configOrigin}, "redirect_uri": {configOrigin + "/auth/callback"}, "scope": {"identify"}, "code_challenge_method": {"S256"}, "state": {"private-state"}, "code_challenge": {"challenge"}}.Encode()
13}
14func TestOAuthContinuationPreservesPolicyCookiesAndLocalResponses(t *testing.T) {
15 for _, destination := range []string{oauthTarget(), "/signin?sent=1"} {
16 w := httptest.NewRecorder()
17 w.Header().Set("Content-Security-Policy", "form-action 'self'")
18 rendered := ""
19 h := OAuthContinuation(configOrigin, func(w http.ResponseWriter, r *http.Request) {
20 w.Header().Add("Set-Cookie", "pending=private; Path=/; Secure; HttpOnly")
21 http.Redirect(w, r, destination, 303)
22 }, func(w http.ResponseWriter, r *http.Request, target string) { rendered = target; w.WriteHeader(200) })
23 h(w, httptest.NewRequest("POST", configOrigin+"/signin", nil))
24 if w.Header().Get("Content-Security-Policy") != "form-action 'self'" || len(w.Result().Cookies()) != 1 {
25 t.Fatal("policy or pending cookie changed")
26 }
27 if strings.HasPrefix(destination, "https:") {
28 if w.Code != 200 || rendered != destination || w.Header().Get("Location") != "" || w.Header().Get("Cache-Control") != "no-store" || w.Header().Get("Referrer-Policy") != "no-referrer" {
29 t.Fatal("OAuth POST did not terminate", w.Code, w.Header())
30 }
31 } else if w.Code != 303 || rendered != "" || w.Header().Get("Location") != destination {
32 t.Fatal("local flow changed")
33 }
34 }
35}
36func TestOAuthContinuationRefusesUnboundDestinationsWithoutLeakingState(t *testing.T) {
37 for _, destination := range []string{"//keymail.example/oauth/authorize", strings.Replace(oauthTarget(), "https:", "http:", 1), strings.Replace(oauthTarget(), "scope=identify", "scope=other", 1), oauthTarget() + "&client_id=other", oauthTarget() + "#fragment", "https://user@keymail.example/oauth/authorize", "https://keymail.example/other", strings.Replace(oauthTarget(), "S256", "plain", 1)} {
38 w := httptest.NewRecorder()
39 h := OAuthContinuation(configOrigin, func(w http.ResponseWriter, r *http.Request) {
40 w.Header().Set("Set-Cookie", "private-cookie=private")
41 http.Redirect(w, r, destination, 303)
42 }, func(http.ResponseWriter, *http.Request, string) { t.Fatal("invalid redirect rendered") })
43 h(w, httptest.NewRequest("POST", configOrigin+"/signin", nil))
44 if w.Code != 502 || w.Header().Get("Location") != "" || len(w.Result().Cookies()) != 0 || strings.Contains(w.Body.String(), "private") {
45 t.Fatal("unsafe destination accepted or leaked", w.Code)
46 }
47 }
48}
49