Skip to content
quarry Artifact [ce268b6ce7]
Login

Artifact [ce268b6ce7]

Artifact ce268b6ce73a367013af0f21a535697200c078ff37a1367162417e78bccb8777:


package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"craftdesign.group/quarry/internal/oltp"
	"craftdesign.group/quarry/internal/ops"
	"craftdesign.group/quarry/internal/web"
)

// A SESSION OPENED BY A SIGN-IN LINK CARRIES ITS TOKEN'S CEILING TO THE
// PAGES, A PASSWORD SESSION CARRIES NO TOKEN, AND REVOKING THE TOKEN
// TAKES THE SESSION AWAY (RFC 0021, Web sign-in).
func TestALinkSessionIsCutToItsTokensCeiling(t *testing.T) {
	g := newDoorRig(t)
	db := g.rg.odb
	_, tok := g.mint(t, oltp.TokenSpec{Scopes: scopes(oltp.ScopeWeb), Ceiling: "o"})
	link, _, err := db.MintSigninLink("jan", tok.ID, "/")
	if err != nil {
		t.Fatal(err)
	}
	cookie, _, _, ok := db.RedeemSigninLink(link, "", "")
	if !ok {
		t.Fatal("FAIL: the link opened no session")
	}
	pwCookie, _, ok := db.NewSession("jan", doorPassword)
	if !ok {
		t.Fatal("FAIL: password sign-in")
	}

	// What the pages see: the token on the request context, if any.
	seen := func(cookieValue string) (hasToken bool, canO, canI bool) {
		var out struct{ has, o, i bool }
		h := g.doors.wrap(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
			if tk, ok := ops.TokenOf(req.Context()); ok {
				out.has = true
				out.o = tk.Caps("vault").HasAny("o")
				out.i = tk.Caps("vault").HasAny("i")
			}
		}))
		req := httptest.NewRequest(http.MethodGet, "/r/vault", nil)
		req.AddCookie(&http.Cookie{Name: web.SessionCookie, Value: cookieValue})
		h.ServeHTTP(httptest.NewRecorder(), req)
		return out.has, out.o, out.i
	}
	if has, o, i := seen(cookie); !has || !o || i {
		t.Errorf("FAIL: link session token=%v o=%v i=%v; want a token holding o and not i (the account holds both)", has, o, i)
	}
	if has, _, _ := seen(pwCookie); has {
		t.Errorf("FAIL: a password session was given a token")
	}
	if err := db.RevokeToken("jan", tok.ID); err != nil {
		t.Fatal(err)
	}
	if has, _, _ := seen(cookie); has {
		t.Errorf("FAIL: the revoked token's session still carries it")
	}
	if _, ok := db.SessionAccount(cookie); ok {
		t.Errorf("FAIL: the revoked token's session still resolves")
	}
}