Практическое руководство: авторизация

Введение

В руководстве показан процесс аутентификации и авторизации для устройств «С камеры в облако» (C2C) в проекте Frame.io. Мы рассмотрим как стандартный способ ввода кода вручную, так гораздо более удобный для пользователей способ сопряжения с помощью QR-кода.

Что потребуется?

Если вы этого еще не сделали, прочитайте руководство Перед внедрением. Вы должны были получить от нашей команды client_secret для идентификации вашей интеграции. Если нет, ознакомьтесь с введением в экосистему C2C и свяжитесь с нашей командой.

Предварительные требования для сопряжения по URL и QR-коду

Для реализации сопряжения по URL и QR-коду должны быть выполнены следующие требования:

  • Совместимость устройства: убедитесь, что ваше устройство поддерживает генерацию URL-адреса/QR-кода во время процесса сопряжения.

Прохождение процесса авторизации

Чтобы понять поток авторизации с точки зрения пользователя, обратитесь к следующим ресурсам:

Этот процесс авторизации минимизирует требования к реализации. Вам не потребуется:

  • Перенаправлять пользователей в веб-браузеры (за исключением использования сопряжения URL-кодов)
  • Обрабатывать аутентификацию пользователей Frame.io
  • Представлять интерфейсы выбора аккаунта/проекта
  • Разрабатывать сложные компоненты пользовательского интерфейса помимо базового отображения информации

Повышать удобство работы пользователей с сопряжением URL-кодов

Современным пользователям необходимо эффективное взаимодействие с устройствами. Хотя текущий процесс сопряжения вручную функционирует нормально, его можно оптимизировать.

Внедрив сопряжение с помощью URL-адреса и QR-кода — как в стриминговых сервисах, таких как Netflix или Disney+, — мы можем значительно оптимизировать процесс, снизить до минимума число ошибок ввода и сократить время сопряжения.

Идентификация устройства (client_id)

Каждому физическому устройству требуется уникальный идентификатор для отслеживания подключения в рамках проекта пользователя.

Для устройств этим идентификатором является параметр client_id, который необходим при авторизации. При реализации рассмотрите подходящие источники идентификаторов, такие как серийные номера устройств, UUID или другие уникальные строки. Если вы выполняете интеграцию на устройстве Apple, мы рекомендуем использовать уникальный постоянный UUID, который остается неизменным при перезагрузке устройства. Будьте осторожны с персональными данными. Адреса электронной почты пользователей не подходят в качестве значений client_id.

Кроме того, убедитесь, что вы контролируете идентификатор. MAC-адреса устройств не подходят, поскольку они не принадлежат вашему программному обеспечению и могут содержать персональные данные.

Если вам нужна помощь в выборе подходящего идентификатора, наша команда может помочь определить подходящее значение, которое упростит интеграцию.

Шаг 1. Запрос кода устройства

Чтобы начать реализацию, запросите код устройства через конечную точку /v2/auth/device/code:

Традиционный метод сопряжения

curl -X POST https://api.frame.io/v2/auth/device/code \
--form 'client_id=[client_id]' \
--form 'client_secret=[client_secret]' \
--form 'scope=asset_create offline' \
| python -m json.tool

Включение сопряжения через URL-код

Для сопряжения через URL-код измените вызов API, добавив дополнительные заголовки:

curl -X POST https://api.frame.io/v2/auth/device/code \
--header "x-client-version: 2.0.0" \
--header "x-client-platypus-enabled: true" \ # New header to enable URL pairing
--form 'client_id=[client_id]' \
--form 'client_secret=[client_secret]' \
--form 'scope=asset_create offline' \
| python -m json.tool

Примечание. Эти конечные точки аутентификации принимают исключительно данные форм, а не JSON. После аутентификации другие конечные точки будут принимать данные JSON, но конечные точки аутентификации будут отклонять запросы JSON.

Параметры полезной нагрузки

  • client_id: уникальный идентификатор вашего физического устройства. Он должен быть гарантированно уникальным, например серийный номер или UUID.

  • client_secret: предоставляется службой поддержки Frame.io для идентификации модели вашего устройства. Это конфиденциальное значение должно быть недоступно пользователям и храниться в зашифрованном виде.

  • scope: запрашиваемые разрешения, разделенные пробелами. Устройства могут запрашивать:

  • asset_create: разрешает создание и добавление ресурсов. * офлайн: разрешает обновление авторизации с помощью токена обновления. Без этой области пользователям потребуется повторно авторизовать свое устройство каждые 8 часов, поскольку срок действия токенов авторизации ограничен.

В практических реализациях устройства обычно запрашивают обе области.

Понимание ответа API-интерфейса

Запрос генерирует ответ, который выглядит как:

Ответ традиционного сопряжения

{
"device_code": "[device_code]",
"expires_in": 120,
"interval": 5,
"name": "MyDevice-[client_id]",
"user_code": "573131"
}

Ответ сопряжения URL

{
"device_code": "[device_code]",
"expires_in": 120,
"interval": 5,
"name": "MyDevice-[client_id]",
"user_code": "573131",
"verification_uri": "https://next.frame.io/pair",
"verification_uri_complete": "https://next.frame.io/pair/573131"
}

Разбор ответа

  • device_code: этот внутренний идентификатор должен оставаться скрытым от пользователей. Он идентифицирует запрос авторизации во время опроса.
  • expires_in: срок действия кода в секундах.
  • interval: рекомендуемый интервал опроса в секундах.
  • имя: идентификатор подключаемого устройства.
  • user_code: шестизначный код для ввода вручную в Frame.io для сопряжения устройства.
  • verification_uri: базовый URL для ввода вручную, если сканирование QR-кода недоступно.
  • verification_uri_complete: полный URL, содержащий код сопряжения и предназначенный для создания гиперссылки в мобильном приложении или генерации QR-кода для упрощения навигации пользователя к интерфейсу сопряжения.

Отображение QR-кода для пользователя

Используя verification_uri_complete, создайте и отобразите QR-код на экране устройства, чтобы пользователь мог его отсканировать. Это сделает сопряжение удобнее и эффективнее.

Пример: экран устройства с показанным QR-кодом

Пример экрана сопряжения устройства с QR-кодом Всегда предоставляйте резервные варианты: отображайте user_code и verification_uri для ввода вручную, если отсканировать QR-код невозможно. Можно также показать verification_uri в виде статического QR-кода для сканирования с мобильного устройства. Для интеграции мобильных приложений включите verification_uri_complete как действующую гиперссылку, поскольку пользователи не могут сканировать QR-коды с устройства, на котором работает приложение.

Шаг 2. Опрос для авторизации пользователя

После предоставления кода сопряжения или URL-кода проверьте ввод пользователя с помощью этого запроса:

curl -X POST https://api.frame.io/v2/auth/token \
--form 'client_id=[client_id]' \
--form 'device_code=[device_code]' \
--form 'grant_type=urn:ietf:params:oauth:grant-type:device_code' \
| python -m json.tool

Параметры полезной нагрузки

  • client_id: тот же идентификатор, который использовался в шаге 1.
  • device_code: значение device_code, возвращенное ранее.
  • grant_type: идентификатор типа разрешения OAuth, неизменно urn:ietf:params:oauth:grant-type:device_code для данной реализации.

Первоначальные попытки опроса обычно возвращают:

{
"error": "authorization_pending"
}

Эта некритическая ошибка указывает, что пользователь не завершил ввод кода. Продолжайте опрос до завершения.

Примечание для устройств под управлением iOS: если пользователь переключается на iOS-приложение Frame.io для ввода кода сопряжения, ваше приложение может перейти в фоновый режим. Когда ваше приложение снова станет активным, например в applicationDidBecomeActive, возобновите опрос, чтобы процесс авторизации продолжался, и пользователям не приходилось перезапускать сопряжение.

Если вы получаете:

{
"error": "expired_token"
}

Срок действия кода истек до ввода пользователем. Создайте новый код/QR-код, повторив шаг 1, предоставьте его пользователю и возобновите опрос.

При успешной авторизации выводится сообщение:

{
"access_token": "[access_token]",
"expires_in": 28800,
"refresh_token": "[refresh_token]",
"token_type": "bearer"
}

Поздравляем с успешной авторизацией вашего устройства «С камеры в облако»!

Рассмотрим этот ответ:

  • access_token: учетные данные аутентификации для доступа к серверной части Frame.io, необходимые в заголовках для будущих запросов API-интерфейса.
  • expires_in: срок действия токена доступа в секундах, после которого необходимо обновление.
  • refresh_token: используется для управления токенами доступа, в основном для обновления авторизации, но также применим для отзыва.
  • token_type: постоянно bearer для реализации API-интерфейса C2C , не требует действий.

Объединяем шаги

Теперь реализуем эти вызовы API-интерфейса в псевдокоде Python, обрабатывая возможное истечение срока действия кода устройства:

Python
1def authorize_with_frame():
2 """
3 Handles authorizing our device with Frame.io.
4 """
5
6 # Our client ID can be a serial number, UUID, or some other unique string.
7 client_id = THIS_DEVICE.get_serial_number()
8
9 while True:
10 # Make the call to Frame.io to get our device codes.
11 pairing_codes = c2c.get_device_codes(client_id)
12
13 # We need to keep track of how long we have been polling for
14 polling_started = datetime.now()
15
16 # Now we are going to poll for authorization until the user enters the code.
17 while True:
18
19 # Re-write this output each time we poll. Note: This message will only update once
20 # per `interval` (e.g., 5 seconds), so if a smooth countdown is desired, that will
21 # need a different implementation.
22 print(
23 f"\rPAIRING CODE: {pairing_codes.user_code}, "
24 f"EXPIRES IN: {pairing_codes.expires_in - (datetime.now() - polling_started).seconds} seconds"
25 )
26
27 # Wait for `interval` before polling each time.
28 sleep(pairing_codes.interval)
29
30 # Make a call to Frame.io to see if the user has entered the code and authorized
31 # the device.
32 authorization, error = c2c.poll_for_authorization(
33 client_id, pairing_codes.device_code
34 )
35
36 if error and error.message == "authorization_pending":
37 # If the authorization is pending, try again.
38 continue
39 elif error and error.message == "expired_token":
40 # If the pairing codes have expired, break to generate new codes.
41 break
42 elif error:
43 # If there was some other error, raise it.
44 raise error
45 else:
46 # If there was no error, we have our authorization!
47 return authorization
48
49 # If we get here, our pairing codes expired. Let's try again.
50 print("\nPairing code expired. Generating a new one...")

Примечание. Внешний цикл обрабатывает случаи, когда срок действия кодов сопряжения истекает и требуются новые коды.

На последнем шаге извлеките и отобразите информацию о проекте из Frame.io для подтверждения успешного сопряжения с намеченным проектом. Мы рассмотрим это в следующем руководстве.

Создание и отображение QR-кодов для сопряжения

При реализации сопряжения по URL/QR-коду вам потребуется cоздать QR-код из значения verification_uri_complete в ответе. Вот примеры с использованием популярных библиотек на разных языках программирования:

Пример на Python с использованием qrcode

Python
1import qrcode
2from PIL import Image
3import io
4
5def generate_qr_code(verification_uri_complete, size=250):
6 """
7 Generate a QR code from the verification_uri_complete URL.
8
9 Args:
10 verification_uri_complete (str): The complete verification URI returned by Frame.io
11 size (int, optional): Size of the QR code in pixels. Defaults to 250.
12
13 Returns:
14 PIL.Image: QR code image that can be displayed or saved
15 """
16 qr = qrcode.QRCode(
17 version=1,
18 error_correction=qrcode.constants.ERROR_CORRECT_L,
19 box_size=10,
20 border=4,
21 )
22 qr.add_data(verification_uri_complete)
23 qr.make(fit=True)
24
25 img = qr.make_image(fill_color="black", back_color="white")
26
27 # Resize the image if needed
28 img = img.resize((size, size))
29 return img
30
31# Example usage in authorization flow
32def display_qr_for_pairing(pairing_codes):
33 """
34 Generate and display QR code along with manual pairing instructions.
35 """
36 if hasattr(pairing_codes, 'verification_uri_complete'):
37 # Generate QR code from the verification URI
38 qr_img = generate_qr_code(pairing_codes.verification_uri_complete)
39
40 # Display the QR code on screen
41 # For GUI applications like Tkinter, PyQt, etc.
42 # display_image(qr_img)
43
44 # For headless devices or testing, save to file
45 qr_img.save("frame_io_pairing_qr.png")
46
47 print(f"Scan the QR code or visit: {pairing_codes.verification_uri}")
48 print(f"Manual code: {pairing_codes.user_code}")
49 else:
50 # Fallback for devices that received traditional pairing response
51 print(f"Enter code on Frame.io: {pairing_codes.user_code}")

Пример на JavaScript (веб-версия или Electron)

1import QRCode from 'qrcode';
2
3/**
4 * Generate and display a QR code from the verification URI
5 * @param {string} verificationUriComplete - The complete verification URI from Frame.io
6 * @param {string} elementId - ID of the HTML element to display the QR code in
7 */
8function displayQRCode(verificationUriComplete, elementId = 'qrcode-container') {
9 const element = document.getElementById(elementId);
10
11 if (!element) {
12 console.error(`Element with ID ${elementId} not found`);
13 return;
14 }
15
16 // Clear any existing content
17 element.innerHTML = '';
18
19 // Generate QR code
20 QRCode.toCanvas(element, verificationUriComplete, { width: 250 }, function(error) {
21 if (error) {
22 console.error('Error generating QR code:', error);
23 // Fallback to displaying the URL as a link
24 element.innerHTML = `<a href="${verificationUriComplete}" target="_blank">Click here to pair</a>`;
25 }
26 });
27
28 // Also display manual pairing information
29 const manualInfoDiv = document.createElement('div');
30 manualInfoDiv.innerHTML = `
31 <p>Scan the QR code or <a href="${verificationUriComplete}" target="_blank">click here</a> to pair your device.</p>
32 <p>Manual code: ${userCode}</p>
33 `;
34 element.parentNode.appendChild(manualInfoDiv);
35}
36
37// Example usage in authorization flow
38async function requestDeviceCode() {
39 try {
40 const response = await fetch('https://api.frame.io/v2/auth/device/code', {
41 method: 'POST',
42 headers: {
43 'x-client-version': '2.0.0',
44 'x-client-platypus-enabled': 'true'
45 },
46 body: new URLSearchParams({
47 'client_id': YOUR_CLIENT_ID,
48 'client_secret': YOUR_CLIENT_SECRET,
49 'scope': 'asset_create offline'
50 })
51 });
52
53 const data = await response.json();
54
55 if (data.verification_uri_complete) {
56 displayQRCode(data.verification_uri_complete);
57 window.userCode = data.user_code; // Store for display purposes
58 } else {
59 // Fallback for traditional pairing
60 displayManualPairingCode(data.user_code);
61 }
62
63 // Begin polling for authorization
64 beginPollingForAuthorization(data.device_code, data.interval);
65
66 } catch (error) {
67 console.error('Error requesting device code:', error);
68 }
69}

Пример для Android (Java)

1import android.graphics.Bitmap;
2import android.widget.ImageView;
3import com.google.zxing.BarcodeFormat;
4import com.google.zxing.MultiFormatWriter;
5import com.google.zxing.common.BitMatrix;
6import com.journeyapps.barcodescanner.BarcodeEncoder;
7
8public void generateAndDisplayQRCode(String verificationUriComplete, ImageView qrCodeImageView) {
9 try {
10 MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
11 BitMatrix bitMatrix = multiFormatWriter.encode(verificationUriComplete,
12 BarcodeFormat.QR_CODE, 250, 250);
13 BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
14 Bitmap bitmap = barcodeEncoder.createBitmap(bitMatrix);
15
16 // Display in ImageView
17 qrCodeImageView.setImageBitmap(bitmap);
18
19 } catch (Exception e) {
20 e.printStackTrace();
21 // Fallback to displaying the URL as text
22 }
23}

Пример для iOS (Swift)

1import UIKit
2import CoreImage
3
4func generateQRCode(from string: String) -> UIImage? {
5 let data = string.data(using: String.Encoding.utf8)
6
7 if let filter = CIFilter(name: "CIQRCodeGenerator") {
8 filter.setValue(data, forKey: "inputMessage")
9 filter.setValue("H", forKey: "inputCorrectionLevel")
10
11 if let outputImage = filter.outputImage {
12 // Scale the image
13 let transform = CGAffineTransform(scaleX: 10, y: 10)
14 let scaledImage = outputImage.transformed(by: transform)
15
16 // Convert to UIImage
17 let context = CIContext()
18 if let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) {
19 return UIImage(cgImage: cgImage)
20 }
21 }
22 }
23
24 return nil
25}
26
27// Usage in your view controller
28func displayPairingQRCode(verificationUriComplete: String) {
29 if let qrCodeImage = generateQRCode(from: verificationUriComplete) {
30 qrCodeImageView.image = qrCodeImage
31
32 // Also show manual pairing information
33 pairingInstructionsLabel.text = "Scan the QR code or enter code manually"
34 pairingCodeLabel.text = userCode
35 } else {
36 // Fallback to manual code display
37 pairingInstructionsLabel.text = "Enter this code on Frame.io:"
38 pairingCodeLabel.text = userCode
39 }
40}

Лучшие практики для отображения QR-кодов

При реализации сопряжения через QR-код учитывайте эти рекомендации, чтобы сделать работу пользователей удобнее:

  1. Оптимальный размер. Отображайте QR-коды размером не менее 200–250 пикселей по каждой стороне для надежного сканирования.

  2. Контрастность. Необходима высокая контрастность между QR-кодом и фоном (идеальный вариант — черный на белом).

  3. Исправление ошибок. Используйте умеренные уровни исправления ошибок (L или M), чтобы обеспечить баланс между плотностью кода и надежностью.

  4. Четкие инструкции. Давайте четкие указания по сканированию кода, например «Для сопряжения устройства отсканируйте этот код камерой вашего смартфона».

  5. Несколько вариантов. В качестве резервного варианта всегда предоставляйте вместе с QR-кодом код для сопряжения вручную:

Scan to pair:
[QR CODE]
Or enter code manually: 573131
  1. Гиперссылка для мобильных приложений. Если ваша интеграция — это мобильное приложение, включите verification_uri_complete как действующую гиперссылку, поскольку пользователи не могут отсканировать QR-код с того же устройства.

  2. Тестирование. Протестируйте QR-коды с различными устройствами и в разных условиях освещения, чтобы гарантировать надежное сканирование.

Пример отображения QR-кода

Поиск и устранение неисправностей

Если возникают проблемы, ознакомьтесь со следующими распространенными сценариями и вариантами решения проблем.

  • Кнопка «Подключить устройство» не отображается. При доступе к панели управления C2C это может указывать на:

  • Отсутствие необходимых разрешений. Если вы видите сообщение, касающееся разрешений, обратитесь к менеджеру учетной записи для получения разрешений или назначения соответствующей роли. * Существующее подключение устройства. После подключения одного устройства вместо первоначальной кнопки «Добавить новое устройство» появляется меню с тремя точками в правом верхнем углу панели «Подключения C2C».

  • Неверный клиент. Ответ invalid_client указывает на несоответствие информации об устройстве, обычно из-за неправильного client_secret.

  • Неправильный запрос. Ответ bad_request указывает на неправильно сформированные данные запроса. Проверьте имена полей и убедитесь, что включены все обязательные поля.

Если ваша проблема здесь не описана, поделитесь с нами своим опытом, чтобы мы могли улучшить раздел, посвященный устранению неполадок.

Дальнейшие шаги

Мы рекомендуем вам связаться с нашей командой и перейти к руководству по управлению авторизацией. Мы ждем ваших отзывов!