feat: add sign-in flow for crossOriginIsolated contexts#3253
Conversation
Salazareo
left a comment
There was a problem hiding this comment.
So the general idea is right, but this would be creating 1 new channel per request, which might get expensive like we talked about in the call.
I think the better approach for our backend architecture would be to expand BroadcastService to relay outer.pubsub.* events through one dedicated channel.
the general logic would be that you'd set up a channel on boot for all nodes connected to a given redis instance
class BroadcastService {
#redisChannel = 'broadcast:pubsub';
// whatever else
#redisRelayKeys = ['outer.pubsub', 'pubsub'] // for peers and local if needed
#redisSub: ReturnType<typeof this.clients.redis.duplicate> | null = null;
#subscribeRedisOutbound(){
// redis sub and register handler to relay via event client, see the webhook path
// note youll probably need some random uuid based dedup
this.redisSub = someSub;
}
override onServerStart(): void {
this.#loadConfig();
this.#subscribeOutbound(); // existing webhook path
this.#subscribeRedisOutbound(); // local bus -> Redis publish
}
override async onServerPrepareShutdown(): Promise<void> {
// ...existing flush code...
if (this.#redisSub) {
try {
await this.#redisSub.unsubscribe(this.#redisChannel);
await this.#redisSub.quit();
} catch (err) {
console.warn('[broadcast] redis sub teardown failed', err);
}
this.#redisSub = null;
}
}
}Note: im suggesting both outer.pubsub, and pubsub in case you want just regional support for this, you might not need this however
with that you could do something like this to listen to an event in one endpoint
// 'outer.' gets stripped when digested IIRC
this.clients.event.on(`pubsub.login.${someKey}`, (data,meta) => {
resolve(data.whatever)
});
const result = await promise;
// do whatever
this.clients.event.clearListener(`outer.pubsub.login.${someKey}`); // TODO: implement this clearListenerand do something like this on the other end to emit it
this.clients.event.emit(`outer.pubsub.login.${someKey}`);Let me know if any of this doesn't make sense happy to sync on it
| if (!token) { | ||
| const subscriber = this.clients.redis.duplicate(); | ||
|
|
||
| token = await new Promise<string | null>(async (resolve) => { |
There was a problem hiding this comment.
nit: can probably do to make it easier to read
const {resolve, promise, reject} = Promise.withResolver();
callEvent(()=>... resolve());
await promise;| const subscriber = this.clients.redis.duplicate(); | ||
|
|
||
| token = await new Promise<string | null>(async (resolve) => { | ||
| const timeout = setTimeout(() => resolve(null), 10000); |
There was a problem hiding this comment.
nit: can probably use Promise.race(promise,timeoutPromise)
adds an alternative to the postMessage auth flow for puterjs that works when cross origin isolated