-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Utilisation des intents sur application Cordova #232
Comments
Non, ce n'est pas possible. Ce serait une grave faille de sécurité que de permettre ça. |
Quelles seraient les conséquences de whitelister
On n'était pas super chaud pour ca à l'origine, pour éviter de faire transiter les valeurs de retour par le serveur (alors que techniquement elle est déjà sur l'appareil, "juste" dans une autre fenêtre). Du coup la les websockets me paraissent le mieux /o. Il se trouve qu'on a d'autres use-cases entre temps pour de la communication permanente via les intents. Désolé pour ces réponses pas très drôles. |
Un peu plus d'explication s'il te plaît ? J'ai soif d'apprendre.
Ca ne toucherait pas que les intents. Ca permettrait à n'importe quelle iframe d'être ouverte donc potentiellement à une application voyou de faire fuiter des données vers un serveur tiers.
Passer par une websocket fait aussi transiter les données via le serveur. Mais elles ne sont pas stockées. Le stockage est un problème de ressource, ou de vie privée ? Est ce que c'est vraiment un soucis si l'intent est supprimé ?
Tu as des exemples ? |
Ok, mais qui ouvre cette iframe ? Pour nos propres applis, on sait ce qu'on ouvre je pense (rien à part des intents que je sache). Et des applis tierces connectés au Cozy, elles n'ont pas besoin d'iframe pour faire fuiter des données.
Tu as raison, au temps pour moi. C'était plus une question de ressources, étant donné que les données qui transitent sont souvent déjà connus par le serveur.
Oui j'aurais du les inclure d'ailleurs. Essentiellement Claudy et la recherche. Pas sûr que ce soient des sujets sur mobile aussi. |
Mmh je pensais justement que notre but avec les CSP, c'était de prévenir ça.
J'ai pas du tout regardé WebRTC mais ca me semble risqué de partir là dessus étant donné que les webview Cordova peuvent être vieilles et que WebRTC est encore à l'état de draft. Je m'y connais pas plus.
La recherche me semble être un sujet très mobile, j'avais complètement zappé que la recherche utilisait un intent. En effet, dans le cas de la recherche, la valeur de retour n'est pas top puisque on veut faire transiter plusieurs informations sur un même intent. |
Actuellement nous arrivons à communiquer entre une fenêtre InAppBrowser et l'application qui la lance grâce à l'événement Le premier soucis à résoudre est je pense l'authentification. Voici une solution :
Je viens de voir avec le back mais il réfléchissent à ce que le cookie n'expire seulement au bout de 7 jours d'inactivité. Il suffirait donc de pinguer la stack à intervalles réguliers pour que le cookie n'expire pas. Un des soucis, c'est si le cookie expire et que l'on n'a pas sauvegardé le mot de passe alors il faudra redemander le mot de passe à l'utilisateur. On peut résoudre ça en le sauvegardant mais c'est vraiment pas top. NB: Cette solution n'est pas forcément idéal. C'est plus un hack pour aller vite mais clairement la solution des websockets serait top. Avec toujours le soucis que l'on devrait redemander le mot de passe de l'utilisateur. |
@kosssi m'a pointé le code de l'authentification mobile qui utilise l'évenement loadstart pour communiquer avec l'inAppBrowser. Il est possible de communiquer avec l'inAppBrowser en se basant sur loadstart/loadstop. Cette méthode me semble cependant assez fragile, il faut que l'intent et possiblement toutes les pages qu'il peut charger n'aient pas de problème avec des urls "bizarres". Dans le service : const base = window.location.href // wishing the application will not change URLs, brittle
const sendData = function (data) {
window.location.href = base + '?data=' + encodeURIComponent(JSON.stringify(data))
} Dans l'application : const regex = /.*\?data=(.*)/
const getData = function (url) {
const match = regex.exec(url)[1];
return match && JSON.parse(decodeURIComponent(match))
}
const onLoadStop = function (options) {
console.log(getData(options.url))
}
const w = window.open('http://adresse-de-l-intent', '_blank')
w.addEventListener('loadstop', onLoadStop) |
Je ne vois pas vraiment de différence entre redemander le mot de passe de l'utilisateur dans l'application et dans l'inAppBrowser. Cela poserait aussi un problème de sécurité car l'application aurait accès au mot de passe de l'utilisateur (et donc à tout ses doctypes et plus...) |
Version longue de ma réponse précédente (que je n'avais pas eu le temps d'écrire jusque là). Le modèle de sécurité pour les apps mobils n'est pas très clair. On était parti sur le principe que l'app mobile que l'on développe doit montrer la bonne manière de faire pour les développeurs tiers. En particulier, on n'a aucun moyen fiable côté stack de savoir si une requête provient d'une app mobile Cozy ou d'une app tiers. On s'est appuyé sur OAuth 2, avec un modèle à 3 pattes. Et dans ma tête, la partie où l'utilisateur se connecte sur la stack puis donne les permissions se faisait dans le navigateur de l'utilisateur, pas dans l'inAppBrowser. D'un point de vue UX, ce n'était pas acceptable et on s'est donc rabattu sur l'inAppBrowser. On considère toujours que l'app ne doit pas avoir accès au mot de passe, ni aux données de l'utilisateur en dehors de celles qu'il a accepté explicitement. C'est particulièrement important pour les apps mobiles, car contrairement aux apps web, on ne peut pas contrôler ces communications externes avec du CSP (et donc les fuites de données). Du coup, si on ajoute un moyen pour les apps mobiles de donner un token qui authentifie l'utisateur, elle pourrait transmettre ce token à un tiers, qui aurait alors accès à tout le cozy de l'utilisateur (mot de passe des comptes bancaires y compris). |
OK, donc, si je résume, la proposition serait :
Côté stack, ça me paraît bien aller. |
🎉
Je pensais que le service se connecterait aussi sur la websocket pour envoyer/recevoir des messages, ca peut marcher comme ca avec |
Envoyer des messages dans la websocket ne permet que de contrôler ce que l'on veut recevoir dedans. Si ton besoin est de pouvoir passer de l'information de l'app mobile vers le service, on peut imaginer que le service écoute lui aussi en websocket et que l'app mobile puisse également faire des requêtes vers la stack pour envoyer des données. |
Pas sur d'avoir compris ? "ne permet pas de contrôler" c'est ca ?
Ok ca me va |
C'est décrit ici -> https://cozy.github.io/cozy-stack/realtime.html#websocket-api En gros, tu peux envoyer des trucs dans la websocket pour dire « je veux être prévenu quand il y a un changement sur les fichiers », mais ça n'aura aucun effet sur le système (la base de données et les autres connexions en websocket). |
(Juste pour rappel, on a une implémentation du realtime dans Collect.) |
OK parfait. Donc si je comprends bien, il n'y a rien à faire côté stack vu que le realtime est déjà implémenté ? Du côté de cozy-client-js il faudrait rapatrier le realtime.js de collect dans cozy-intents (qui naitra prochainement) et s'en servir pour les nouveaux services. |
Si, côté stack, il y a un peu de boulot pour ajouter la route |
Au final la route POST |
Je pensais aussi garder dans couchdb un historique (des logs) de ce qui passe par ce canal.
On n'a pas actuellement d'id de websocket et c'est assez compliqué à gérer à cause des déconnexions/reconnexions possibles. Et il faut également savoir gérer les autorisations, ce qui me semblent aussi être un terrain assez glissants. |
OK pour moi |
je déterre ce sujet pour ajouter deux informations
|
J'ouvre cette issue pour démarrer une discussion sur comment va-t-on faire pour faire marcher les intents sur mobile. J'ai essayé de proposer quelques pistes et aimerait avoir vos retours là-dessus.
Cas d'usages d'intent
Intent via inAppBrowser au lieu d'une iframe
L'utilisation de inAppBrowser pose le problème de la communication entre l'application et le service. Sur mobile nous ne pouvons pas utiliser les
iframe
s à cause des politiques de sécurité de Cordova.En effet, pour pouvoir ouvrir une iframe il faut inscrire son domain dans la
whitelist
etétant donné que nous ne connaissons pas le domaine en avance, nous ne pouvons pas le faire.
Nous pouvons cependant utiliser
inAppBrowser
qui utilise une véritable fenêtre pour ouvrirla page demandée.
Via postMessage, executeScript
La communication entre les deux fenêtres semble difficile (surtout de l'inappbrowser vers l'app).
J'ai essayé (comme préconisé sur https://www.telerik.com/blogs/cross-window-communication-with-cordova's-inappbrowser) :
La valeur dans localStorage est bien inscrite mais on ne peut pas la récupérer☹️ . Cela semble un
problème qu'on plusieurs personnes : https://www.google.fr/search?q=inappbrowser+callback+not+firing&oq=inappbrowser+callback+not+firing&aqs=chrome..69i57j69i60l3.4359j0j4&sourceid=chrome&ie=UTF-8. Avec les politiques
de CSP strictes que l'on a, je doute que cela ne marche.
✅ On peut cependant écouter sur l'évenement "exit" de la fenêtre.
Stocker valeur de retour dans l'intent
Stocker une valeur de retour dans l'intent (via un
HTTP POST
par leur service et unHTTP GET
par l'application) permettrait sa lecture par l'application à la fermeture de l'inAppBrowser.PUT
sur l'intent pour le modifier (seulement la valeur de retour doit être modifiable, juste une fois).Websocket pour communication permanente
Idée pour communiquer des valeurs : passer par une websocket. Le service et l'application
recevrait de la stack un id + token ou ils pourraient communiquer. Inconvénients:
complexité chez la stack, latence, 2 connexions en plus par intent. Avantage : assez générique et
niveau de confiance plutôt élevé sur le fait que ca marche.
Abstraction du channel de communication app/service
Ces 2 possibilités d'ouverture/communication entre l'application et le service (via une iframe/postMessage, inAppBrowser/
HTTP GET intents/id/returnValue
) nécessiterait une abstraction niveaucozy-intent
pour que l'utilisateur n'ait pas à se préoccuper de ces détails bas-niveaux, idéalement juste utiliser une option{ mobile: true }
?Possibles améliorations
Login automatique sur la stack
L'inAppBrowser ne partage pas ses cookies avec la webview Cordova, à l'ouverture de l'intent, l'utilisateur devrait donc se logguer. Pour améliorer l'expérience utilisateur, il pourrait être intéressant de le logguer directement dans l'inappbrowser, est ce que ce serait possible de demander à la stack un token d'authentification à n'utiliser qu'une fois et qui permettrait à l'utilisateur de ne pas avoir à retaper son mot de passe ?
Nettoyage des intents
Le nettoyage des intents n'a pas été implémenté, l'idée étant de les supprimer juste après leur lecture par le service. Si l'on souhaitere stocker une valeur de retour dans l'intent pour lecture par l'application mobile, il faudrait le supprimer après lecture de la valeur de retour. Cela pourrait être configuré au lancement de l'intent avec une option spécifique
{ deleteAfter: 'readByService' }
,{ deleteAfter: 'readByApp' }
. Autre possibilité : l'option{mobile:true}
évoquée plus haut pourrait abstraire ce détail.The text was updated successfully, but these errors were encountered: