From e8a9672594733218fd773bab9e9216ae1c2db6c2 Mon Sep 17 00:00:00 2001 From: Eugene Blikh Date: Sun, 9 Aug 2026 00:45:12 +0300 Subject: [PATCH] bearer: mint the internal authorization through internalauth MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- bearer/bearer.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/bearer/bearer.go b/bearer/bearer.go index 71f88b934b74126a84328d9146e86a211eaef41b..d974dddd0384cbc69de6e043f2f30958b37bb31d 100644 --- a/bearer/bearer.go +++ b/bearer/bearer.go @@ -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 {