Skip to content

Commit c35fba4

Browse files
authored
fix(realtime): patch channel join payloads with resolved access token before flushing send buffer (#2136)
1 parent f681484 commit c35fba4

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

packages/core/realtime-js/src/RealtimeClient.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,34 @@ export default class RealtimeClient {
695695

696696
authPromise
697697
.then(() => {
698+
// When subscribe() is called before the accessToken callback has
699+
// resolved (common on React Native / Expo where token storage is
700+
// async), the phx_join payload captured at subscribe()-time will
701+
// have no access_token. By this point auth has settled and
702+
// this.accessTokenValue holds the real JWT.
703+
//
704+
// The stale join messages sitting in sendBuffer captured the old
705+
// (token-less) payload in a closure, so we cannot simply flush
706+
// them. Instead we:
707+
// 1. Patch each channel's joinPush payload with the real token
708+
// 2. Drop the stale buffered messages
709+
// 3. Re-send the join for any channel still in "joining" state
710+
//
711+
// On browsers this is a harmless no-op: accessTokenValue was
712+
// already set synchronously before subscribe() ran, so the join
713+
// payload already had the correct token.
714+
if (this.accessTokenValue) {
715+
this.channels.forEach((channel) => {
716+
channel.updateJoinPayload({ access_token: this.accessTokenValue })
717+
})
718+
this.sendBuffer = []
719+
this.channels.forEach((channel) => {
720+
if (channel._isJoining()) {
721+
channel.joinPush.sent = false
722+
channel.joinPush.send()
723+
}
724+
})
725+
}
698726
this.flushSendBuffer()
699727
})
700728
.catch((e) => {

0 commit comments

Comments
 (0)