Actualmente tenemos muchos problemas que giran en torno a nuestro flujo de OAuth, el cambio de cuenta, la gestión de tokens, la marca respectiva, etc. Este es un intento de hacer que todos estos sean más procesables bajo una nueva aplicación account
que se encargará de todas estas preocupaciones.
Una aplicación que actúa como proveedor de OAuth y una interfaz de usuario de configuración de marca y con todas las funciones en torno a todas las preocupaciones de cuenta y autenticación.
Web
Creo que un gran problema con la implementación actual es la falta de claridad y contexto para el usuario. Es difícil reconocer la aplicación OAuth como una entidad de autenticación independiente. Las razones son:
Creé tres esquemas que dan una idea de cómo imagino la aplicación de la cuenta:Ver esquemas
(Observe el conmutador de cuenta integrado en el menú desplegable del usuario en la parte superior derecha)
Si. @johanstokking @htdvisser , hágame saber si cree que es bueno continuar.
Con respecto a todo el problema de confusión de inicio/cierre de sesión entre la consola y el proveedor de autenticación, este es mi plan:
Account
separado para la aplicación de la cuenta (en lugar del logotipo TTS) y usamos el mismo componente de encabezado que también usamos para la consola (cc @pierreph)/console/login
/account/login
, cuando no tenga un token de acceso (válido)/users/logout
que activará un cierre de sesión al que se puede hacer referencia desde cualquier lugarSi no escucho ninguna queja sobre este plan, comenzaré a implementarlo.
Suena como un gran plan. Acepto que no necesitamos un cierre de sesión explícito de la consola y permanecer conectado a través de OAuth en el UX, aunque funcionará de esa manera en la parte inferior.
¿Qué necesita para el cierre de sesión de origen cruzado? ¿No sería un simple enfoque de dos pasos; Cerrar sesión en la "página" para eliminar el token de acceso almacenado en la Consola, luego redirigir a la página de cierre de sesión genérica donde la aplicación de la cuenta cierra la sesión. ¿O desea esto sin redirección pero publicar en un punto final de cierre de sesión?
Para el cierre de sesión, podemos inspirarnos en el cierre de sesión de OpenID Connect. Puede encontrar un buen resumen aquí: https://medium.com/@robert.broeckelmann/openid -connect-logout-eccc73df758f
Suena como un gran plan. Acepto que no necesitamos un cierre de sesión explícito de la consola y permanecer conectado a través de OAuth en el UX, aunque funcionará de esa manera en la parte inferior.
¿Qué necesita para el cierre de sesión de origen cruzado? ¿No sería un simple enfoque de dos pasos; Cerrar sesión en la "página" para eliminar el token de acceso almacenado en la Consola, luego redirigir a la página de cierre de sesión genérica donde la aplicación de la cuenta cierra la sesión. ¿O desea esto sin redirección pero publicar en un punto final de cierre de sesión?
El enfoque de dos pasos está bien. Mi preocupación era que el cierre de sesión de la aplicación de la cuenta debe estar deshabilitado CSRF, lo que significa que cualquier persona con un enlace de cierre de sesión podría atraer a alguien para que cierre sesión en su cuenta. Actualmente, esto también es posible con la pila v2 (al hacer clic aquí se cerrará la sesión ).
Creo que por ahora esto es aceptable pero no exactamente la mejor práctica.
He hecho bastante trabajo ahora para la nueva aplicación de cuenta:
Hice esto codificando un token de acceso para poder usar la API de pila. Actualmente no puedo avanzar con una implementación adecuada, ya que no sé cuál sería la mejor manera de obtener un token de acceso para la aplicación de la cuenta.
En este momento, la "aplicación de autenticación" es solo un SPA que se conecta a los puntos finales de autenticación del servidor de autenticación (inicio de sesión, cierre de sesión y otros puntos finales relacionados con la cuenta que no necesitan un token de acceso).
@htdvisser me mencionó que nuestra idea inicial era tener la aplicación de la cuenta como un cliente de autenticación independiente, usando el tipo de concesión de contraseña. Creo que deberíamos abrir una discusión sobre esto, ya que:
Ya le dije a @htdvisser que todo el aspecto de autenticación/autorización delegado de esto es algo abrumador para mí y no me siento lo suficientemente informado como para ser responsable de un asunto tan sensible a la seguridad.
Lo que debemos buscar es un flujo que haga que el flujo de autenticación de nuestros clientes oficiales se sienta como una autenticación nativa (ver también mi otro comentario ), lo que significa que los inicios y cierres de sesión son globales y no debe haber distinción entre el estado autenticado de los clientes y el proveedor de la autorización.
Por lo tanto, necesitaría ayuda e información para continuar con la aplicación de la cuenta. ¿Cómo podemos coordinar esto?
dependiendo de la fuente, se desaconseja el tipo de concesión de contraseña, incluso para clientes "oficiales" y de confianza
Sí, no se debe utilizar la concesión de contraseña, consulte la especificación y el razonamiento aquí: https://tools.ietf.org/html/draft-ietf-oauth-security-topics-13#section -3.4
Actualmente bloqueado por #2148
Entonces, después de estar involucrado en esto por un tiempo, creo que necesito algo de información.
La idea original de la aplicación de la cuenta era reemplazar la aplicación Oauth actual y ampliar la funcionalidad hacia la gestión de perfiles y sesiones (ver OP). El problema con esto es que para implementar dicha funcionalidad, la aplicación necesitaría un token de acceso, lo que significa esencialmente que la aplicación de la cuenta sería tanto un proveedor como un cliente de OAuth.
Mi idea era presentar un nuevo cliente de OAuth ( account
) y la interfaz, para combinar la funcionalidad con la aplicación OAuth actual. Para el usuario, parecería que tanto el proveedor de OAuth (inicio de sesión, registro, validación de la cuenta, etc.) como el cliente de la aplicación de la cuenta (configuración del perfil, gestión de la sesión, gestión de la autorización) son la misma aplicación, mientras que en segundo plano hay es una separación técnica entre el proveedor de OAuth y el cliente. En el backend, el cliente de la cuenta se convertiría en parte del paquete oauth
. En cuanto a la interfaz, también podríamos tratar ambas cosas como la misma aplicación, utilizando el mismo punto de entrada ( account.js
).
Asimismo, el enrutamiento reflejaría esta combinación, por ejemplo:
/account/login
para el inicio de sesión de OAuth [capa de proveedor de OAuth]/account/register
para registro de usuario [capa de proveedor OAuth]/account/forgot-password
para registro de usuario [capa de proveedor OAuth]/account/client/login/ttn-stack
para el inicio de sesión del cliente (autorización) [capa de cliente OAuth]/account/client/oauth/callback
para intercambiar el código de autenticación [capa de cliente OAuth]/account
página de descripción general del cliente OAuth [capa de cliente OAuth]Alternativamente, podríamos mantener ambas preocupaciones separadas, dejando el proveedor de OAuth ( /oauth
través de pkg/oauth
) como está y tratando la aplicación de la cuenta ( /account
través de pkg/account
) como algo completamente independiente, como hacemos con la consola. Entonces, el proveedor de OAuth solo sería responsable de los asuntos de autenticación, incluida la autorización y el registro de la cuenta de usuario, pero no tendría una vista autenticada propia como la que tiene actualmente. En cambio, después del inicio de sesión, se redirigiría a la aplicación de la cuenta de forma predeterminada, que luego recuperaría un token automáticamente.
Siento que la primera solución podría evitar parte de la confusión que actualmente tenemos en torno a la autenticación y la administración de cuentas, pero no puedo prever si podría presentar otras complicaciones. La segunda solución parece más limpia, pero la pregunta es cómo comunicar/marcar la separación. Por ejemplo, ¿ambos deberían comunicarse como "Aplicación de cuenta" todavía? ¿O deberían ser los The Things Stack Single Sign On
y The Things Stack Account Application
?
Por favor, hágame saber sus opiniones.
Hmm, retrocediendo un paso, ¿cuál es el propósito de hacer que la aplicación de la cuenta sea un cliente OAuth? ¿Qué funcionalidad a través de OAuth queremos allí?
Todos ellos requieren un token de acceso, ya que esa es la única forma de autorizar los respectivos RPC.
Necesitamos una separación del proveedor de OAuth, que podría ser externo, por ejemplo, "The Things Network Community", y la administración de usuarios, que se trata de administrar los campos de la entidad de usuario almacenados con The Things Stack, incluidos los puntos @kschiffer. escribió en el comentario de arriba.
Nuestros terminales /api/v3/*
no aceptan autenticación de cookies porque están habilitados para CORS. Solo funcionan con claves API y tokens de acceso.
- Configuración del perfil (nombre, correo electrónico, foto de perfil)
- Gestión de sesiones (revisar, revocar)
- Gestión de autorizaciones (revisar, revocar)
- (Posiblemente otras metaconfiguraciones relacionadas con TTES en el futuro)
Todos ellos requieren un token de acceso, ya que esa es la única forma de autorizar los respectivos RPC.
También podríamos hacer que estos formen parte de la consola, pero eso significaría que la consola mezclaría preocupaciones hasta cierto punto. Podría ver situaciones en las que sería mejor realizar la administración de cuentas sin la sobrecarga de todas las demás funcionalidades de la consola, pero tal vez soy yo quien está haciendo un exceso de ingeniería en esto 🤷♂️.
En general, la pregunta sería si queremos ver la consola solo como una herramienta para administrar asuntos relacionados con la red. Podemos abrirlo para que sea una plataforma de administración de propósito general para todos los asuntos relacionados con TTS o podemos ser más atómicos y mantener la separación y usar diferentes aplicaciones/clientes para diferentes preocupaciones. Es una cuestión estratégica. Veo casos para los dos.
No creo que la consola (todas las consolas, porque hay una consola en cada clúster) deba tener plenos derechos sobre el usuario. Las consolas no deben usarse para administrar clientes OAuth autorizados, sesiones, dirección de correo electrónico principal, información de contacto. Tener una aplicación de gestión de usuarios dedicada (la aplicación de la cuenta) es mucho mejor.
De hecho, buen punto. Entonces se vuelve a la pregunta inicial .
Mi opinión es:
Enfoque mixto:
Enfoque separado:
Me inclino por el enfoque mixto.
- Configuración del perfil (nombre, correo electrónico, foto de perfil)
- Gestión de sesiones (revisar, revocar)
- Gestión de autorizaciones (revisar, revocar)
- (Posiblemente otras metaconfiguraciones relacionadas con TTES en el futuro)
Esta es la aplicación de cuenta, ¿verdad? ¿No es OAuth?
- Presenta una nueva aplicación junto a la aplicación oauth, que necesita una marca y una comunicación sensatas
¿Para qué sirve la aplicación OAuth entonces?
¿Puede enumerar las características para el usuario de lo que el cliente de OAuth agrega a la aplicación de la cuenta, que no podemos crear en la aplicación de la cuenta, posiblemente a través de nuevos puntos finales?
Esta es la aplicación de cuenta, ¿verdad? ¿No es OAuth?
Sí, esta es la aplicación de cuenta. Pero el plan era que lo que tenemos actualmente como aplicación OAuth pase a formar parte de la aplicación de la cuenta.
¿Para qué sirve la aplicación OAuth entonces?
Para autenticación (como parte del flujo OAuth), registro de usuarios, autorización de clientes, restablecimiento de contraseña. Básicamente todo lo que tiene que ver con autenticación de usuarios y autorización de clientes.
¿Puede enumerar las características para el usuario de lo que el cliente de OAuth agrega a la aplicación de la cuenta, que no podemos crear en la aplicación de la cuenta, posiblemente a través de nuevos puntos finales?
El problema es más bien al revés, no podemos simplemente extender nuestra aplicación OAuth actual con las funcionalidades que queremos para la aplicación de la cuenta, ya que necesitaríamos obtener un token de acceso. Es un poco el problema del huevo y la gallina. Si hubiera un medio diferente de autorización para las funcionalidades de la aplicación de la cuenta (sesiones, autorizaciones, etc.), por ejemplo, a través de la cookie de sesión que tiene la aplicación OAuth, entonces sería diferente. Pero por lo que veo esto es inviable.
¿La aplicación OAuth es algo independiente? ¿Está implementando los flujos de redirección para los clientes de OAuth? ¿O es un cliente de OAuth en sí mismo?
Énfasis mío:
Mi idea era presentar un nuevo cliente OAuth (
account
) y frontend, para combinar la funcionalidad con la aplicación OAuth actual . Para el usuario, parecería que tanto el proveedor de OAuth (inicio de sesión, registro, validación de la cuenta, etc.) como el cliente de la aplicación de la cuenta (configuración del perfil, gestión de la sesión, gestión de la autorización) son la misma aplicación, mientras que en segundo plano hay es una separación técnica entre el proveedor de OAuth y el cliente . En el backend , el cliente de la cuenta se convertiría en parte del paqueteoauth
.
veo aquí;
oauth
Estoy tratando de entender la propuesta, pero todavía no entiendo completamente qué es qué.
Entonces, ¿cuáles son las características que queremos?
Supongo que 1-6 se puede implementar sin tocar OAuth en absoluto, si optamos por la autenticación de sesión. Eso es posible, ¿verdad?
si lo siento Tenemos una serie de términos no fijados aquí que hacen bastante difícil explicar las cosas. Al menos da una buena idea de la complejidad del problema 😅.
Así que tomemos el statu quo:
proveedor de OAuth
La entidad que proporciona la autorización (y en nuestro caso también la autenticación) según la especificación OAuth 2.0. En nuestro caso, ese es el paquete pkg/oauth
, que a su vez usa la aplicación OAuth (ver más abajo) para implementar la interfaz de usuario necesaria para obtener información del usuario (renderizar inicio de sesión, registro, vistas de autorización, etc.).
aplicación OAuth
Esta es la aplicación web de reacción en la interfaz. Nuestro código de interfaz consta de diferentes aplicaciones (con diferentes puntos de entrada oauth.js
/ console.js
) que comparten partes comunes, como componentes de reacción y utilidades
cliente OAuth
Un cliente registrado que usa OAuth para autenticación y autorización, como la consola o la CLI.
paquete de autenticación
El paquete Go que es responsable de implementar el proveedor de OAuth. Eso es pkg/oauth
.
Como puede ver, hay tres o cuatro capas diferentes en juego aquí. El problema es que si mantenemos la forma en que hacemos la autorización en este momento, necesitaríamos tener algo que desempeñe todos los roles descritos anteriormente al mismo tiempo.
Supongo que 1-6 se puede implementar sin tocar OAuth en absoluto, si optamos por la autenticación de sesión. Eso es posible, ¿verdad?
Si. 1-4 ya son posibles sin oauth/token de acceso. 5 y 6 actualmente necesitan un token de acceso. 7. ii aún no se ha implementado. Si 5 y 6 fueran posibles sin token de acceso, entonces no necesitaríamos otro cliente de autenticación para hacer esto. Aún así, debemos considerar que cada funcionalidad que queramos agregar a la aplicación de la cuenta en el futuro no debe usar el token de acceso como único medio de autorización.
Si 5 y 6 fueran posibles sin token de acceso, entonces no necesitaríamos otro cliente de autenticación para hacer esto. Aún así, debemos considerar que cada funcionalidad que queramos agregar a la aplicación de la cuenta en el futuro no debe usar el token de acceso como único medio de autorización.
Correcto. Esto tiene mucho sentido para mí. Esta es también una mejor base para el "modo sudo", donde los usuarios pueden hacer cosas _solo_ en la aplicación de la cuenta, después de volver a ingresar su contraseña, por ejemplo. Entonces, sí, puede haber cierta superposición entre lo que pueden hacer los clientes de OAuth y la aplicación de la cuenta, pero esa superposición no me parece grande. Veo valor en mantener las cosas dedicadas a la aplicación de la cuenta.
Bueno suena bien.
@htdvisser ¿Tiene alguna objeción? Y si no, ¿puede indicarme los archivos/paquetes relativos para la autorización, porque supongo que no tendrá tiempo para trabajar en esto pronto (?).
Como comenté antes, nuestros terminales /api/v3/*
no aceptan la autenticación de cookies porque están habilitados para CORS. Si desea comenzar a aceptar la autenticación de cookies, debe observar detenidamente nuestros encabezados CORS, porque realmente no queremos que un atacante realice solicitudes de origen cruzado autenticadas por cookies a estos puntos finales.
Nuestra API es gRPC y la autenticación se realiza con el encabezado Authorization
, que se propaga a gRPC como metadatos de solicitud. La implementación de la autenticación de sesión podría verse así:
SessionToken
a pkg/auth/auth.go
Session
, similar a lo que hacemos con las claves API y los tokens de acceso.Authorization
como un token de sesión.SessionToken
como case
a los switch tokenType {
en pkg/identityserver/entity_access.go
Una cosa a considerar aquí es que esto también significa que la aplicación de la cuenta y la API v3 deben servirse desde el mismo origen. De lo contrario, la autenticación de cookies no funcionaría ya que el contexto de autenticación comprende diferentes orígenes.
No estoy seguro de cuán aceptable es eso. Al menos en la práctica, parece que estamos usando los mismos orígenes en nuestras implementaciones.
Sí, estarán en el mismo origen.
@kschiffer , háganos saber cómo podemos desbloquear el progreso aquí.
Escribí un resumen aquí: https://github.com/TheThingsNetwork/lorawan-stack/pull/2850#issuecomment -657497193
OK, continuemos esa conversación aquí.
@kschiffer Después de trabajar un poco en esto:
- La parte frontal de la aplicación oauth básicamente consistiría solo en la pantalla de autorización
sí
- Creo que es muy molesto tener que conservar las configuraciones de
is.oauth.ui.*
solo por eso
[...]- También estoy un poco inseguro acerca de las restricciones exactas de cómo podemos alterar la configuración de la pila sin romper el CC
- No tengo suerte al encontrar una solución viable aquí y realmente necesito alguna información.
No podemos romper la configuración en V3, pero podemos introducir una nueva configuración, desaprobar la configuración anterior, usar la configuración anterior como alternativa y presentar un problema TODO etiquetado como bump/major
para eliminar la configuración anterior.
Entonces, mi sugerencia sería introducir una nueva configuración que sería un reemplazo completo y habilitaría la aplicación de la nueva cuenta. Para la compatibilidad con versiones anteriores, debería funcionar sin que el usuario especifique esta nueva configuración, es decir, confiar en los valores predeterminados sanos y la configuración anterior a través de is.oauth.ui.*
.
@kschiffer ¿cuál es el estado aquí?
Actualmente rebasando mi trabajo en el nuevo andamio, que está en curso aquí: #3453
El siguiente paso es reorganizar, arreglar y PRing las vistas autenticadas y ajustar los diseños actuales a la nueva marca.
@kschiffer ¿cuál es el estado aquí?
La aplicación de cuenta se introdujo en 3.11. Actualmente todavía faltan:
está bien. https://github.com/TheThingsNetwork/lorawan-stack/issues/488 ya está cerrado, parece.
Este ha sido un gran problema. ¿Puede presentar uno o dos problemas nuevos para el anterior para reemplazar este, para que pueda cerrarse?