Lorawan-stack: Introduire une nouvelle application de compte (pour remplacer l'application oauth)

Créé le 4 oct. 2019  ·  32Commentaires  ·  Source: TheThingsNetwork/lorawan-stack

Résumé

Nous avons actuellement beaucoup de problèmes qui gravitent autour de notre flux OAuth, le changement de compte, la gestion des jetons, l' image de marque respectifs, etc. Ceci est une tentative de faire tous ces plus une action dans une nouvelle account app qui prendra soin de toutes ces préoccupations.

Pourquoi avons nous besoin de ça?

  • Fonctionnalité de changement de compte manquante ⟶ #488
  • Image de marque et contexte manquants pour l'utilisateur ⟶ #730
  • Gestion de session manquante ⟶ #1217
  • Confusion des utilisateurs autour du flux d'authentification OAuth ⟶ #265

Qu'est-ce qu'il y a déjà ? Que voyez-vous maintenant?

  • Application OAuth avec interface utilisateur limitée

Que manque-t-il? Qu'est-ce que tu veux voir?

Une application qui agit en tant que fournisseur OAuth et une interface utilisateur de configuration complète et de marque pour tous les problèmes de compte et d'authentification

Environnement

la toile

Comment proposez-vous de mettre cela en œuvre ?

Je pense qu'un gros problème avec l'implémentation actuelle est le manque de clarté et de contexte pour l'utilisateur. Il est difficile de reconnaître l'application OAuth en tant qu'entité d'authentification indépendante. Les raisons sont :

  • manque d'image de marque et de contexte
  • UI très réduite et peu informative
  • console agissant comme si elle gérait elle-même l'authentification (message "Connexion" au lieu de "Connexion avec votre compte {OAuth provider service name}", saut d'autorisation)
    Pour améliorer la clarté, nous devons rendre l'application plus visible, distincte et ciblée :
  • Ajouter une image de marque configurable
  • Fonctionnalité étoffée

    • Changement de compte

    • Gestion des sessions

    • Gestion des autorisations

    • Paramètres du profil (modifier/oublier le mot de passe, e-mail, photo de profil)

J'ai créé trois wireframes qui donnent une idée de la façon dont j'envisage l'application de compte :

Voir les wireframes

account_login
account_overview
account_profile_settings
(notez le sélecteur de compte intégré dans la liste déroulante des utilisateurs en haut à droite)

Pouvez-vous le faire vous-même et soumettre une Pull Request ?

Oui. @johanstokking @htdvisser , veuillez me faire savoir si vous pensez qu'il est bon de continuer.

identity server uweb umbrella

Tous les 32 commentaires

En ce qui concerne l'ensemble du problème de confusion connexion/déconnexion entre la console et le fournisseur oauth, voici mon plan :

  • Nous utilisons un logo Account distinct pour l'application de compte (au lieu du logo TTS) et utilisons le même composant d'en-tête que nous utilisons également pour la console (cc @pierreph)
  • Au lieu d'avoir deux écrans de connexion distincts pour la console et l'application de compte, nous devrions lier l'expérience plus étroitement, ce qui signifie

    • Nous allons supprimer l'écran de connexion à la console /console/login

    • La console redirigera automatiquement vers la page de connexion de l'application du compte /account/login , lorsqu'elle n'a pas de jeton d'accès (valide)

    • Comme nous le faisons déjà avec le bouton de connexion à la console, nous utiliserons un paramètre de requête de redirection pour renvoyer l'utilisateur à la console après une connexion réussie

    • La déconnexion de l'interface utilisateur de la console entraînera la suppression du jeton d'accès stocké, ainsi que la déconnexion de l'application de compte. De cette façon, les utilisateurs devront toujours ressaisir leurs informations d'identification afin de se reconnecter à la console.



      • Pour pouvoir le faire, nous avons besoin d'un moyen de déclencher des déconnexions à partir de demandes d'origine croisée (puisque la console et l'application de compte ne sont pas garanties d'être sur la même origine)


      • Dans la v2, nous utilisons une simple route /users/logout qui déclenchera une déconnexion à laquelle on peut se référer de n'importe où


      • Ce serait bien de chercher des moyens d'atteindre la même chose tout en restant en sécurité CSRF



    • Le nouveau flux ressemblera à peu près au flux de la console v2 ; nous allons essentiellement sacrifier la séparation du client de la console et du serveur d'autorisation pour améliorer l'UX, ce qui est OK puisque la console est en quelque sorte un client de cas particulier

    • Nous pourrions avoir besoin de réviser ce flux si nous autorisons différentes procédures de connexion à l'avenir

Si je n'entends aucune plainte au sujet de ce plan, je commencerai à le mettre en œuvre.

Cela a l'air d'être un super plan. Je suis d'accord que nous n'avons pas besoin de nous déconnecter explicitement de la console et que nous restons connectés via OAuth dans l'UX, bien que cela fonctionnera de cette façon en dessous.

De quoi avez-vous besoin pour la déconnexion cross-origin ? Ne s'agirait-il pas d'une simple approche en deux étapes ? "page" de déconnexion pour supprimer le jeton d'accès stocké dans la console, puis rediriger vers la page de déconnexion générique où l'application Compte se déconnecte ? Ou voulez-vous cela sans redirection mais publier sur un point de terminaison de déconnexion ?

Pour la déconnexion, nous pouvons nous inspirer de la déconnexion d'OpenID Connect. Un joli résumé peut être trouvé ici : https://medium.com/@robert.broeckelmann/openid -connect-logout-eccc73df758f

Cela a l'air d'être un super plan. Je suis d'accord que nous n'avons pas besoin de nous déconnecter explicitement de la console et que nous restons connectés via OAuth dans l'UX, bien que cela fonctionnera de cette façon en dessous.

De quoi avez-vous besoin pour la déconnexion cross-origin ? Ne s'agirait-il pas d'une simple approche en deux étapes ? "page" de déconnexion pour supprimer le jeton d'accès stocké dans la console, puis rediriger vers la page de déconnexion générique où l'application Compte se déconnecte ? Ou voulez-vous cela sans redirection mais publier sur un point de terminaison de déconnexion ?

Une approche en deux étapes est acceptable. Ma préoccupation était que la déconnexion de l'application de compte doit être désactivée CSRF, ce qui signifie que toute personne disposant d'un lien de déconnexion pourrait inciter quelqu'un à se déconnecter de son compte. Ceci est également actuellement possible avec la pile v2 ( cliquez ici pour vous déconnecter ).
Je pense que pour l'instant c'est acceptable mais pas exactement la meilleure pratique.

J'ai fait pas mal de travail maintenant pour la nouvelle application de compte :

  • Composants et conteneurs refactorisés pouvant être utilisés par la console et l'application de compte
  • Implémentation de nouveaux designs (y compris la réactivité)
  • Paramètres de profil implémentés, y compris la photo de profil
  • Mise en place de la gestion des autorisations (consulter et révoquer)
  • Implémentation de la gestion des sessions (voir et révoquer)
  • Résolution d'un problème qui entraînait des rendus vierges lors de l'utilisation de dépendances de modules CSS partagés

Je l'ai fait en codant en dur un jeton d'accès, pour pouvoir utiliser l'API de la pile. Je suis actuellement incapable d'avancer avec une implémentation appropriée, car je ne sais pas quelle serait la meilleure façon d'obtenir un jeton d'accès pour l'application de compte.
À l'heure actuelle, "l'application oauth" n'est qu'un SPA qui se connecte aux points de terminaison d'authentification du serveur oauth (connexion, déconnexion et autres points de terminaison liés au compte qui n'ont pas besoin de jeton d'accès).
@htdvisser m'a mentionné que notre idée initiale était d'avoir l'application de compte en tant que client oauth distinct, en utilisant le type d'octroi de mot de passe. Je pense que nous devrions ouvrir une discussion à ce sujet, car:

  • selon la source, le type d'octroi de mot de passe est déconseillé, même pour les clients "officiels" et de confiance
  • cela nécessiterait un autre écran de connexion (à côté de l'écran de connexion du fournisseur oauth)
  • Je me demande s'il existe un moyen d'obtenir un jeton d'accès directement auprès du fournisseur oauth, sans avoir à utiliser un autre client séparé, car nous procédons déjà à l'authentification dans l'application oauth
  • si nous utilisons l'octroi de mot de passe pour l'application de compte, nous devrions également l'utiliser pour la console

J'ai déjà dit à @htdvisser que l'ensemble de l'aspect authentification/autorisation déléguée est quelque peu accablant pour moi et je ne me sens pas suffisamment informé pour être responsable d'une question aussi sensible à la sécurité.

Ce que nous devrions viser, c'est un flux qui donne l'impression que le flux d'authentification de nos clients officiels ressemble à une authentification native (voir aussi mon autre commentaire ), ce qui signifie que les connexions et les déconnexions sont globales et qu'il ne devrait y avoir aucune distinction entre l'état authentifié des clients et le fournisseur d'autorisation.

J'aurais donc besoin d'aide et de commentaires pour continuer avec l'application de compte. Comment pouvons-nous coordonner cela?

selon la source, le type d'octroi de mot de passe est déconseillé, même pour les clients "officiels" et de confiance

Oui, l'octroi de mot de passe ne doit pas être utilisé, voir les spécifications et le raisonnement ici : https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section -3.4

Actuellement bloqué par #2148

Donc, après avoir été impliqué dans cela pendant un certain temps maintenant, je pense que j'ai besoin d'informations.

L'idée originale de l'application de compte était de remplacer l'application oauth actuelle et d'étendre les fonctionnalités à la gestion des profils et des sessions (voir OP). Le problème est que pour implémenter une telle fonctionnalité, l'application aurait besoin d'un jeton d'accès, ce qui signifie essentiellement que l'application de compte serait à la fois un fournisseur et un client OAuth.

Mon idée était d'introduire un nouveau client OAuth ( account ) et au niveau du frontend, pour mélanger les fonctionnalités avec l'application OAuth actuelle. Pour l'utilisateur, il semblerait que le fournisseur OAuth (connexion, enregistrement, validation du compte, etc.) et le client de l'application de compte (paramètres de profil, gestion de session, gestion des autorisations) soient une seule et même application, tandis qu'en arrière-plan, il est une séparation technique entre le fournisseur OAuth et le client. Sur le backend, le client du compte deviendrait une partie du package oauth . En ce qui concerne le frontend, nous pourrions également traiter les deux éléments comme la même application, en utilisant le même point d'entrée ( account.js ).
De même, le routage refléterait ce mélange, par exemple :

  • /account/login pour la connexion oauth [couche fournisseur OAuth]
  • /account/register pour l'enregistrement de l'utilisateur [couche fournisseur OAuth]
  • /account/forgot-password pour l'enregistrement de l'utilisateur [couche fournisseur OAuth]
  • /account/client/login/ttn-stack pour la connexion client (autorisation) [couche client OAuth]
  • /account/client/oauth/callback pour échanger le code d'authentification [couche client OAuth]
  • /account page de présentation du client oauth [couche client OAuth]

Alternativement, nous pourrions séparer les deux préoccupations, en laissant le fournisseur OAuth ( /oauth via pkg/oauth ) tel quel et en traitant l'application de compte ( /account via pkg/account ) comme une chose complètement distincte, comme nous le faisons avec la console. Le fournisseur OAuth serait alors uniquement responsable des questions d'authentification, y compris l'autorisation et l'enregistrement du compte utilisateur, mais n'aurait pas sa propre vue authentifiée comme il l'a actuellement. Au lieu de cela, après la connexion, il redirigerait vers l'application de compte par défaut, qui récupérerait alors automatiquement un jeton.

J'ai l'impression que la première solution pourrait éviter une partie de la confusion que nous avons actuellement autour de l'authentification et de la gestion des comptes, mais je ne peux pas prévoir si cela pourrait introduire d'autres complications. La deuxième solution semble plus propre, mais la question est de savoir comment communiquer/marquer la séparation. Par exemple, les deux doivent-ils toujours être communiqués en tant qu'« application de compte » ? Ou devrait-il s'agir du The Things Stack Single Sign On et du The Things Stack Account Application ?

Merci de me faire part de vos avis.

Hmm, en prenant du recul, quel est le but de faire de l'application de compte un client OAuth ? Quelle fonctionnalité via OAuth voulons-nous là-dedans ?

  • Paramètres du profil (nom, e-mail, photo de profil)
  • Gestion des sessions (revue, révocation)
  • Gestion des autorisations (réviser, révoquer)
  • (Potentiellement d'autres méta-paramètres liés à TTES à l'avenir)

Tous ces éléments nécessitent un jeton d'accès, car c'est le seul moyen d'autoriser les RPC respectifs.

Nous avons besoin d'une séparation du fournisseur OAuth - qui pourrait être externe, par exemple "The Things Network Community" - et de la gestion des utilisateurs - qui consiste à gérer les champs de l'entité User stockés avec The Things Stack, y compris les points @kschiffer a écrit dans le commentaire ci-dessus.

Nos points /api/v3/* terminaison

  • Paramètres du profil (nom, e-mail, photo de profil)
  • Gestion des sessions (revue, révocation)
  • Gestion des autorisations (réviser, révoquer)
  • (Potentiellement d'autres méta-paramètres liés à TTES à l'avenir)

Tous ces éléments nécessitent un jeton d'accès, car c'est le seul moyen d'autoriser les RPC respectifs.

Nous pourrions également en faire une partie de la console, mais cela signifierait que la console mélangerait les préoccupations dans une certaine mesure. Je pouvais voir des situations où il serait préférable d'effectuer la gestion des comptes sans les frais généraux de toutes les autres fonctionnalités de la console, mais c'est peut-être moi qui sur-ingénie cela 🤷‍♂️.

Généralement, la question serait de savoir si nous voulons voir la console uniquement comme un outil pour gérer les problèmes liés au réseau. Nous pouvons soit l'ouvrir pour en faire une plate-forme de gestion à usage général pour toutes les questions liées au TTS, soit être plus atomique et respecter la séparation et utiliser différentes applications/clients pour différentes préoccupations. C'est une question stratégique. Je vois des cas pour les deux.

Je ne pense pas que la console (toutes les consoles, car il y a une console dans chaque cluster) devrait avoir tous les droits sur l'utilisateur. Les consoles ne doivent pas être utilisées pour gérer les clients OAuth autorisés, les sessions, l'adresse e-mail principale, les coordonnées. Avoir une application de gestion des utilisateurs dédiée (l'application de compte) est bien mieux.

En effet, bon point. Puis on revient à la question initiale .

Mon avis est :

Approche mixte :

  • À partir d'un POV utilisateur moins déroutant (un emplacement pour toutes les questions liées au compte)
  • Image de marque / communication plus facile
  • Conforme au plan d'origine de l'application de compte
  • Côté frontend, nous n'avons pas besoin d'un nouveau point d'entrée et donc d'un passe-partout séparé
  • La mise en œuvre devient plus complexe/déroutante (l'application de compte étant le fournisseur et le client oauth)

Approche séparée :

  • Mise en œuvre plus propre et plus conventionnelle
  • Configuration plus flexible et plus claire
  • Introduit une nouvelle application à côté de l'application oauth, qui nécessite une image de marque et une communication sensées
  • Des versions plus longues (peut-être marginales, n'ont pas été testées) et plus d'actifs

Je penche pour l'approche mixte.

  • Paramètres du profil (nom, e-mail, photo de profil)
  • Gestion des sessions (revue, révocation)
  • Gestion des autorisations (réviser, révoquer)
  • (Potentiellement d'autres méta-paramètres liés à TTES à l'avenir)

Ceci est une application de compte, n'est-ce pas ? Pas OAuth ?

  • Introduit une nouvelle application à côté de l'application oauth, qui nécessite une image de marque et une communication sensées

A quoi sert l'application OAuth alors ?

Pouvez-vous répertorier les fonctionnalités pour l'utilisateur de ce que le client OAuth ajoute à l'application de compte, que nous ne pouvons pas créer dans l'application de compte, potentiellement via de nouveaux points de terminaison ?

Ceci est une application de compte, n'est-ce pas ? Pas OAuth ?

Oui, il s'agit d'une application de compte. Mais le plan était que ce que nous avons actuellement en tant qu'application OAuth fasse partie de l'application de compte.

A quoi sert l'application OAuth alors ?

Pour l'authentification (dans le cadre du flux OAuth), l'enregistrement de l'utilisateur, l'autorisation du client, la réinitialisation du mot de passe. Fondamentalement, tout ce qui concerne l'authentification des utilisateurs et l'autorisation des clients.

Pouvez-vous répertorier les fonctionnalités pour l'utilisateur de ce que le client OAuth ajoute à l'application de compte, que nous ne pouvons pas créer dans l'application de compte, potentiellement via de nouveaux points de terminaison ?

Le problème est plutôt l'inverse, nous ne pouvons pas simplement étendre notre application OAuth actuelle avec les fonctionnalités que nous voulons pour l'application de compte, car nous aurions besoin d'un jeton d'accès. C'est un peu un problème de poule et d'œuf. S'il existait un moyen d'autorisation différent pour les fonctionnalités de l'application de compte (sessions, autorisations, etc.), par exemple via le cookie de session que possède l'application OAuth, ce serait différent. Mais d'après ce que je vois, c'est irréalisable.

L'application OAuth est-elle autonome ? Met-il en œuvre les flux de redirection pour les clients OAuth ? Ou est-ce un client OAuth lui-même ?


J'insiste sur le mien :

Mon idée était d'introduire un nouveau client OAuth ( account ) et au niveau du frontend, pour mélanger les fonctionnalités avec l' application OAuth actuelle . Pour l'utilisateur, il semblerait que le fournisseur OAuth (connexion, enregistrement, validation du compte, etc.) et le client de l'application de compte (paramètres de profil, gestion de session, gestion des autorisations) soient une seule et même application, tandis qu'en arrière-plan, il est une séparation technique entre le fournisseur OAuth et le client . Sur le backend , le compte client deviendrait une partie du package oauth .

je vois ici;

  • Client OAuth
  • application OAuth actuelle
  • Fournisseur OAuth
  • le client de l'application de compte
  • le fournisseur OAuth
  • le client
  • le backend
  • le compte client
  • le forfait oauth

J'essaie de comprendre la proposition, mais je ne comprends pas tout à fait ce qui est encore.

Alors, quelles sont les fonctionnalités que nous voulons?

  1. Créer un compte
  2. Mot de passe oublié
  3. Connexion
  4. Changer le mot de passe
  5. Afficher et modifier le profil
  6. Gérer les sessions
  7. Trucs OAuth

    1. Écran de consentement (flux de code d'autorisation OAuth)

    2. Gérer les autorisations OAuth

Je suppose que 1-6 peut être implémenté sans toucher du tout à OAuth, si nous utilisons l'authentification de session. C'est possible, non ?

Ouais désolé. Nous avons ici un certain nombre de termes non fixés qui rendent assez difficile l'explication des choses. Au moins, cela donne un bon aperçu de la complexité de la question 😅.

Alors prenons le statu quo :

Fournisseur OAuth
L'entité qui fournit l'autorisation (et dans notre cas également l'authentification) selon la spécification OAuth 2.0. Dans notre cas, il s'agit du package pkg/oauth , qui utilise à son tour l'application OAuth (voir ci-dessous) pour implémenter l'interface utilisateur nécessaire pour obtenir les informations utilisateur (rendu de connexion, enregistrement, vues d'autorisation, etc.).

Application OAuth
Il s'agit de l'application Web de réaction sur le frontend. Notre code frontal se compose de différentes applications (avec différents points d'entrée oauth.js / console.js ) qui partagent des parties communes telles que les composants réactifs et les utilitaires

Client OAuth
Un client enregistré qui utilise OAuth pour l'authentification et l'autorisation, comme la console ou la CLI.

paquet oauth
Le package Go responsable de l'implémentation du fournisseur OAuth. C'est pkg/oauth .

Donc, vous voyez, il y a trois ou quatre couches différentes en jeu ici. Le problème est que si nous maintenons la façon dont nous procédons à l'autorisation pour le moment, nous aurions besoin d'avoir quelque chose qui joue tous les rôles décrits ci-dessus en même temps.

Je suppose que 1-6 peut être implémenté sans toucher du tout à OAuth, si nous utilisons l'authentification de session. C'est possible, non ?

Oui. 1-4 sont déjà possibles sans oauth / access token. 5 et 6 ont actuellement besoin d'un jeton d'accès. 7. ii n'est pas encore mis en œuvre. Si 5 et 6 étaient possibles sans jeton d'accès, nous n'aurions en effet pas besoin d'un autre client oauth pour le faire. Nous devons néanmoins considérer que chaque fonctionnalité que nous pourrions vouloir ajouter à l'application de compte à l'avenir ne doit alors pas utiliser le jeton d'accès comme seul moyen d'autorisation.

Si 5 et 6 étaient possibles sans jeton d'accès, nous n'aurions en effet pas besoin d'un autre client oauth pour le faire. Nous devons néanmoins considérer que chaque fonctionnalité que nous pourrions vouloir ajouter à l'application de compte à l'avenir ne doit alors pas utiliser le jeton d'accès comme seul moyen d'autorisation.

À droite. Cela a beaucoup de sens pour moi. C'est également une meilleure base pour le "mode sudo", où les utilisateurs peuvent faire des choses _uniquement_ dans l'application de compte, après avoir ressaisi votre mot de passe par exemple. Alors oui, il peut y avoir un certain chevauchement entre ce que les clients OAuth et l'application de compte peuvent faire, mais ce chevauchement ne me semble pas important. Je vois l'intérêt de garder les choses dédiées à l'application de compte.

D'accord, ça sonne bien.
@htdvisser Avez-vous des objections ? Et sinon, pouvez-vous m'indiquer les fichiers/paquets relatifs pour autorisation, car je suppose que vous n'aurez pas le temps de travailler dessus de sitôt (?).

Comme je l'ai déjà dit, nos points /api/v3/* terminaison


Notre API est entièrement gRPC, et l'authentification est effectuée avec l'en-tête Authorization , qui est propagé à gRPC en tant que métadonnées de requête. La mise en œuvre de l'authentification de session pourrait ressembler à ceci :

  • Ajoutez un type SessionToken à pkg/auth/auth.go
  • Ajoutez une partie secrète au modèle Session , similaire à ce que nous faisons avec les clés API et les jetons d'accès.
  • Ajoutez un middleware qui extrait l'ID de session et le secret de session du cookie et les transfère dans l'en-tête Authorization en tant que SessionToken
  • Ajoutez SessionToken en case au switch tokenType { en pkg/identityserver/entity_access.go

Une chose à considérer ici est que cela signifie également que l'application de compte et l'API v3 doivent être servies à partir de la même origine. Sinon, l'authentification par cookie ne fonctionnerait pas car le contexte d'authentification comprend différentes origines.
Je ne sais pas à quel point c'est acceptable. Au moins en pratique, nous semblons utiliser les mêmes origines dans nos déploiements.

Oui, ils seront sur la même origine.

@kschiffer s'il vous plaît laissez-nous savoir comment nous pouvons débloquer les progrès ici.

OK, continuons cette conversation ici.

@kschiffer Après avoir travaillé un peu dessus :

  • La partie frontale de l'application oauth consisterait essentiellement en l'écran d'autorisation uniquement

Oui

  • Je pense que c'est très ennuyeux de devoir conserver les configurations is.oauth.ui.* juste pour ça
    [...]
  • Je suis également un peu incertain des restrictions exactes sur la façon dont nous pouvons modifier la configuration de la pile sans casser le CC
  • Je n'ai pas de chance de trouver une solution viable ici et j'ai vraiment besoin d'informations

Nous ne pouvons pas casser la configuration dans la V3, mais nous pouvons introduire une nouvelle configuration, déprécier l'ancienne configuration, utiliser l'ancienne configuration comme solution de secours et déposer un problème TODO intitulé bump/major pour supprimer l'ancienne configuration.

Ma suggestion serait donc d'introduire une nouvelle configuration qui remplacerait complètement et activerait la nouvelle application de compte. Pour une compatibilité descendante, cela devrait fonctionner sans que l'utilisateur ne spécifie cette nouvelle configuration, c'est-à-dire s'appuyer sur des valeurs par défaut saines et sur l'ancienne configuration via is.oauth.ui.* .

@kschiffer quel est le statut ici ?

Rebasant actuellement mon travail sur le nouvel échafaudage, qui est en cours ici : #3453

La prochaine étape consiste à rebaser, corriger et appliquer les vues authentifiées et à ajuster les conceptions actuelles à la nouvelle image de marque.

@kschiffer quel est le statut ici ?

L'application de compte a été introduite en 3.11. Il manque actuellement :

  • Changement de compte #488
  • Gestion des sessions
  • Gestion des autorisations (iirc cela inclut également l'ajout de points de terminaison d'API)

D'ACCORD. https://github.com/TheThingsNetwork/lorawan-stack/issues/488 est déjà fermé, semble-t-il.

Cela a été un gros problème. Pouvez-vous déposer un ou deux nouveaux problèmes pour ce qui précède pour remplacer celui-ci, afin qu'il puisse être fermé ?

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

w4tsn picture w4tsn  ·  6Commentaires

ecities picture ecities  ·  5Commentaires

htdvisser picture htdvisser  ·  9Commentaires

MatteMoveSRL picture MatteMoveSRL  ·  7Commentaires

bafonins picture bafonins  ·  5Commentaires