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

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

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

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

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

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


Изменить:

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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

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

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

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

  • Как объединить аккаунты?

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

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

  • Учетная запись связана с локальной учетной записью, а cookie сеанса не является настоящее → Вход
  • Учетная запись связана с локальной учетной записью и session cookie присутствует → Объединить
  • Учетная запись не связана с локальная учетная запись и нет cookie сеанса → Регистрация
  • учетная запись не связана с локальной учетной записью, а файл cookie сеанса настоящее → Ссылка на дополнительную учетную запись

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

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

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

Ответ 3

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

Я вижу, что это жизнеспособный вариант, но опять же это зависит от вашего предпочтения о том, как слить. Адрес электронной почты является основным способом, который люди используют для проверки некоторых важных изменений информации на вашем сайте, например, смены пароля, прекращения обслуживания, останова на балансе аккаунта и т.д. Это почти похоже на систему номеров социального страхования в Интернете, но с возможностью связи, В культурном плане: я считаю разумным предположить, что электронное письмо является довольно уникальной идентификацией через службы аутентификации 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     | "[email protected]" |  *null*  ]

      3) create an external auths entry like so
         *ProviderUserId is the unique id of that user on the provider 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     | [email protected] |  myCoolPwd  ]

2) В какой-то другой момент пользователь возвращается, но решает щелкнуть по Google Войти

      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) Теперь вы слились с учетной записью, которой доверяете электронное письмо в своих записях базы данных, такие же, как те, которым вы доверяете внешним входам.

Итак, для последующих логинов

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

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

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

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

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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