Various AT Protocol integrations with obsidian
20
fork

Configure Feed

Select the types of activity you want to include in your feed.

test preventing race with token exchange timing

+27
+10
manifest-beta.json
··· 1 + { 2 + "id": "atmosphere", 3 + "name": "Atmosphere", 4 + "version": "0.1.16-beta.1", 5 + "minAppVersion": "0.15.0", 6 + "description": "Various integrations with AT Protocol.", 7 + "author": "treethought", 8 + "authorUrl": "https://github.com/treethought", 9 + "isDesktopOnly": false 10 + }
+2
src/lib/oauth/oauth.ts
··· 65 65 new Notice('Continue login in the browser'); 66 66 67 67 const params = await waitForCallback; 68 + await new Promise((resolve) => setTimeout(resolve, 300)); 69 + 68 70 const { session } = await finalizeAuthorization(params); 69 71 return session; 70 72 }
+15
src/main.ts
··· 16 16 this.client = new ATClient(); 17 17 this.clipper = new Clipper(this); 18 18 19 + // prevent duplicate handling 20 + const processedStates = new Set<string>(); 21 + 19 22 this.registerObsidianProtocolHandler('atmosphere-oauth', (params) => { 20 23 try { 24 + const state = params.state as string; 25 + 26 + if (state && processedStates.has(state)) { 27 + console.log('[OAuth] Ignoring duplicate callback for state:', state); 28 + return; 29 + } 30 + 21 31 const urlParams = new URLSearchParams(); 22 32 for (const [key, value] of Object.entries(params)) { 23 33 if (value) { 24 34 urlParams.set(key, String(value)); 25 35 } 26 36 } 37 + if (state) { 38 + processedStates.add(state); 39 + setTimeout(() => processedStates.delete(state), 2 * 60_000); 40 + } 41 + 27 42 this.client.handleOAuthCallback(urlParams); 28 43 new Notice('Authentication completed! Processing...'); 29 44 } catch (error) {