( baseUrl: string, clientId: string, deviceCode: string )
| 186 | } |
| 187 | |
| 188 | export async function pollDeviceToken( |
| 189 | baseUrl: string, |
| 190 | clientId: string, |
| 191 | deviceCode: string |
| 192 | ): Promise<PollDeviceTokenResult> { |
| 193 | let response: Response; |
| 194 | try { |
| 195 | response = await fetch(`${baseUrl}/api/oauth/device/token`, { |
| 196 | method: "POST", |
| 197 | headers: { "Content-Type": "application/x-www-form-urlencoded" }, |
| 198 | body: new URLSearchParams({ |
| 199 | grant_type: DEVICE_CODE_GRANT, |
| 200 | device_code: deviceCode, |
| 201 | client_id: clientId, |
| 202 | }).toString(), |
| 203 | }); |
| 204 | } catch (error) { |
| 205 | // Network blip — keep polling. |
| 206 | return { |
| 207 | status: "transient", |
| 208 | errorMessage: error instanceof Error ? error.message : "network error", |
| 209 | }; |
| 210 | } |
| 211 | |
| 212 | if (response.ok) { |
| 213 | const tokens = (await response.json()) as TokenData; |
| 214 | return { status: "approved", tokens }; |
| 215 | } |
| 216 | |
| 217 | // Treat any 5xx as transient so a flaky backend doesn't end the user's session. |
| 218 | if (response.status >= 500) { |
| 219 | const err = (await response.json().catch(() => ({}))) as TokenErrorResponse; |
| 220 | return { |
| 221 | status: "transient", |
| 222 | errorMessage: err.error_description || err.error || `HTTP ${response.status}`, |
| 223 | }; |
| 224 | } |
| 225 | |
| 226 | const err = (await response.json().catch(() => ({}))) as TokenErrorResponse; |
| 227 | switch (err.error) { |
| 228 | case "authorization_pending": |
| 229 | return { status: "pending" }; |
| 230 | case "slow_down": |
| 231 | return { status: "slow_down" }; |
| 232 | case "access_denied": |
| 233 | return { status: "denied" }; |
| 234 | case "expired_token": |
| 235 | return { status: "expired" }; |
| 236 | default: |
| 237 | throw new Error(err.error_description || err.error || "Device token poll failed"); |
| 238 | } |
| 239 | } |
no outgoing calls
no test coverage detected