Skip to content
This repository was archived by the owner on Jul 18, 2026. It is now read-only.

fix(spotify): profile identity from the session, not spclient (v1.1.0)#97

Merged
volod-vana merged 2 commits into
mainfrom
volod/spotify-profile-identity
Jul 15, 2026
Merged

fix(spotify): profile identity from the session, not spclient (v1.1.0)#97
volod-vana merged 2 commits into
mainfrom
volod/spotify-profile-identity

Conversation

@volod-vana

Copy link
Copy Markdown
Member

What

Spotify exports were stamped with a stranger's name and avatar ("Micael Widell") over the user's own account.

Root cause

The connector built spotify.profile from two sources: id/uri from the session-bound GraphQL me query (correct), but display_name/avatar/follower-counts from spclient.wg.spotify.com/user-profile-view/v3/profile/me. That spclient endpoint is not session-bound - called with a token that is not tied to a user it still returns 200 with uri: "spotify:user:me" and a fixed foreign profile. So the merged record carried the user's real id and real collected tracks, but someone else's name/photo/counts.

Reproducible with a fresh anonymous token (no login, no cookies) - every caller gets the same foreign profile:

curl -s https://spclient.wg.spotify.com/user-profile-view/v3/profile/me \
  -H "authorization: Bearer $TOKEN" -H "app-platform: WebPlayer"
# -> {"uri":"spotify:user:me","name":"Micael Widell", "followers_count":56, ...}

Fix

  • Identity (id, display_name, uri) comes only from the session GraphQL profileAttributes.me.
  • spclient is used strictly as enrichment (avatar + counts, not exposed by GraphQL) and only when its uri equals the resolved identity; the spotify:user:me sentinel is rejected.
  • If the session profile cannot be resolved, the run fails clearly instead of importing a stranger.
  • Version 1.0.0 to 1.1.0; connector-index regenerated.

Follow-up (separate)

Every user who already connected Spotify has a spotify.profile record with the wrong name/avatar in their PS - needs a re-collect or a one-off rewrite. Will file a ticket.

…1.1.0)

`/user-profile-view/v3/profile/me` on spclient.wg.spotify.com is NOT
session-bound: called with a token that is not tied to a user it still
returns 200, with `uri: "spotify:user:me"` and a fixed stranger's
name/avatar/follower counts (reproduced with a fresh anonymous token -
every caller gets the same foreign profile). The connector read
display_name/avatar/counts from there while taking id/uri from the
session GraphQL query, so every user's export was stamped with that
stranger's identity over their own id and their own collected data.

Identity now comes only from the session-bound GraphQL `me`
(profileAttributes). spclient is used strictly as enrichment (avatar +
counts, which GraphQL does not expose) and only when its `uri` matches
the resolved identity; the "spotify:user:me" sentinel is rejected. If the
session profile cannot be resolved the run fails clearly instead of
silently importing someone else.

Claude-Session: https://claude.ai/code/session_01DYpJrHgZxFcFW9apg9uPaa
@github-actions

Copy link
Copy Markdown

Schema Health Check — Non-blocking inherited issues

44/50 scopes consistent | 6 inherited Gateway gap(s) | no new blocking issues in this PR

Refines the enrichment call after confirming the exact root cause
(matches the interrogator report): the trailing path segment of
/user-profile-view/v3/profile/<name> is a literal vanity username, not a
self-alias, and a real user owns the username "me"
(open.spotify.com/user/me => "Micael Widell"). Passing "me" returned that
stranger's avatar/counts for everyone.

Now the profile-view is fetched for the session-resolved username
(pa.username), so avatar + follower/following counts are the user's own
again instead of being dropped. The uri-equality guard stays as
defense-in-depth.

Claude-Session: https://claude.ai/code/session_01DYpJrHgZxFcFW9apg9uPaa
@volod-vana
volod-vana merged commit 37b45c3 into main Jul 15, 2026
2 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant