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.
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
la toile
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 :
J'ai créé trois wireframes qui donnent une idée de la façon dont j'envisage l'application de compte :Voir les wireframes
(notez le sélecteur de compte intégré dans la liste déroulante des utilisateurs en haut à droite)
Oui. @johanstokking @htdvisser , veuillez me faire savoir si vous pensez qu'il est bon de continuer.
En ce qui concerne l'ensemble du problème de confusion connexion/déconnexion entre la console et le fournisseur oauth, voici mon plan :
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)/console/login
/account/login
, lorsqu'elle n'a pas de jeton d'accès (valide)/users/logout
qui déclenchera une déconnexion à laquelle on peut se référer de n'importe où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 :
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:
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 ?
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 :
Approche séparée :
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 packageoauth
.
je vois ici;
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?
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 :
SessionToken
à pkg/auth/auth.go
Session
, similaire à ce que nous faisons avec les clés API et les jetons d'accès.Authorization
en tant que SessionTokenSessionToken
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.
J'ai écrit un résumé ici : https://github.com/TheThingsNetwork/lorawan-stack/pull/2850#issuecomment -657497193
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 :
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é ?