~bigbes/sr-ht-ecore

e8a9672594733218fd773bab9e9216ae1c2db6c2 — Eugene Blikh 9 days ago b6bf6d2
bearer: mint the internal authorization through internalauth

This package assembled the header by hand — json.Marshal of an auth.InternalAuth
plus "Internal " and a fernet seal — two files away from the package whose whole
purpose is to hold both ends of that handshake. It is the same drift internalauth
was hoisted to end, sitting inside the library that hoisted it: a change to the
payload shape here would have gone unnoticed by every Guard on the instance until
a revocation check started failing.
1 files changed, 8 insertions(+), 4 deletions(-)

M bearer/bearer.go
M bearer/bearer.go => bearer/bearer.go +8 -4
@@ 47,7 47,6 @@ package bearer

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"


@@ 59,9 58,9 @@ import (
	"time"

	"sourcecraft.dev/bigbes/sr-ht-core/auth"
	"sourcecraft.dev/bigbes/sr-ht-core/crypto"

	"sourcecraft.dev/bigbes/sr-ht-ecore/grants"
	"sourcecraft.dev/bigbes/sr-ht-ecore/internalauth"
)

// TokensClientID is the ClientID tokens.sr.ht stamps into every working token it


@@ 479,7 478,12 @@ func (v *Validator) checkRevocation(ctx context.Context, id int) error {
	// The internal authorization is minted per request and cannot be cached: it
	// is a fernet blob the daemon accepts only for thirty seconds, which is what
	// stops a captured one being replayed for a week.
	blob, err := json.Marshal(auth.InternalAuth{ClientID: v.clientID, NodeID: v.nodeID})
	//
	// Through internalauth rather than assembled here, so that this caller and
	// every Guard on the instance read one definition of the payload. Minting it
	// by hand next to a package whose whole purpose is to hold both ends of this
	// handshake is the drift that package exists to prevent.
	authorization, err := internalauth.Authorization(v.clientID, v.nodeID)
	if err != nil {
		return fmt.Errorf("%w: sealing the internal authorization: %s", ErrUnavailable, err)
	}


@@ 489,7 493,7 @@ func (v *Validator) checkRevocation(ctx context.Context, id int) error {
	if err != nil {
		return fmt.Errorf("%w: building the request for %s: %s", ErrUnavailable, url, err)
	}
	req.Header.Set("Authorization", "Internal "+string(crypto.Encrypt(blob)))
	req.Header.Set("Authorization", authorization)

	resp, err := v.client.Do(req)
	if err != nil {