方法:認証

はじめに

このガイドでは、Frame.io プロジェクト上の Camera to Cloud(C2C)デバイスの認証および認可プロセスについて説明します。標準的な手動コード入力方法と、最適なユーザーエクスペリエンスを実現するための強化された QR コードペアリング方法の両方について説明します。

必要なもの

まだご覧になっていない場合は、実装を開始する前にガイドを参照してください。

統合を特定するために、当社チームから既に client_secret を受け取っているはずです。受け取っていない場合は、C2C エコシステムの概要を参照し、当社チームにお問い合わせください。

URL と QR コードのペアリングの前提条件

URL と QR コードのペアリングを実装するには、次の要件を満たしていることを確認してください。

  • デバイスの互換性:お使いのデバイスが、ペアリングプロセス中の URL/QR コード生成をサポートしていることを確認します。

認証フローの説明

ユーザーの観点から認証フローを理解するには、次のリソースを参照してください。

この認証プロセスを実行することで、実装要件が最小限に抑えられます。次の操作は不要です。

  • Web ブラウザーへのリダイレクト(URL コードペアリングを使用しない場合)
  • Frame.io ユーザー認証の処理
  • アカウント/プロジェクト選択インターフェイスの提示
  • 基本的な情報表示にとどまらない複雑な UI 要素の開発

URL コードペアリングによるユーザーエクスペリエンスの向上

現代のユーザーは、効率的なデバイス操作を期待しています。最新の手動ペアリングプロセスは適切に機能しますが、最適化することができます。

Netflix や Disney+ などのストリーミングサービスと同様に、URL と QR コードのペアリングを実装することで、プロセスを大幅に合理化し、入力エラーを最小限に抑え、ペアリング時間を短縮できます。

デバイス ID(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:アセットの作成とアップロードを有効にします。
    • offline:リフレッシュトークンによる認証の更新を許可します。このスコープがない場合、認証トークンの有効期限が切れると、ユーザーは 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:推奨されるポーリング間隔(秒単位)。
  • name:接続デバイスの識別子。
  • user_code:デバイスペアリングのために Frame.io に手動で入力する 6 桁のコード。
  • verification_uri:QR スキャンが使用できない場合の手動入力のベース URL。
  • verification_uri_complete:ペアリングインターフェイスへのユーザーナビゲーションを簡素化するために、モバイルアプリ内でのハイパーリンクまたは QR コード生成を目的とした、ペアリングコードを含む完全な URL。

ユーザーへの QR コードの表示

verification_uri_complete を使用して、QR コードを生成してデバイス画面に表示し、ユーザーがスキャンできるようにして、効率的なペアリングを促します。

例:QR コードが表示されたデバイス画面

デバイスの QR コードペアリング画面の例

万一の場合に備えたオプションを必ず用意してください。QR スキャンができない場合は、手入力用に user_codeverification_uri を表示します。または、verification_uri をモバイルスキャン用の静的 QR コードとして表示することを検討してください。

モバイルアプリ統合の場合、ユーザーはアプリ実行中のデバイスから QR コードをスキャンできないので、verification_uri_complete をタップ可能なハイパーリンクとして含めます。

手順 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"
}

この致命的でないエラーは、ユーザーがコード入力を完了していないことを示します。完了するまでポーリングを続行します。

次のメッセージが表示される場合:

{
"error": "expired_token"
}

ユーザー入力前にコードの有効期限が切れました。ステップ 1 で新しいコード/QR コードを生成し、ユーザーに提示して、ポーリングを再開します。

認証に成功すると、以下が表示されます。

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

Camera to Cloud デバイスの認証が正常に完了しました。

この応答を確認しましょう。

  • access_token:Frame.io バックエンドアクセスの認証資格情報。今後の API 要求のヘッダーに必要です。
  • expires_in:アクセストークンの有効期間(秒単位)。この期間を過ぎると更新が必要になります。
  • refresh_token:アクセストークン管理に使用されます。主に認証の更新に使用されますが、失効にも適用されます。
  • token_type:C2C API 実装は bearer で一貫しており、アクションは不要です。

ステップのまとめ

次に、これらの 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 コードのペアリングを実装する場合は、応答の verification_uri_complete 値から QR コードを生成する必要があります。以下に、様々なプログラミング言語で一般的なライブラリを使用する例を示します。

qrcode を使用した Python の例

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 の例(Web または 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
  6. モバイルアプリのハイパーリンク:統合がモバイルアプリケーションの場合、ユーザーは同じデバイスから QR コードをスキャンできないため、verification_uri_complete をタップ可能なリンクとして含めます。

  7. テスト:様々なデバイスと照明条件で QR コードをテストして、信頼性の高いスキャンを確保します。

QR コード表示の例

トラブルシューティング

問題が発生した場合は、次の一般的なシナリオと解決策を参照してください。

  • 「Connect Device」ボタンが表示されない:C2C 管理パネルにアクセスすると、次のことが示されます。
    • 権限が不十分:権限メッセージが表示された場合は、アカウントマネージャーに連絡して権限を調整するか、適切なロールを割り当ててください。
    • 既存のデバイス接続:1 つのデバイスを接続すると、プライマリの「Add New Device」ボタンが、C2C Connections パネルの右上隅にある 3 つのドットメニューに変わります。
  • 無効なクライアントエラーinvalid_client 応答は、通常誤った client_secret によるデバイス情報の不一致を示します。
  • 不正な要求エラーbad_request 応答は、不正な形式の要求データを示しています。フィールド名を確認し、すべての必須フィールドが含まれていることを確認します。

上記の方法で問題が解決されない場合は、このトラブルシューティングセクションを改善するために、お客様の体験を共有してください。

次のステップ

当社チームまでお問い合わせください。その後、認証管理ガイドにお進みください。お客様のご意見をお待ちしております。