Skip to content
quarry Artifact [bcda50eff8]
Login

Artifact [bcda50eff8]

Artifact bcda50eff82c37ba88ea5468caffabb385b065e954c63292e3144a952265e0ce:


package web

import (
	"net/http"
	"net/url"
	"strings"
	"testing"
)

// An invite link is a BEARER CREDENTIAL: it opens an account. (A reset
// link is never shown to anybody but its owner, by mail — #319.) It used to
// ride setFlash, which is Path="/" with a 30-second life — so until it
// was spent the browser sent it back on every request to any path, and
// the credential crossed the edge many times instead of once.
//
// It rides the vault now (secretvault.go): the link stays server-side
// under a single-use nonce and only the nonce travels.
func TestTheOneTimeLinksDoNotRideTheFlash(t *testing.T) {
	srv, accts, _ := betaForge(t)
	if err := accts.AddAccount("jo", "the-old-password", false); err != nil {
		t.Fatal(err)
	}
	for _, c := range []struct {
		name, path string
		form       url.Values
	}{
		{"an invite", "/fleet/people/invite", url.Values{"name": {"newbie"}}},
	} {
		res := as(t, srv, "root", "POST", c.path, c.form)
		body(res)
		if res.StatusCode != 303 {
			t.Errorf("FAIL: %s answered %d", c.name, res.StatusCode)
			continue
		}
		// The nonce travels; the link does not.
		where := res.Header.Get("Location")
		if !strings.Contains(where, "?s=") {
			t.Errorf("FAIL: %s carries no vault nonce: %q", c.name, where)
		} else if strings.Contains(where, "/invite/") {
			t.Errorf("FAIL: %s put the link itself in the URL: %q", c.name, where)
		} else {
			t.Logf("ok: %s travels as a nonce", c.name)
		}
		// And no cookie the response sets contains the link.
		for _, ck := range res.Cookies() {
			if strings.Contains(ck.Value, "/invite/") {
				t.Errorf("FAIL: %s put the link in cookie %q", c.name, ck.Name)
			}
		}
		t.Logf("ok: %s is in no cookie", c.name)
	}
}

// Single use, which is what "shown once" has always claimed. Asking
// twice with the same nonce shows nothing the second time.
func TestAOneTimeLinkIsShownOnce(t *testing.T) {
	srv, accts, _ := betaForge(t)
	if err := accts.AddAccount("jo", "the-old-password", false); err != nil {
		t.Fatal(err)
	}
	res := as(t, srv, "root", "POST", "/fleet/people/invite", url.Values{"name": {"newbie"}})
	body(res)
	where := res.Header.Get("Location")

	get := func() string {
		req, _ := http.NewRequest("GET", srv.URL+where, nil)
		req.AddCookie(&http.Cookie{Name: sessionCookie, Value: "tok-root"})
		for _, ck := range res.Cookies() {
			req.AddCookie(ck)
		}
		r, err := http.DefaultClient.Do(req)
		if err != nil {
			t.Fatal(err)
		}
		return body(r)
	}
	if !strings.Contains(get(), "/invite/") {
		t.Fatal("FAIL: the link was not shown even once")
	}
	t.Log("ok: shown once")
	if strings.Contains(get(), "/invite/") {
		t.Error("FAIL: the same nonce showed the link twice")
	} else {
		t.Log("ok: and not twice")
	}
}