Comment faire : Autoriser (Application)

Introduction

Dans ce Guide, nous allons apprendre comment authentifier et autoriser une application C2C sur un projet Frame.io.

De quoi aurai-je besoin ?

Si vous n’avez pas lu le guide Implémentation C2C : Configuration, jetez-y un coup d’œil rapide avant de continuer !De plus, vous devriez avoir reçu un client_id de notre équipe qui sera utilisé pour identifier votre intégration.Si vous n’avez pas reçu de client_id, consultez cette introduction au réseau C2C et contactez notre équipe.Si vous avez reçu un client_secret au lieu d’un client_id, nous vous avons configuré comme appareil matériel plutôt qu’comme application C2C, et vous voudrez soit suivre le guide d’authentification d’appareil matériel soit contacter notre équipe pour qu’un client_id vous soit attribué à la place.

Présentation du flux d’authentification d’application

Assurons-nous d’avoir une compréhension globale de l’expérience client attendue pour le flux d’autorisation que nous voulons implémenter.Consultez les ressources suivantes pour voir ce flux du point de vue de l’utilisateur, essayez de télécharger Zoelog et de vous connecter à Frame.io pour vous familiariser avec le processus d’autorisation des applications C2C !

Présentation OAuth

Les applications C2C utilisent un flux OAuth 2.0 pour l’authentification et l’autorisation.Il s’agit d’un ensemble standardisé d’appels qui peut être utilisé pour authentifier et autoriser une application ou un utilisateur tiers pour un service.Vous pouvez en savoir plus sur le flux OAuth ici.

Les URI de rappel / redirection

Dans le cadre du flux OAuth, nos serveurs devront effectuer un appel HTTP vers une URI / URL que vous contrôlez.Après qu’un utilisateur se soit connecté à Frame.io dans son navigateur, nous redirigerons le navigateur vers cette URI pour fournir à votre appli certaines informations.Votre URI de redirection doit être :

  • Vous appartenir
  • Statique

Vous pouvez avoir plusieurs redirections valides enregistrées pour votre appareil tant qu’elles respectent ces deux critères.

Pendant le flux OAuth, nous vérifierons que l’URI de rappel demandée par votre application est l’une des URI que nous avons dans nos dossiers.Si ce n’est pas le cas, le flux d’autorisation échouera. Si nous n’effectuions pas cette vérification, un acteur malveillant pourrait fournir une redirection vers une adresse qu’il contrôle.

À des fins de développement, nous prenons en charge les rappels non HTTPS sur http://localhost.

Identification de l’appareil

Lors de la connexion à Camera to Cloud, chaque installation d’application individuelle devra s’identifier de manière unique, afin que nous puissions répertorier les connexions d’appareil dans le Projet d’un utilisateur.

Pour les applications C2C, nous appelons cela le device_id de l’appareil. Lors de la configuration de votre implémentation, vous devez réfléchir à la façon dont vous souhaitez procéder. Certaines plateformes offrent une API pour générer un identifiant spécifique à l’appareil et à l’application pour ce cas d’usage précis :

PLATEFORMERÉFÉRENCE
iOSidentifierForVendor
AndroidFID ou GUID
Veillez à ne pas divulguer d'informations personnellement identifiables

L’e-mail de l’Utilisateur, par exemple, n’est pas une Valeur valide à utiliser comme device_id. De même, assurez-vous de posséder l’identifiant unique. N’utilisez pas l’adresse MAC de l’appareil, par exemple. L’adresse MAC n’appartient pas à votre logiciel et pourrait également être considérée comme une information personnellement identifiable.

Si vous n’êtes pas sûr de la Valeur que vous souhaitez utiliser, nous pouvons discuter de ce choix ensemble et nous assurer qu’une Valeur appropriée est choisie pour rendre l’intégration aussi facile que possible.

Étape 1 : Authentification de l’Utilisateur

Lorsque je décide de me connecter à Frame.io dans YourApp™, je vais dans la section de configuration Frame.io et je sélectionne « Se connecter au Projet » (ou quelque chose de similaire). Lorsque j’appuie sur le bouton, je suis redirigé vers Frame.io pour me connecter et autoriser l’Application.

Nous faisons cela en créant une URL et en l’ouvrant dans un navigateur web. Examinons un pseudocode de type Python :

Python
1def redirect_to_auth(config):
2 credentials = {
3 "response_type": "code",
4 "redirect_uri": "http://MyApp.io/frameio-callback",
5 "client_id": f"{MYAPP.client_id}",
6 "scope": "offline device.connect asset.create",
7 "state": str(uuid.uuid4()),
8 "device_id": f"{HARDWARE.get_vendor_id('com.mycompany.myapp')}",
9 }
10
11 encoded = parse.urlencode(credentials)
12 url = "https://applications.frame.io/oauth2/auth?" + encoded
13
14 webbrowser.open(url)

Notre « charge utile » est encodée dans l’URL elle-même, et lorsqu’elle est entièrement encodée, l’URL ressemblera à ceci :

https://applications.frame.io/oauth2/auth?response_type=code&redirect_uri=http%3A%2F%2FMyApp.io%2Fframeio-callback&client_id=[client_id]&scope=offline+device.connect+asset.create&state=[state]&device_id=62f88d2a-1ae1-45e7-a6a0-81954e0cf2ff

Analysons un peu ces options :

response_type : Ce avec quoi le flux Oauth doit répondre. Cette valeur doit toujours être « code ». Cela indique à notre serveur Oauth de renvoyer un code vers l’URI de redirection, qui sera ensuite utilisé pour récupérer les jetons d’autorisation réels. redirect_uri : L’URL/URI où le serveur Oauth doit faire un GET lors de la réponse à une requête d’authentification. client_id : Identifie votre appli. Pour les intégrations d’Application, cette valeur sera fournie par Frame.io. scope : Une liste d’autorisations délimitées par des espaces que votre appli demande. Les autorisations suivantes sont disponibles pour les applications C2C

  • offline : L’appli peut actualiser sa propre autorisation lorsque le jeton initial expire.
  • device.connect : L’appareil peut obtenir une liste de comptes et de Projets disponibles pour les connexions C2C par l’utilisateur.
  • asset.create : L’appli peut télécharger des ressources vers les Projets auxquels elle est connectée.

Bien qu’il soit possible de demander et d’obtenir un sous-ensemble de ces portées, vous voudrez toujours demander les trois.

state : Une valeur aléatoire associée à cette requête. Nous utilisons state pour vérifier que les appels vers notre URI de redirection concernent des requêtes valides. Lorsque vous recevez un rappel sur votre URI enregistré, vous devez valider que le state est attendu.

state doit être aléatoire”> Si le paramètre state n’est pas aléatoire, vous vous exposez aux attaques CRSF, où un acteur malveillant usurpe votre paramètre state et fait une mauvaise requête vers votre rappel. Vous pouvez en savoir plus sur le paramètre state dans ce blog par Auth0

device_id : Un identifiant unique pour cet appareil/installation particulier. L’ID d’appareil doit être une valeur qui vous appartient (donc pas d’adresse MAC / numéro de série CPU, etc.), et ne doit pas contenir d’informations d’identification personnelle (donc pas d’adresses e-mail, codes de sécurité sociale, hachages d’empreintes digitales, etc.). Consultez la section ci-dessus sur device_id pour plus d’informations.

Étape 2 : Réception de la réponse OAuth

Une fois que l’Utilisateur s’est connecté à Frame.io et a accepté les portées demandées dans son navigateur, une requête GET est faite vers votre URI de rappel. La requête contient un payload encodé en URL avec les paramètres de requête suivants : code : un code qui sera utilisé pour récupérer les jetons d’autorisation depuis le backend de Frame.io. state : la Value d’état qui était incluse dans la requête d’authentification originale à l’étape 1. scope : les portées / autorisations accordées.

L’URI complète ressemblera à ceci :

https://MyApp.io/frameio-callback?code=[authorization_code]&scope=offline+device.connect+asset.create&state=[state]

L’analyse des URI peut être délicate, et la bibliothèque HTTP / Serveur dispose probablement de bonnes ressources pour ce faire, alors consultez-la avant de décider d’essayer d’analyser cette Value vous-même !

Pour les test, nous pouvons rapidement configurer un Serveur pour observer la requête GET en utilisant Python. Votre URI de callback doit être configuré comme http://localhost:8888/callback

$$ python -m http.server 8888

Nous pouvons maintenant utiliser le Modèle suivant pour demander l’accès à Frame.io. Renseignez le [client_id] et une Value [state]. Vous pouvez générer un UUID aléatoire ici pour state.

https://applications.frame.io/oauth2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8888%2Fcallback&client_id=[client_id]&scope=offline+device.connect+asset.create&state=[state]&device_id=62f88d2a-1ae1-45e7-a6a0-81954e0cf2ff

Lorsque nous passons par le flux d’authentification, nous obtiendrons une erreur 404. C’est parce que Python ne reconnaît pas la ressource demandée et ne sait pas comment y répondre. Mais ne vous inquiétez pas, la requête d’authentification a quand même réussi ! Nous devrions voir notre Serveur afficher quelque chose comme ceci dans le terminal :

Serving HTTP on :: port 8888 (http://[::]:8888/) ...
::1 - - [08/Mar/2022 14:04:34] code 404, message File not found
::1 - - [08/Mar/2022 14:04:34] "GET /callback?code=[authentication_code]&scope=offline+device.connect+asset.create&state=[state] HTTP/1.1" 404 -

Nous devrions vérifier que l’état est le même que celui que nous avons envoyé, et le authentication_code sera important à l’étape suivante pour récupérer les jetons d’accès.

Dans une Application réelle, un gestionnaire de callback pourrait ressembler à ceci :

Python
1@handler("/frameio-callback")
2def do_get(request):
3 params = url.parse_query(request.url.parts.query)
4 if "error" in params:
5 raise AuthError(params["error"])
6
7 # Handles sending the authentication code and state to the proper user
8 MyApp.frameio_oauth_success(state=params["state"], code=params["code"])
9
10 # Render some sort of confirmation page for the user.
11 request.send_response(
12 code=200,
13 headers={"Content-type": "text/html"},
14 data=OauthSuccessPage()
15 )

Étape 3 : Récupération des jetons d’accès

Maintenant que nous avons le authorization_code, nous pouvons récupérer le jeton d’accès ! À ce stade, le jeton d’accès a déjà été accordé, nous devons simplement le demander au backend.

Effectuons la requête suivante :

$curl -X POST https://applications.frame.io/oauth2/token \
> --form 'client_id=[client_id]' \
> --form 'state=[state]' \
> --form 'code=[authorization_code]' \
> --form 'redirect_uri=http://localhost:8888/callback' \
> --form 'grant_type=authorization_code' \
> --form 'scope=offline device.connect asset.create' \
> | python -m json.tool
Points d'entrée OAuth

Notez que l’hôte pour cette requête est applications.frame.io, par opposition à api.frame.io, que nous utilisons pour la plupart des requêtes. Notez également que nous utilisons des données de formulaire ici plutôt que des données JSON. Les points d’entrée OAuth C2C n’acceptent que les données de formulaire.

Une fois que vous êtes authentifié, les autres points d’entrée acceptent les données utiles application/json, mais les points d’entrée d’authentification renvoient une erreur si vous envoyez du JSON plutôt que des données application/x-www-form-urlencoded.

Passons en revue ces paramètres :

client_id : L’identifiant de l’application Oauth qui nous a été attribué par Frame.io state : La valeur d’état que nous avons incluse dans notre demande d’autorisation originale au navigateur et que nous avons reçue dans le rappel. code : Le code d’autorisation que nous avons reçu dans le rappel redirect_uri : La même URI de redirection que nous avons enregistrée avec le serveur principal de Frame.io. Si cette valeur ne figure pas dans la liste des URL séparées par des virgules que Frame.io a en dossier pour votre intégration, cette demande échouera. grant type : Pour le flux d’autorisation d’appareil logiciel, sera toujours authorization_code. scope : Doit correspondre aux portées approuvées renvoyées dans le rappel.

Nous devrions recevoir une réponse qui ressemble à ceci :

1{
2 "access_token": "[access_token]",
3 "expires_in": 3599,
4 "refresh_token": "[refresh_token]",
5 "scope": "offline device.connect asset.create",
6 "token_type": "bearer"
7}

Notre appareil est maintenant autorisé avec succès avec Frame.io ! Gardez ces valeurs à portée de main car nous en aurons besoin pour effectuer le reste de nos demandes. Examinons ce qui se trouve dans les données utiles :

access_token : C’est votre clé d’accès au reste du serveur principal Frame.io. Nous devrons ajouter ceci à l’en-tête du reste des demandes que nous allons faire dans ces tutoriels. expires_in : Le nombre de secondes avant que access_token n’expire. Une fois que le temps du jeton est écoulé, il devra être actualisé, ce que nous verrons dans un futur tutoriel. refresh_token : Un jeton que nous pouvons utiliser pour gérer notre access_token. Il sera le plus souvent utilisé pour actualiser notre autorisation, mais il peut également être utilisé pour la révoquer. token_type : Sera toujours bearer pour l’API C2C, et n’est pas exploitable.

{ "trancreatedText": [ "Il nous reste encore quelques étapes avant d'être réellement connectés à un Projet, alors maintenant que c'est acquis, continuons !
1## Étape 4 : Lister les comptes
2
3
4
5
6
7Ensuite, nous devons obtenir une liste des comptes auxquels notre utilisateur peut se connecter.Il s'agit du premier appel qui nécessite notre jeton d'accès, et nous l'ajouterons à un en-tête :
8
9
10
11
12
13```shell
14curl -X GET https://api.frame.io/v2/devices/accounts \
15 --header "x-client-version: 2.0.0" \
16 --header "Authorization: Bearer [access_token]" \
17 | python -m json.tool
Spécification du point d'entrée de l'API

La documentation pour /v2/devices/accounts peut être consultée ici

L'en-tête Authorization" ] } ```

Pour chaque point d’entrée qui nécessite une autorisation, nous devons ajouter le access_token à l’en-tête Authorization. Notez que nous devons préfixer Bearer (avec un espace !) à notre jeton d’accès comme Valeur.

Cet appel devrait renvoyer une liste de comptes auxquels l’utilisateur peut se connecter :

1[
2 {
3 "_type": "account",
4 "display_name": "Hogwarts General",
5 "id": "46b7ea11-3041-4e2b-97f7-98fbf5c974c9"
6 },
7 {
8 "_type": "account",
9 "display_name": "Gryffindor",
10 "id": "e6007a3d-cad7-4666-9ee3-23c1af032060"
11 },
12 {
13 "_type": "account",
14 "display_name": "QUIDDITCH LEGENDS -- LETS GOOOOOOOOOO",
15 "id": "cc94119d-f957-4d6e-b8cf-0c095211b1b9"
16 }
17]

À ce stade, vous afficheriez cette liste à l’utilisateur et lui demanderiez de sélectionner le Compte auquel il souhaite se connecter. Ensuite, nous utiliserons l’id du Compte à l’étape suivante pour répertorier les projets pour lesquels l’utilisateur peut connecter un équipement C2C.

Étape 5 : Lister les projets

Nous devons maintenant obtenir une liste de projets pour le Compte qui nous intéresse :

$curl -X GET https://api.frame.io/v2/devices/accounts/[account_id]/projects \
> --header "x-client-version: 2.0.0" \
> --header "Authorization: Bearer [access_token]" \
> | python -m json.tool
Spécification du point d'entrée d'API

La documentation pour /v2/devices/accounts/[account_id]/projects peut être trouvée ici

Nous devons ajouter l’account_id pour lequel nous essayons de lister les projets à l’URL. Remarquez également que le chemin d’accès global à la ressource commence par /devices/.... Nous ne nous contentons pas de lister les projets ici, nous listons les projets pour lesquels l’utilisateur dispose d’autorisations de gestion d’équipement C2C. Si un Projet auquel appartient l’utilisateur n’est pas répertorié, cela signifie qu’il ne dispose pas d’autorisations de gestion d’équipement C2C pour ce Projet.

Nous obtiendrons une réponse similaire à celle des comptes :

1[
2 {
3 "_type": "project",
4 "id": "921480ec-1225-424a-9447-19c61a3a1ef2",
5 "name": "Match Recordings"
6 },
7 {
8 "_type": "project",
9 "id": "ed5dbf4a-f146-416b-add0-74de98201876",
10 "name": "Year Book Material"
11 }
12]

Tout comme avec les comptes, cette liste devrait être affichée à l’utilisateur pour qu’il sélectionne le Projet auquel il souhaite se connecter, et tout comme les comptes, nous aurons besoin de l’id du Projet pour l’étape suivante.

Étape 6 : Connexion à un projet

Maintenant que l’utilisateur a sélectionné le Projet auquel il souhaite se connecter, nous sommes prêts à commencer ! Il ne reste qu’une dernière étape pour terminer l’appairage de notre périphérique logiciel à un Projet Frame.io :

$curl -X POST https://api.frame.io/v2/devices/connect?project_id={project_id} \
> --header "x-client-version: 2.0.0" \
> --header "Authorization: Bearer [access_token]" \
> | python -m json.tool
Spécification du point d'entrée d'API

La documentation pour /v2/devices/connect peut être trouvée ici

L’id du Projet est un paramètre de requête d’URL, et nous devons toujours transmettre notre en-tête d’autorisation !

Nous obtenons une réponse comme celle-ci (certaines données omises par souci de concision) :

1{
2 "_type": "project_device",
3 "asset_type": "video",
4 "authorization": {
5 "_type": "project_device_authorization",
6 "creator": {
7 "_type": "user",
8 "account_id": "93f872fb-9924-4e31-a430-2574e0742260",
9 "deleted_at": null,
10 "email": "hpotter@hoggyhoggyhogwarts.edu",
11 "id": "d473b5e1-08d2-4842-82ac-a6b01233dc2c",
12 ...
13 "name": "Harry Potter",
14 ...
15 },
16 "creator_id": "d473b5e1-08d2-4842-82ac-a6b01233dc2c",
17 "expires_at": null,
18 "id": "ee9f5949-b7fa-4c71-8480-6d4c60877c51",
19 "inserted_at": "2022-03-09T18:14:21.893283Z",
20 "project_device_id": "6a55d7f6-dfb7-46a1-bff8-a3acb2d3d1aa",
21 "scopes": {
22 ...
23 "asset_create": true,
24 ...
25 "id": "1e174fe9-5b53-48db-b556-c310c0848898",
26 "offline": true,
27 ...
28 }
29 },
30 "channels": [
31 {
32 "_type": "project_device_channel",
33 "asset_type": "video",
34 ...
35 }
36 ],
37 "creator_id": "d473b5e1-08d2-4842-82ac-a6b01233dc2c",
38 "deleted_at": null,
39 "device_id": "a8a4f3bf-196c-4748-832b-28f1d0801515",
40 "id": "93af90e7-ee89-4b47-86e6-c2750f3790b6",
41 ...
42 "name": "MyApp-62f88d2a-1ae1-45e7-a6a0-81954e0cf2ff",
43 "project": {
44 "_type": "project",
45 "id": "921480ec-1225-424a-9447-19c61a3a1ef2",
46 "name": "Testbed"
47 },
48 "project_id": "921480ec-1225-424a-9447-19c61a3a1ef2",
49 "status": "online",
50 ...
51}
Un projet à la fois

Vous ne pouvez appairer qu’un équipement avec un Projet à la fois et effectuer une autre opération d’appairage vers un Projet différent supprimera sa connexion avec celui précédemment connecté.

Si votre charge utile de réponse ressemble à cela : Ouah ! Vous avez réussi ! Vous avez autorisé votre premier appareil Camera to Cloud. Prenez le temps de célébrer !

Une fois que vous avez terminé de célébrer, vous devriez afficher le nom du Projet à l’Utilisateur pour vérifier le Projet auquel il s’est connecté.

Utilisation d’une bibliothèque OAuth tiers

Frame.io utilise le flux Oauth2.0 standard. Pour la sécurité, nous appliquons PKCE. Il existe de nombreuses bibliothèques disponibles pour gérer cette partie d’une intégration à votre place.

Voici quelques bibliothèques Oauth populaires :

Langage de programmationNomURL
SwiftOAuthSwiftGithub
Pythonrequests-oauthlibGithub
Flutteroauth2_clientGithub
N’oubliez pas que Frame.io ajoute un champ device_id pour identifier un appareil particulier. Il s’agit d’un champ personnalisé supplémentaire. La bibliothèque que vous choisissez d’utiliser prendra très probablement en charge les champs personnalisés, mais assurez-vous de ne pas oublier de l’ajouter !

Résolution des problèmes

Si vous vous trouvez ici, c’est que quelque chose s’est mal passé ! Qu’est-ce qu’une intégration avec un tiers sans une sorte d’erreur ? Cette section répertorie un ensemble de problèmes courants et vous guidera à travers les étapes les plus susceptibles de les résoudre. Parcourez la liste suivante et voyez si quelque chose correspond à votre problème. Le guide des erreurs est également une excellente ressource pour rechercher les erreurs d’API.

Si vous ne trouvez pas de solution ici, nous aimerions beaucoup connaître le problème que vous avez rencontré afin de pouvoir l’ajouter ici !

Le compte ou le Projet auquel je souhaite me connecter n’a pas été renvoyé : si vous répertoriez les comptes et/ou les projets et que celui auquel vous souhaitez vous connecter n’est pas répertorié, plusieurs éléments peuvent se produire. Dans Frame.io, accédez au projet auquel vous souhaitez vous connecter et cliquez sur l’onglet Connexions C2C. Cela vous aidera à découvrir ce qui ne va pas.

  • C2C n’est pas activé pour votre compte : si l’écran est vide et qu’un message indique que C2C n’est pas disponible pour votre compte, le gestionnaire de compte doit l’activer pour votre projet dans les paramètres du compte !
  • Vous n’êtes pas un gestionnaire d’appareil : si l’écran est vide et qu’un message indique que vous n’avez pas les autorisations, le gestionnaire de compte doit soit modifier les autorisations pour déterminer qui est autorisé à connecter les appareils C2C, soit vous ajouter à un rôle qui dispose de ces autorisations.

Erreur de client non valide : invalid_client est renvoyé lorsque les informations que vous nous fournissez sur l’appareil ne correspondent à rien de ce que nous avons en dossier. Cela signifie très probablement que votre client_secret, client_id ou redirect_uri ne correspondent pas à ce que Frame.io a en dossier dans notre backend. Erreur de demande incorrecte : bad_request est renvoyé lorsque les données de demande sont mal formées d’une manière ou d’une autre. Vérifiez que vous n’avez pas mal orthographié un nom de champ ou oublié d’ajouter un champ obligatoire.

Étape suivante

Si ce n’est pas déjà fait, nous vous encourageons à contacter notre équipe, puis à poursuivre avec le guide suivant. Nous avons hâte de vous entendre !