pollForCompletion method

Future<void> pollForCompletion(
  1. DeviceCodeChallenge challenge
)

Implementation

Future<void> pollForCompletion(DeviceCodeChallenge challenge) async {
  final deadline = DateTime.now().add(_pollTimeout);

  while (DateTime.now().isBefore(deadline)) {
    await Future.delayed(Duration(seconds: challenge.intervalSeconds));

    try {
      final response = await _dio.post(
        '$_issuer/api/accounts/deviceauth/token',
        options: Options(
          headers: {'content-type': 'application/json'},
          validateStatus: (status) => status != null && status < 500,
        ),
        data: {
          'device_auth_id': challenge.deviceAuthId,
          'user_code': challenge.userCode,
        },
      );

      debugPrint('[OpenAiAuth] Poll status=${response.statusCode}');

      if (response.statusCode == 403 || response.statusCode == 404) {
        continue;
      }

      if (response.statusCode != null &&
          response.statusCode! >= 200 &&
          response.statusCode! < 300) {
        final data = response.data as Map<String, dynamic>;
        debugPrint('[OpenAiAuth] Poll success keys=${data.keys.toList()}');

        final authCode = data['authorization_code'] as String;
        final codeVerifier = data['code_verifier'] as String;

        await _exchangeCodeForTokens(authCode, codeVerifier);
        return;
      }

      throw Exception('Device auth poll failed: HTTP ${response.statusCode}');
    } on DioException catch (e) {
      if (e.response?.statusCode == 403 || e.response?.statusCode == 404) {
        continue;
      }
      rethrow;
    }
  }

  throw Exception('Device code sign-in timed out (15 minutes).');
}