Skip to content

Commit e28b0e4

Browse files
Re-establish streams when App Check token expires. (#5902)
* Re-establish streams when App Check token expires. * Create happy-badgers-leave.md * Better patch message. * better patch message. * address comments. * Remove outdated comment. * Update packages/firestore/src/core/firestore_client.ts Co-authored-by: Sebastian Schmidt <[email protected]> Co-authored-by: Sebastian Schmidt <[email protected]>
1 parent 2820674 commit e28b0e4

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

.changeset/happy-badgers-leave.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Fixed an AppCheck issue that caused Firestore listeners to stop working and
6+
receive a "Permission Denied" error. This issue only occurred for AppCheck users
7+
that set their expiration time to under an hour.

packages/firestore/src/core/firestore_client.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ export class FirestoreClient {
9999
private readonly clientId = AutoId.newId();
100100
private authCredentialListener: CredentialChangeListener<User> = () =>
101101
Promise.resolve();
102+
private appCheckCredentialListener: (
103+
appCheckToken: string,
104+
user: User
105+
) => Promise<void> = () => Promise.resolve();
102106

103107
offlineComponents?: OfflineComponentProvider;
104108
onlineComponents?: OnlineComponentProvider;
@@ -122,8 +126,10 @@ export class FirestoreClient {
122126
await this.authCredentialListener(user);
123127
this.user = user;
124128
});
125-
// Register an empty credentials change listener to activate token refresh.
126-
this.appCheckCredentials.start(asyncQueue, () => Promise.resolve());
129+
this.appCheckCredentials.start(asyncQueue, newAppCheckToken => {
130+
logDebug(LOG_TAG, 'Received new app check token=', newAppCheckToken);
131+
return this.appCheckCredentialListener(newAppCheckToken, this.user);
132+
});
127133
}
128134

129135
async getConfiguration(): Promise<ComponentConfiguration> {
@@ -142,6 +148,12 @@ export class FirestoreClient {
142148
this.authCredentialListener = listener;
143149
}
144150

151+
setAppCheckTokenChangeListener(
152+
listener: (appCheckToken: string, user: User) => Promise<void>
153+
): void {
154+
this.appCheckCredentialListener = listener;
155+
}
156+
145157
/**
146158
* Checks that the client has not been terminated. Ensures that other methods on
147159
* this class cannot be called after the client is terminated.
@@ -234,6 +246,9 @@ export async function setOnlineComponentProvider(
234246
client.setCredentialChangeListener(user =>
235247
remoteStoreHandleCredentialChange(onlineComponentProvider.remoteStore, user)
236248
);
249+
client.setAppCheckTokenChangeListener((_, user) =>
250+
remoteStoreHandleCredentialChange(onlineComponentProvider.remoteStore, user)
251+
);
237252
client.onlineComponents = onlineComponentProvider;
238253
}
239254

0 commit comments

Comments
 (0)