| 224 | }; |
| 225 | |
| 226 | export const requestDeviceCode = async ( |
| 227 | discovery: CliLoginDiscovery, |
| 228 | options: DeviceLoginHttpOptions = {}, |
| 229 | ): Promise<DeviceCodeGrant> => { |
| 230 | const response = await post( |
| 231 | discovery.deviceAuthorizationEndpoint, |
| 232 | { client_id: discovery.clientId, scope: discovery.scope }, |
| 233 | discovery.requestFormat, |
| 234 | options, |
| 235 | ); |
| 236 | const body = await readJson(response); |
| 237 | if (!response.ok) { |
| 238 | throw new DeviceLoginError( |
| 239 | `Device authorization failed (${response.status}): ${asString(body.error_description) ?? asString(body.error) ?? "unknown error"}`, |
| 240 | ); |
| 241 | } |
| 242 | const deviceCode = asString(body.device_code); |
| 243 | const userCode = asString(body.user_code); |
| 244 | const verificationUri = asString(body.verification_uri); |
| 245 | if (!deviceCode || !userCode || !verificationUri) { |
| 246 | throw new DeviceLoginError("Device authorization response was missing required fields."); |
| 247 | } |
| 248 | return { |
| 249 | deviceCode, |
| 250 | userCode, |
| 251 | verificationUri, |
| 252 | verificationUriComplete: asString(body.verification_uri_complete), |
| 253 | expiresInSeconds: asNumber(body.expires_in) ?? 300, |
| 254 | intervalSeconds: asNumber(body.interval) ?? DEFAULT_INTERVAL_SECONDS, |
| 255 | }; |
| 256 | }; |
| 257 | |
| 258 | const sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms)); |
| 259 | |