Архитектура объединения нескольких учетных записей пользователей

ладно, у меня есть сайт, где вы можете зарегистрироваться и войти. Вы также можете войти в свою учетную запись facebook, twitter или linkedin.

важно, чтобы у пользователей была зарегистрирована только одна учетная запись. Так или иначе, я хочу объединить учетные записи пользователей, если они используют разные способы для входа. Как лучше всего решить эту проблему?

например, пользователь входит в систему со своей учетной записи Facebook. Я использую эти данные, чтобы автоматически зарегистрировать для него аккаунт. Я Должен отправили электронное письмо с именем пользователя и паролем нашего сайта? (Если это нормально с политикой Facebook). Я должен дать им второй экран, где они могут заполнить имя пользователя и пароль? Но это не идея входа в систему с помощью вашей учетной записи Facebook. Это должно упростить процедуру участия.

также возможно, что пользователь зарегистрировался на нашем сайте и в следующий раз он войдет в свою учетную запись twitter. Как объединить эти 2 счета в один? Что лучший способ?

поэтому в основном мой вопрос: у меня есть 4 разных способа пользователь становится членом нашего сайта. Как я могу убедиться, что все эти 4 способа создать только одну учетную запись, если пользователь решает использовать несколькими способами? Какой лучший поток, чтобы убедиться, что он не станет хлопот для самого пользователя?


Edit:

через 3 года после того, как я задал этот вопрос, я даю ответ сам в серии статей: http://www.sitepoint.com/series/using-social-networks-as-a-login-system/

7 ответов


Я столкнулся с точно такой же задачей на данный момент. Дизайн, который я разработал, довольно прост, но он работает хорошо.

основная идея заключается в том, что модели для идентификации локального сайта и идентификаторов сторонних сайтов хранятся изолированно, но позже связаны. Таким образом, каждый пользователь, который входит на сайт, имеет локальное удостоверение, которое сопоставляется с любым количеством удостоверений сторонних сайтов.

локальная идентификационная запись содержит минимум информации - это может быть даже одно поле - только первичный ключ. (Для моего приложения меня не волнует электронная почта, имя или дата рождения пользователя - я просто хочу знать, что это человек, который все время входил в эту учетную запись.)

идентификаторы третьих лиц содержат информацию, относящуюся только к аутентификации с третьей стороной. Для OAuth это обычно означает идентификатор пользователя (например, идентификатор, адрес электронной почты или имя пользователя) и идентификатор службы (указывающий, какой сайт или служба прошли проверку подлинности). В других частях приложение вне базы данных этот идентификатор службы сопряжен с методом извлечения соответствующего идентификатора пользователя из этой службы, и именно так выполняется проверка подлинности. Для OpenID мы используем тот же подход, за исключением того, что метод аутентификации более обобщен (потому что мы почти всегда можем выполнять один и тот же протокол - за исключением того, что мы используем другой URL-адрес идентификатора, и это наш идентификатор службы).

наконец, я храню записи сторонних идентичности сопряжены с какой локальной идентичностью. Чтобы создать эти записи, поток выглядит следующим образом:

  • пользователь входит в систему впервые, используя удостоверение третьей стороны. Записи личных данных, то сторонняя запись личности, затем они в паре.
  • на панели управления пользователю предоставляется возможность связать учетную запись путем входа в сторонние службы. (Довольно просто, как это работает.)
  • в сценарии где пользователь невольно делает несколько учетных записей, решение довольно простое. Пока пользователь входит в одну из учетных записей, он входит в другую, которую он ранее использовал для входа на сайт (через функцию панели управления выше). Веб-служба обнаруживает это столкновение (локальное удостоверение пользователя, вошедшего в систему, отличается от локального удостоверения, связанного со сторонним удостоверением, которое только что вошло в систему), и пользователю предлагается ввести учетную запись объединить.

слияние учетных записей - это вопрос слияния каждого отдельного поля локального идентификатора (который будет варьироваться от приложения к приложению и должен быть легким, если у вас есть только несколько полей в ваших локальных записях идентификаторов), а затем обеспечение связанных сторонних идентификаторов связаны с результирующим локальным идентификатором.


Я, как правило, найти много сайтов слияния на основе почта как перекрывая соединяя фактор.

Я вижу, что это жизнеспособный вариант, но опять же это зависит от ваших предпочтений о том, как объединить. Адрес электронной почты является основным способом люди используют, чтобы проверить некоторые важные изменения информации на вашем сайте, как, изменяя свой пароль, прекращение обслуживания, баланс счета является низким и т. д... Это почти как система социального страхования в интернете, но с возможностью связь. Культурно: я думаю, разумно предположить, что электронная почта является довольно уникальной идентичностью в службах аутентификации OAuth. Конечно, это то, что просят формы входа для Facebook и Google.

мой мыслительный процесс.

страница входа в систему имеет 3 варианта

  • членство вашего собственного сайта
  • войти с facebook
  • войти с google

1) пользователь входит в первый раз: запуск потока регистрации, в котором учетная запись создается и заполняется впервые.

 if the user logins using Facebook (or whatever 3rd party login)
      1) call the Facebook api asking for their information (email, name, etc...) 
      2) create an account membership entry in your database somewhat like this 

         Table = Users
         [ UserId   |       Email             | Password ]
         [    23     | "newuser@coolmail.com" |  *null*  ]

      3) create an external auths entry like so
         *ProviderUserId is the unique id of that user on the provider's site

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]

 if the user wants to create an account with your own registration it would just be this           

         Table = Users
         [ UserId   |       Email           |   Password  ]
         [    23     | newuser@coolmail.com |  myCoolPwd  ]

2) в другое время пользователь возвращается, но решает нажать на Google Login

      1) call the Google api asking for their information (email, name, etc...) 

      2) once you get the email, match it up to the userId entry with the existing email 

      3) create an additional External auth entry as such

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]
         [    57           |      23        |    Google    |  "1234854368"     ]

3) Теперь вы объединились в учетной записи, которой Вы доверяете, что электронная почта в ваших записях базы данных такая же, как и те, которым Вы доверяете из внешних Логинов.

Так для последующих регистрациях

Итак, что делать, если у вас есть внешние логины, а затем вы хотите пользователь, чтобы иметь возможность войти с паролем позже?

Я вижу два простых способа сделать это

  • при любом первом входе в систему, когда учетная запись создается из внешней аутентификации, попросите их ввести пароль для завершения их первой записи в приложение

  • если они уже зарегистрировались с помощью facebook или google сначала, то как-то хотели зарегистрироваться, используя регистрационную форму вашего собственного сайта. Определить, если адрес электронной почты, который они ввели уже существует, попросите у них пароль, и отправить им подтверждение по электронной почте после регистрации.


Я прошел через это с sled.com - ... Существует несколько проблем в отношении создания учетных записей и поддержки нескольких сторонних учетных записей для входа в систему. Некоторые из них:

  • вам нужно поддерживать как локальный пароль, так и сторонние логины?

для sled.com, я решил удалить локальный пароль из-за небольшого значения, которое он добавляет, и дополнительных затрат на защиту формы ввода пароля. Есть много известных атак для взлома паролей и если вы собираетесь ввести пароли, вы должны убедиться, что они не легко сломать. Вам также нужно хранить их в одностороннем хэше или чем-то подобном, чтобы предотвратить их утечку.

  • сколько гибкости вы хотите разрешить в поддержке нескольких сторонних учетных записей?

похоже, вы уже выбрали трех поставщиков входа: Facebook, Twitter и LinkedIn. Это здорово, потому что это означает, что вы используете OAuth и работаете с четко определенный набор доверенных поставщиков. Я не поклонник OpenID. Остается вопрос, нужно ли поддерживать несколько сторонних учетных записей от одного и того же поставщика (например, один локальный аккаунт с двумя связанными учетными записями Twitter). Я предполагаю, что нет, но если вы это сделаете, вам нужно будет разместить это в своей модели данных.

для Саней мы поддерживаем вход в систему с Facebook, Twitter и Yahoo! и внутри каждой учетной записи пользователя храните ключ для каждого: {"_id": "djdjd99dj", "yahoo":"dj39djdj", twitter:"3723828732","facebook": "12837287"}. Мы устанавливаем кучу ограничений, чтобы гарантировать, что каждая сторонняя учетная запись может быть связана только с одной локальной учетной записью.

Если вы собираетесь разрешить несколько учетных записей от одного и того же стороннего поставщика, вам нужно будет использовать списки или другие структуры для поддержки этого и с этим все другие ограничения для обеспечения уникальности.

  • как связать несколько аккаунтов?

первый когда пользователь подписывается на вашу услугу, он сначала идет к стороннему провайдеру и возвращается с проверенным сторонним идентификатором. Затем вы создаете для них локальную учетную запись и собираете любую другую информацию. Мы собираем их адрес электронной почты, а также просим их выбрать локальное имя пользователя (мы стараемся предварительно заполнить форму с их существующим именем пользователя от другого поставщика). Наличие некоторого локального идентификатора (email, username) очень важно для восстановления учетной записи позже.

сервер знает, что это первый вход в систему, если браузер не имеет cookie сеанса (действительный или истекший) для существующей учетной записи, и что используемая учетная запись третьей стороны не найдена. Мы пытаемся сообщить пользователю, что они не просто входят в систему, но создают новую учетную запись, чтобы, если у них уже есть учетная запись, они, надеюсь, приостановят и войдут в существующую учетную запись.

мы используем точно такой же поток для связывания дополнительных учетных записей, но когда пользователь возвращается от третьей стороны, наличие действительного сеанса cookie используется для различения между попыткой связать новую учетную запись с действием входа в систему. Мы разрешаем только одну стороннюю учетную запись каждого типа, и если она уже связана, заблокируйте действие. Это не должно быть проблемой, потому что интерфейс для связывания новой учетной записи отключен, если у вас уже есть (на поставщика), но на всякий случай.

  • как объединить учетные записи?

Если пользователь попытался связать новую стороннюю учетную запись, которая уже связана с локальной учетной записью, вы просто попросите их подтвердить, что они хотят объединить две учетные записи (предполагая, что вы можете обрабатывать такое слияние с вашим набором данных - часто проще сказать, чем сделать). Вы также можете предоставить им специальную кнопку для запроса слияния, но на практике все, что они делают, это связывание другой учетной записи.

Это довольно простая государственная машина. Пользователь возвращается из стороннего стороннего аккаунта идентификатор. Ваша база данных может находиться в одном из трех состояний:

  1. учетная запись связана с локальной учетной записью, и cookie сеанса не присутствует --> Login
  2. учетная запись связана с локальной учетной записью и файл cookie сеанса присутствует --> Merge
  3. учетная запись не связана с локальная учетная запись и нет сеанса cookie присутствует --> Регистрация
  4. в счета не привязаны к локальной учетной записи и куки present --> Linking дополнительно счет

    • Как выполнить восстановление учетной записи со сторонними поставщиками?

Это все еще экспериментальная территория. Я не видел идеального UX для этого, поскольку большинство сервисов предоставляют как локальный пароль рядом со сторонними учетными записями, так и сосредоточиться на случае использования "забыл пароль", а не все остальное, что может пойти не так.

с санями мы решили использовать "нужна помощь при входе в систему?"и когда вы нажимаете, спросите пользователя их адрес электронной почты или имя пользователя. Мы ищем его, и если мы найдем подходящую учетную запись, напишите этому пользователю ссылку, которая может автоматически войти в Службу (хорошо для одного раза). После того, как в, мы берем их непосредственно на страницу привязки счета, сказать им, что они должны взглянуть и потенциально связать дополнительные счета, и показать им счета третьих лиц, которые они уже связаны.


оба подхода для автоматического слияния учетных записей оставляет довольно большую уязвимость, которая позволит кому-то взять на себя учетную запись. Они оба, похоже, предполагают, что пользователь-это тот, за кого они себя выдают, когда предлагают регистрирующемуся пользователю возможность слияния.

моя рекомендация по уменьшению уязвимости заключается в том, чтобы запросить аутентификацию пользователя у одного из известных поставщиков удостоверений перед выполнением слияния для проверки идентичности пользователь.

пример: пользователь A регистрируется с идентификатором Facebook. Через некоторое время они возвращаются на ваш сайт и пытаются получить доступ с помощью Windows Live ID и начать процесс регистрации. Ваш сайт предложит пользователю A with... Похоже, вы зарегистрировались в Facebook ранее. Пожалуйста, войдите в Facebook (предоставьте ссылку), и мы можем объединить ваш Windows Live ID с вашим существующим профилем.

Другой альтернативой является сохранение общего секрета (пароль/личный вопрос) на первоначальная регистрация, которую пользователь должен предоставить при слиянии удостоверений, однако это возвращает вас в бизнес хранения общих секретов. Это также означает, что вы должны обрабатывать ситуацию, когда пользователь не помнит общий секрет и процесс, который идет вместе с ней.


большинство сообщений довольно старые, и я думаю, Google бесплатно Проверка Подлинности Firebase службы еще не было. После проверки с помощью OAuth вы передаете ему маркер OAuth и получаете уникальный идентификатор пользователя, который можно сохранить для справки. Поддерживаемые поставщики Google, Facebook, Twitter, GitHub и есть возможность зарегистрировать пользовательские и анонимные поставщики.


отличные ответы и ресурсы выше. Мой вклад, представлены здесь... https://github.com/JavascriptMick/learntree.org/blob/master/design/Schema.md

TLDR: отдельные схемы учетной записи и лица. 2 варианта учетной записи, электронной почты и OAuth.

учетная запись-аутентифицирует - > человек


вы должны разрешить вход из один учетная запись, затем при входе в систему дайте возможность добавить другую учетную запись для слияния с ней.