tutorial react examples apps app meteor

react - ¿Cómo agregar inicios de sesión de servicios externos a una cuenta ya existente en Meteor?



meteor tutorial (4)

Aquí es cómo agrego las credenciales a la cuenta de usuario existente: ... / meteor-how-to-login-with-github-account.html

Después de haber creado una página de perfil para mi aplicación, me gustaría mostrar una lista de los servicios sociales en los que se encuentra el usuario. Me sorprendió que la forma más fácil sería utilizar el sistema de cuentas integrado de Meteor para esto.

¿Hay una buena manera de agregar servicios externos a una cuenta existente?

Además, ¿podrá el usuario iniciar sesión con (por ejemplo) Facebook y su contraseña desde mi aplicación?

Otra pregunta que sigue naturalmente es: ¿hay una buena manera de agregar una contraseña específica de la aplicación a una cuenta que se creó con un servicio externo?


Aquí hay un método alternativo. En esta solución, estoy anulando una función central y agregando un comportamiento personalizado. Mi objetivo es asociar los datos del servicio con el usuario que está conectado en ese momento, luego permitir que la función principal haga su trabajo normal.

orig_updateOrCreateUserFromExternalService = Accounts.updateOrCreateUserFromExternalService; Accounts.updateOrCreateUserFromExternalService = function(serviceName, serviceData, options) { var loggedInUser = Meteor.user(); if(loggedInUser && typeof(loggedInUser.services[serviceName]) === "undefined") { var setAttr = {}; setAttr["services." + serviceName] = serviceData; Meteor.users.update(loggedInUser._id, {$set: setAttr}); } return orig_updateOrCreateUserFromExternalService.apply(this, arguments); }

Pros:

  • Evita la creación de cuentas innecesarias
  • El código es corto y fácil de entender
  • El código es fácil de eliminar si esta funcionalidad se agrega al núcleo Meteor

Contras:

  • Requiere que el usuario inicie sesión. Si un usuario inicia sesión con Twitter inicialmente, cierra la sesión y luego inicia sesión con Facebook, se crearán dos cuentas separadas.
  • Los usuarios que comparten una computadora pueden fusionar sus cuentas involuntariamente.
  • Se basa en el conocimiento de cómo funciona updateOrCreateUserFromExternalService. Esto no es terrible, porque es parte de la API pública de Meteor, probablemente no cambiará drásticamente (no de todos modos). Pero sigue siendo arriesgado.

Sí, una cuenta de usuario puede asociarse con múltiples servicios y tener un inicio de sesión basado en contraseña al mismo tiempo. En los documentos de Meteor , puede ver la estructura de dicha cuenta de usuario:

{ _id: "bbca5d6a-2156-41c4-89da-0329e8c99a4f", // Meteor.userId() username: "cool_kid_13", // unique name emails: [ // each email address can only belong to one user. { address: "[email protected]", verified: true }, { address: "[email protected]", verified: false } ], createdAt: 1349761684042, profile: { // The profile is writable by the user by default. name: "Joe Schmoe" }, services: { facebook: { id: "709050", // facebook id accessToken: "AAACCgdX7G2...AbV9AZDZD" }, resume: { loginTokens: [ { token: "97e8c205-c7e4-47c9-9bea-8e2ccc0694cd", when: 1349761684048 } ] } } }

Para agregar un nombre de usuario / contraseña de inicio de sesión a una cuenta existente, puede usar Accounts.sendResetPasswordEmail en el lado del servidor. Esto también asegura que el cambio ocurra autenticado y autorizado.

Por supuesto, también puede actualizar el registro del usuario en el servidor con una nueva contraseña usted mismo, pero esto podría crear un agujero de seguridad en su aplicación. También recomendaría no implementar su propio protocolo criptográfico para esto si es posible, ya que es difícil .

Si desea agregar otros servicios además del correo electrónico, podría, por ejemplo,

  1. llame a un método de servidor que guarda un token aleatorio y largo en el documento MongoDB del usuario actual y lo devuelve al cliente.
  2. Accounts.loginWith[OtherService] iniciar sesión en el usuario con otro servicio usando Accounts.loginWith[OtherService] . Esto registra al usuario y lo vuelve a iniciar, usando una cuenta nueva en el otro servicio.
  3. llamar a un segundo método de servidor con el token devuelto desde el primer método como parámetro. Este segundo método busca la cuenta de usuario con el token dado y fusiona sus datos en la cuenta actual (nueva).

Vea el ejemplo y responda en esta publicación. Más o menos te da el código para integrar múltiples cuentas externas e internas. Con ajustes menores, puede agregar los campos de contraseña para cada cuenta como lo desee.

Cómo usar Meteor.loginWithGoogle con mrt: accounts-ui-bootstrap-dropdown

Código:

isProdEnv = function () { if (process.env.ROOT_URL == "http://localhost:3000") { return false; } else { return true; } } Accounts.loginServiceConfiguration.remove({ service: ''google'' }); Accounts.loginServiceConfiguration.remove({ service: ''facebook'' }); Accounts.loginServiceConfiguration.remove({ service: ''twitter'' }); Accounts.loginServiceConfiguration.remove({ service: ''github'' }); if (isProdEnv()) { Accounts.loginServiceConfiguration.insert({ service: ''github'', clientId: ''00000'', secret: ''00000'' }); Accounts.loginServiceConfiguration.insert({ service: ''twitter'', consumerKey: ''00000'', secret: ''00000'' }); Accounts.loginServiceConfiguration.insert({ service: ''google'', appId: ''00000'', secret: ''00000'' }); Accounts.loginServiceConfiguration.insert({ service: ''facebook'', appId: ''00000'', secret: ''00000'' }); } else { // dev environment Accounts.loginServiceConfiguration.insert({ service: ''github'', clientId: ''11111'', secret: ''11111'' }); Accounts.loginServiceConfiguration.insert({ service: ''twitter'', consumerKey: ''11111'', secret: ''11111'' }); Accounts.loginServiceConfiguration.insert({ service: ''google'', clientId: ''11111'', secret: ''11111'' }); Accounts.loginServiceConfiguration.insert({ service: ''facebook'', appId: ''11111'', secret: ''11111'' }); } Accounts.onCreateUser(function (options, user) { if (user.services) { if (options.profile) { user.profile = options.profile } var service = _.keys(user.services)[0]; var email = user.services[service].email; if (!email) { if (user.emails) { email = user.emails.address; } } if (!email) { email = options.email; } if (!email) { // if email is not set, there is no way to link it with other accounts return user; } // see if any existing user has this email address, otherwise create new var existingUser = Meteor.users.findOne({''emails.address'': email}); if (!existingUser) { // check for email also in other services var existingGitHubUser = Meteor.users.findOne({''services.github.email'': email}); var existingGoogleUser = Meteor.users.findOne({''services.google.email'': email}); var existingTwitterUser = Meteor.users.findOne({''services.twitter.email'': email}); var existingFacebookUser = Meteor.users.findOne({''services.facebook.email'': email}); var doesntExist = !existingGitHubUser && !existingGoogleUser && !existingTwitterUser && !existingFacebookUser; if (doesntExist) { // return the user as it came, because there he doesn''t exist in the DB yet return user; } else { existingUser = existingGitHubUser || existingGoogleUser || existingTwitterUser || existingFacebookUser; if (existingUser) { if (user.emails) { // user is signing in by email, we need to set it to the existing user existingUser.emails = user.emails; } } } } // precaution, these will exist from accounts-password if used if (!existingUser.services) { existingUser.services = { resume: { loginTokens: [] }}; } // copy accross new service info existingUser.services[service] = user.services[service]; existingUser.services.resume.loginTokens.push( user.services.resume.loginTokens[0] ); // even worse hackery Meteor.users.remove({_id: existingUser._id}); // remove existing record return existingUser; // record is re-inserted } });