Commit fb439c9
authored
fix(mcp): deliver OAuth callback result over BroadcastChannel so COOP can't strand the connect (#5767)
* fix(mcp): deliver OAuth callback result over BroadcastChannel so COOP can't strand the connect
An MCP provider whose authorization page sets `Cross-Origin-Opener-Policy:
same-origin` (e.g. Gauge) severs `window.opener` when the popup navigates
through it, so the callback's `window.opener.postMessage` was silently lost and
the row hung on "Connecting…" forever — even when the callback succeeded.
- Signal completion over a same-origin `BroadcastChannel` instead, which is
origin-scoped and immune to opener severance (the MDN/Chrome-recommended COOP
workaround). Scope the message by workspaceId so other open workspaces ignore it.
- Log every OAuth callback failure with its reason + serverId. The early-return
gates previously returned a silent `ok:false` popup close, so a failed
authorization was undiagnosable from the server logs.
* fix(mcp): react to the OAuth broadcast only in the tab that opened the popup
A BroadcastChannel reaches every same-origin tab, so the previous workspace-id
scoping (which the success path carried but failure paths omitted) still let
unrelated tabs clear state, refetch, and show spurious toasts. Gate every
reaction on whether this tab actually has an in-flight popup for the result's
server (`popupIntervalsRef`) — strictly more precise than workspace scoping and
correct for both cross-workspace and same-workspace-second-tab cases. Removes
the now-redundant workspaceId from the callback message.
* fix(mcp): decouple OAuth result correlation from popup.closed
Cursor flagged two defects in the previous gate, both rooted in keying the
BroadcastChannel filter on `popupIntervalsRef` (the popup.closed poll map):
- A genuine completion was dropped whenever the poll had already removed the
server's entry — and COOP can make `popup.closed` misreport, which is exactly
the case this PR targets, so the fix could silently fail to apply.
- A result without a serverId fell back to "any in-flight popup", waking
unrelated same-origin tabs with spurious toasts/refetches.
Introduce `pendingFlowsRef` (serverId -> safety timeout) as the correlation
source of truth: cleared only on completion or a 10-min timeout (matching the
server OAuth start TTL), never by popup.closed. The popup.closed poll now only
clears the spinner (best-effort abandon UX) and never touches correlation, so a
real completion is always processed. Results without a serverId are ignored;
the initiating tab's safety timeout clears its own "Connecting…".
* fix(mcp): correlate the OAuth result on the state nonce, not serverId
Cursor flagged that a failure which can't resolve a serverId (notably
invalid_state) broadcasts ok:false with no serverId, so the serverId-keyed gate
ignored it and the initiating tab sat on "Connecting…" until the safety timeout
with no error feedback.
Correlate on the OAuth `state` instead — the per-flow nonce the callback echoes
on every result, success or failure. The client parses it from the authorization
URL and keys the in-flight map by it; the callback includes it on every response
via a `respond` helper. This is the canonical popup-OAuth correlation: it reaches
the initiating tab even when no serverId exists, and — because each flow has a
unique state — it also fixes the same-user-same-server-in-two-tabs edge a serverId
key left open. Results with no parseable state (a malformed callback) are still
ignored; that flow clears via its timeout.
* fix(mcp): drop a server's prior in-flight OAuth flow when it is retried
Each start mints a new `state`, so an abandoned attempt's safety timeout was
keyed under a different state than its retry and never cleared. In the contrived
case where both stayed pending ~10 min, the stale timer would clear the newer
flow's spinner. Sweep any prior in-flight flow for the same serverId on a new
start (replacing the can't-happen same-state check). Result delivery was already
correct; this makes the state machine airtight.1 parent e337308 commit fb439c9
5 files changed
Lines changed: 205 additions & 86 deletions
File tree
- apps/sim
- app/api/mcp/oauth/callback
- hooks
- mcp
- queries
- lib/mcp/oauth
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
75 | 116 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | | - | |
| 46 | + | |
| 47 | + | |
47 | 48 | | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
48 | 54 | | |
49 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
50 | 62 | | |
51 | | - | |
| 63 | + | |
52 | 64 | | |
53 | 65 | | |
54 | 66 | | |
| |||
63 | 75 | | |
64 | 76 | | |
65 | 77 | | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
66 | 88 | | |
67 | 89 | | |
68 | 90 | | |
69 | 91 | | |
70 | 92 | | |
71 | 93 | | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
| 94 | + | |
78 | 95 | | |
79 | 96 | | |
80 | | - | |
| 97 | + | |
81 | 98 | | |
82 | 99 | | |
83 | 100 | | |
| |||
89 | 106 | | |
90 | 107 | | |
91 | 108 | | |
92 | | - | |
| 109 | + | |
93 | 110 | | |
94 | 111 | | |
95 | 112 | | |
| |||
99 | 116 | | |
100 | 117 | | |
101 | 118 | | |
102 | | - | |
| 119 | + | |
103 | 120 | | |
104 | 121 | | |
105 | 122 | | |
106 | 123 | | |
107 | | - | |
| 124 | + | |
108 | 125 | | |
109 | 126 | | |
110 | 127 | | |
| |||
118 | 135 | | |
119 | 136 | | |
120 | 137 | | |
121 | | - | |
| 138 | + | |
122 | 139 | | |
123 | 140 | | |
124 | | - | |
| 141 | + | |
125 | 142 | | |
126 | 143 | | |
127 | 144 | | |
| |||
131 | 148 | | |
132 | 149 | | |
133 | 150 | | |
134 | | - | |
| 151 | + | |
135 | 152 | | |
136 | 153 | | |
137 | 154 | | |
| |||
152 | 169 | | |
153 | 170 | | |
154 | 171 | | |
155 | | - | |
| 172 | + | |
156 | 173 | | |
157 | 174 | | |
158 | 175 | | |
| |||
163 | 180 | | |
164 | 181 | | |
165 | 182 | | |
166 | | - | |
| 183 | + | |
167 | 184 | | |
168 | 185 | | |
169 | 186 | | |
| |||
173 | 190 | | |
174 | 191 | | |
175 | 192 | | |
176 | | - | |
| 193 | + | |
177 | 194 | | |
178 | 195 | | |
179 | | - | |
| 196 | + | |
180 | 197 | | |
181 | 198 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
40 | 47 | | |
41 | 48 | | |
42 | 49 | | |
43 | 50 | | |
44 | 51 | | |
45 | | - | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
46 | 91 | | |
47 | 92 | | |
48 | | - | |
| 93 | + | |
| 94 | + | |
49 | 95 | | |
50 | | - | |
51 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
52 | 100 | | |
53 | 101 | | |
54 | 102 | | |
55 | 103 | | |
56 | | - | |
57 | | - | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
58 | 110 | | |
59 | 111 | | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
79 | | - | |
80 | | - | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
81 | 120 | | |
82 | 121 | | |
83 | | - | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
92 | 125 | | |
93 | 126 | | |
94 | 127 | | |
95 | 128 | | |
96 | 129 | | |
97 | 130 | | |
98 | | - | |
99 | | - | |
100 | | - | |
| 131 | + | |
| 132 | + | |
101 | 133 | | |
102 | 134 | | |
103 | 135 | | |
104 | 136 | | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | 137 | | |
118 | 138 | | |
119 | 139 | | |
120 | | - | |
| 140 | + | |
121 | 141 | | |
122 | 142 | | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
130 | 172 | | |
131 | | - | |
| 173 | + | |
| 174 | + | |
132 | 175 | | |
133 | 176 | | |
134 | 177 | | |
135 | 178 | | |
136 | | - | |
| 179 | + | |
137 | 180 | | |
138 | 181 | | |
139 | 182 | | |
| |||
0 commit comments