... | ... | @@ -24,193 +24,4 @@ Read them to get some good ideas! |
|
|
- [Facebook pages](https://zapier.com/apps/facebook-pages/integrations);
|
|
|
- [RSS](https://zapier.com/apps/rss/integrations);
|
|
|
- [Wordpress](https://zapier.com/apps/wordpress/integrations);
|
|
|
- [Google Calendar](https://zapier.com/apps/google-calendar/integrations);
|
|
|
|
|
|
## Mail sent to Zapier team (in french)
|
|
|
|
|
|
### Question
|
|
|
|
|
|
(after a short exchange, but this is the interesting part)
|
|
|
|
|
|
> Bonjour,
|
|
|
> Merci pour votre réponse rapide.
|
|
|
> J'ai bien lu la doc Zapier sur oauth2, ce n'est pas vraiment là dessus que je bloque. ;)
|
|
|
>
|
|
|
> Je bloque sur la génération des `client_id` et `client_secret`.
|
|
|
> La plupart des apps Zapier concernent des services centralisés, donc ce n'est pas vraiment un problème, puisque qu'il suffit au développeur de les générer une seule fois et de les stocker dans les variables d'environnement Zapier spécifiques à chaque utilisateur.
|
|
|
>
|
|
|
> Ce n'est pas le cas de Mastodon : étant donné que c'est une plateforme décentralisée, il y existe des milliers de serveurs et je ne sais pas comment procéder pour générer et stocker les `client_id` et `client_secret`.
|
|
|
>
|
|
|
> En gros il faudrait que :
|
|
|
> 1. l'utilisateur renseigne l'url de son serveur;
|
|
|
> 2. que mon app enregistre l'application Zapier au serveur à ce moment (génération des `client_id` et `client_secret`) ; idéalement, elle ne devrait le faire uniquement si cela n'a pas été fait par un autre utilisateur auparavant qui utiliserait le même serveur Mastodon ;
|
|
|
> 3. qu'elle stocke `client_id` et `client_secret` dans les variables d'environnement spécifiques à l'utilisateur.
|
|
|
>
|
|
|
> J'ai regardé comment fonctionne l'app de Gitlab au début elle demande directement les client_id et client_secret. Du coup coup c'est l'utilisateur lui-même qui enregistre à la main l'application Zapier depuis l'interface de GitLab. Mastodon ne permet pas de faire ça. Donc cette opération doit se faire coté Zapier. Je ne sais pas comment procéder.
|
|
|
|
|
|
### Answer from Zapier team
|
|
|
|
|
|
> Je vois, je n'avais pas compris ça, désolé.
|
|
|
>
|
|
|
> Voici les pistes que j'explorerai pour implémenter ce que tu souhaites, n'hésite pas à me corriger si j'ai mal compris quelque chose ou si ce n'est pas techniquement possible.
|
|
|
>
|
|
|
> **1. L'utilisateur renseigne l'url de son serveur**
|
|
|
>
|
|
|
> Tu peux demander à l'utilisateur de renseigner des champs lors de la phase d'authentification en utilisant la propriété authentication.fields.
|
|
|
> Dans la doc que je t'ai lié précédement il y a un exemple sur comment demander un sous-domaine.
|
|
|
>
|
|
|
> Cela donnerait quelque chose comme :
|
|
|
>
|
|
|
> ```js
|
|
|
> const authentication = {
|
|
|
> type: 'oauth2',
|
|
|
> // ...
|
|
|
> fields: [
|
|
|
> { key: 'url', type: 'string', required: true, default: 'mastodon.com' }
|
|
|
> ]
|
|
|
> }
|
|
|
> ```
|
|
|
>
|
|
|
> **2. que mon app enregistre l'application Zapier au serveur à ce moment**
|
|
|
>
|
|
|
> Si je comprends bien tu veux que l'app récupère dynamiquement le client_id et client_secret une seule fois par serveur Mastodon ?
|
|
|
> La seule manière que je verrai serait de faire ça juste avant d'authentifier l'utilisateur.
|
|
|
> Tu peux spécifier une fonction au lieu d'un objet à la propriété `authentication.oauth2Config.authorizeUrl`.
|
|
|
> Tu pourrais faire une première requête pour récupérer le client_id et client_secret, puis retourner ton URL d'authentification.
|
|
|
>
|
|
|
> Quelque chose comme :
|
|
|
>
|
|
|
> ```js
|
|
|
> const authentication = {
|
|
|
>
|
|
|
> type: 'oauth2',
|
|
|
> // ...
|
|
|
> oauth2Config: {
|
|
|
> authorizeUrl: async (z, bundle) => {
|
|
|
> // Fetch client_id and client_secret
|
|
|
> // Build the authorization URL using client data
|
|
|
> // Return the URL
|
|
|
> }
|
|
|
> }
|
|
|
> }
|
|
|
> ```
|
|
|
>
|
|
|
> **3. qu'elle stocke `client_id` et `client_secret` dans les variables d'environnement spécifiques à l'utilisateur**
|
|
|
>
|
|
|
> Malheureusement nous n'offrons pas une manière de faire persister de la donnée comme ceci...
|
|
|
> Une idée pourrait être d'effectuer la requête pour avoir le client_id and le client_secret vers un proxy que tu héberges qui stockerait les triplet url,client_id,client_secret.
|
|
|
>
|
|
|
> Dis-moi si les informations que je t'ai donné t'aident à y voir plus clair. Je ne suis pas sur qu'il y ait une manière simple de faire ce que tu souhaitres malheureusement, vu que c'est un cas assez particulier. Je vais me renseigner en interne pour voir si on a déjà une app avec ce genre d'authentification et je te reviendrai si j'ai plus d'élements.
|
|
|
>
|
|
|
> Merci de ta patience et bon courage!
|
|
|
|
|
|
### My Answer
|
|
|
|
|
|
> > > que mon app enregistre l'application Zapier au serveur à ce moment
|
|
|
> > Si je comprends bien tu veux que l'app récupère dynamiquement le client_id et client_secret une seule fois par serveur Mastodon ?
|
|
|
>
|
|
|
> Oui, tout à fait.
|
|
|
>
|
|
|
> > La seule manière que je verrai serait de faire ça juste avant d'authentifier l'utilisateur.
|
|
|
> > Tu peux spécifier une fonction au lieu d'un objet à la propriété `authentication.oauth2Config.authorizeUrl`.
|
|
|
> > Tu pourrais faire une première requête pour récupérer le client_id et client_secret, puis retourner ton URL d'authentification.
|
|
|
>
|
|
|
> Ok. Serait-il possible par un quelquonque moyen de vérifier si l'application a déjà été enregistrée sur ce serveur ? Parce que sinon ça voudrait dire que je fais un enregistrement d'application différent pour chaque utilisateur et je vais me faire taper sur les doigts par les admins. ^^
|
|
|
>
|
|
|
> > > qu'elle stocke client_id et client_secret dans les variables d'environnement spécifiques à l'utilisateur
|
|
|
> > Malheureusement nous n'offrons pas une manière de faire persister de la donnée comme ceci...
|
|
|
>
|
|
|
> Ah ? Je ne pensais pas que le critère bloquant se situerait ici. Vous stockez bien les client_id et client_secret pour l'app GitLab, ou même les tokens d'authentification pour les autres Apps, qui sont tous spécifiques à chaque utilisateur non ?
|
|
|
>
|
|
|
> Merci pour les autres pistes, je vais regarder ça.
|
|
|
|
|
|
### Zapier answer
|
|
|
|
|
|
> Je viens de regarder un peu plus en détail, et je pense qu'au final tu peux t'en sortir en jouant avec le curseur and les computed fields stockés dans `bundle.inputData`.
|
|
|
>
|
|
|
> C'est un peu tordu, mais je pense que ça devrait fonctionner. Généralement on évite de donner trop de code, mais dans ce cas précis je pense que c'est plus simple que d'expliquer.
|
|
|
> Ça donnerait quelque chose comme ça :
|
|
|
>
|
|
|
> ```js
|
|
|
> const authentication = {
|
|
|
> type: 'oauth2',
|
|
|
> // ...
|
|
|
> oauth2Config: {
|
|
|
> authorizeUrl: async (z, bundle) => {
|
|
|
> // Fetch client_id and client_secret
|
|
|
> const { client_id, client_secret } = await z.request(`${bundle.inputData.url}/my/register/endpoint`).then(res => res.json);
|
|
|
>
|
|
|
> // Store client_id and client_secret
|
|
|
> await z.cursor.set(`${client_id}|${client_secret}`)
|
|
|
>
|
|
|
> // Return the authorization URL
|
|
|
> return {
|
|
|
> method: 'GET',
|
|
|
> url: `https://${bundle.inputData.url}/my/authorize/endpoint`,
|
|
|
> params: {
|
|
|
> client_id: `${bundle.inputData.client_id}`,
|
|
|
> state: `${bundle.inputData.state}`,
|
|
|
> redirect_uri: `${bundle.inputData.redirect_uri}`,
|
|
|
> response_type: 'code'
|
|
|
> }
|
|
|
> }
|
|
|
> },
|
|
|
> getAccessToken: async (z, bundle) => {
|
|
|
> // Retreive client_id and client_secret
|
|
|
> const [ client_id, client_secret ] = await z.cursor.get().split('|')
|
|
|
>
|
|
|
> // Fetch tokens
|
|
|
> const { access_token, refresh_token } = await z.request({
|
|
|
> method: 'POST',
|
|
|
> url: `https://${bundle.inputData.url}/my/token/endpoint`,
|
|
|
> body: {
|
|
|
> code: bundle.inputData.code,
|
|
|
> client_id,
|
|
|
> client_secret,
|
|
|
> redirect_uri: bundle.inputData.redirect_uri,
|
|
|
> grant_type: 'authorization_code'
|
|
|
> }
|
|
|
> }).then(res => res.json);
|
|
|
>
|
|
|
> // This is stored in `bundle.authData` for later usage
|
|
|
> return {
|
|
|
> client_id,
|
|
|
> client_secret,
|
|
|
> access_token,
|
|
|
> refresh_token
|
|
|
> }
|
|
|
> },
|
|
|
> refreshAccessToken: async (z, bundle) => {
|
|
|
> // Fetch tokens
|
|
|
> const { access_token, refresh_token } = await z.request({
|
|
|
> method: 'POST',
|
|
|
> url: `https://${bundle.inputData.url}/my/token/endpoint`,
|
|
|
> body: {
|
|
|
> client_id: bundle.authData.client_id,
|
|
|
> client_secret: bundle.authData.client_secret,
|
|
|
> redirect_uri: bundle.inputData.redirect_uri,
|
|
|
> refresh_token: bundle.authData.refresh_token,
|
|
|
> grant_type: 'refresh_token'
|
|
|
> }
|
|
|
> }).then(res => res.json);
|
|
|
>
|
|
|
> // This is stored in `bundle.authData` for later usage
|
|
|
> return {
|
|
|
> client_id: bundle.authData.client_id,
|
|
|
> client_secret: bundle.authData.client_secret,
|
|
|
> access_token,
|
|
|
> refresh_token
|
|
|
> }
|
|
|
> },
|
|
|
> fields: [
|
|
|
> { key: 'url', type: 'string', required: true, default: 'mastodon.com' },
|
|
|
> { key: 'client_id', type: 'string', required: true, computed: true },
|
|
|
> { key: 'client_secret', type: 'string', required: true, computed: true }
|
|
|
> ]
|
|
|
> }
|
|
|
> }
|
|
|
> ```
|
|
|
>
|
|
|
> Dis-moi si tu penses que ça pourrait marcher.
|
|
|
>
|
|
|
> Merci! |
|
|
\ No newline at end of file |
|
|
- [Google Calendar](https://zapier.com/apps/google-calendar/integrations); |
|
|
\ No newline at end of file |