fix(bskyweb): sanitize DID colons in Google Wallet object id

This commit is contained in:
vineyardbovines
2026-06-25 16:23:36 -04:00
parent 07a3b987ed
commit 089ee66a30
4 changed files with 47 additions and 2 deletions
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"encoding/pem"
"errors"
"net/url"
"strings"
"github.com/golang-jwt/jwt/v5"
)
@@ -63,7 +64,7 @@ func BuildSaveJWT(cfg *WalletConfig, did, handle, theme string) (string, error)
heroURL := cfg.HeroBaseURL + "?" + heroQuery.Encode()
obj := map[string]any{
"id": cfg.IssuerID + ".bsky-" + did + "-" + theme,
"id": cfg.IssuerID + ".bsky-" + strings.ReplaceAll(did, ":", "_") + "-" + theme,
"classId": cfg.IssuerID + ".bsky_invite_v1",
"logo": map[string]any{
"sourceUri": map[string]any{"uri": cfg.LogoURL},
+43 -1
View File
@@ -46,7 +46,7 @@ func TestBuildSaveJWT_RoundTrip(t *testing.T) {
t.Fatalf("want 1 object, got %d", len(objs))
}
obj := objs[0].(map[string]any)
if !strings.HasSuffix(obj["id"].(string), ".bsky-did:plc:abc-dusk") {
if !strings.HasSuffix(obj["id"].(string), ".bsky-did_plc_abc-dusk") {
t.Errorf("unexpected id: %v", obj["id"])
}
if obj["hexBackgroundColor"] != "#b15aa2" {
@@ -71,3 +71,45 @@ func TestBuildSaveJWT_ThemeCoerced(t *testing.T) {
t.Errorf("expected coercion to day, got id %v", obj["id"])
}
}
func TestBuildSaveJWT_IdSanitizesDidColons(t *testing.T) {
key, _ := rsa.GenerateKey(rand.Reader, 2048)
cfg := &WalletConfig{
IssuerEmail: "issuer@example.com",
IssuerID: "3388000000000000000",
PrivateKey: key,
HeroBaseURL: "https://bsky.app/invite/wallet/hero",
LogoURL: "https://web-cdn.bsky.app/passes/logo.png",
}
tok, err := BuildSaveJWT(cfg, "did:plc:abc123", "alice.bsky.social", "day")
if err != nil {
t.Fatalf("build: %v", err)
}
parsed, err := jwt.Parse(tok, func(t *jwt.Token) (any, error) {
return &key.PublicKey, nil
})
if err != nil {
t.Fatalf("parse: %v", err)
}
claims := parsed.Claims.(jwt.MapClaims)
payload := claims["payload"].(map[string]any)
objs := payload["genericObjects"].([]any)
if len(objs) != 1 {
t.Fatalf("want 1 object, got %d", len(objs))
}
obj := objs[0].(map[string]any)
// Assert that the id ends with the sanitized DID (colons replaced with underscores)
if !strings.HasSuffix(obj["id"].(string), ".bsky-did_plc_abc123-day") {
t.Errorf("expected id to end with .bsky-did_plc_abc123-day, got %v", obj["id"])
}
// Assert that the barcode value still contains the original profile URL
barcode := obj["barcode"].(map[string]any)
if barcode["value"] != "https://bsky.app/profile/alice.bsky.social" {
t.Errorf("expected barcode.value to be unchanged, got %v", barcode["value"])
}
}
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
# Placeholder static files