Создание системы создания/авторизации пользователя для Интернета и мобильных устройств, которая использует как электронную почту, так и facebook_id

Я пишу систему создания пользователя для приложения iOS и веб-приложения (т.е. пользователь может быть создан из мобильного приложения или веб-интерфейса) с помощью Ruby on Rails. Я не заинтересован в использовании такой системы, как Devise.

Я не делал этого через пару лет, поэтому просто хочу убедиться, что мои идеи актуальны и имеют смысл.

Шаги/предположения

  • Мы будем управлять состоянием между нашим сервером и клиентами через настраиваемое поле HTTP, такое как "X-auth_token".
  • Их можно создать либо с помощью учетных данных электронной почты или паролей, либо через facebook.

В случае входа в систему по электронной почте пользователь просто разместит следующий json:

{
  user:{
    email:'[email protected]',
    password:'testpassword',
  }
}

Я буду использовать Rails has_secure_password для хэш-значений.

и вернет

{
  user:{
    id:23,
    auth_token:'md5value',
  }
}

Для Интернета мы передадим auth_token как значение cookie. Для приложения iOS auth_token будет передаваться как пользовательское поле заголовка HTTP, такое как "X-auth_token"

  1. В случае входа в facebook они будут использовать FacebookSDK, получить разрешенные разрешения от FB и отправить

{ user: { is_facebook_login: true, fb_email: '[email protected]', fb_auth_token: 'abigvaluefromFB' } }

На сервере мы гарантируем, что они передадут действительные учетные данные fb_auth_token вызов facebook с помощью

def self.verify_facebook fb_auth_token
  result = Net::HTTP.get(URI.parse("https://graph.facebook.com/me?access_token=#{fb_auth_token}"))
  obj=JSON.parse(result)
  obj["email"]
end 

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

Здесь шаги с соответствующей диаграммой:

ШАГОВ

  • oauth запрос в facebook, запрос электронной почты ТОЛЬКО
  • пользователь одобряет, токен электронной почты и токен аутентификации возвращаются
  • отправить auth_token на наш сервер; если клиент facebook auth'd, установите флаг, чтобы только войти в систему через facebook
  • проверить с помощью facebook точный токен.

Не волнуйтесь прямо сейчас, если они меняют электронную почту в facebook, тяжелая удача. Если они заходят через Facebook, а затем хотят войти в систему по электронной почте /pwd, вам не повезло.

на нашем конце мы создадим auth_token (строку MD5) и отправим его обратно клиенту, который теперь управляет аутентификацией. С этого момента мы отправим пользовательский HTTP-заголовок X-auth_token

введите описание изображения здесь

Мы ответим на

{
  user:{
    id:23,
    auth_token:'md5value',
  }
}

и приложение iOS будет записывать auth_token в цепочку ключей через https://github.com/kishikawakatsumi/KeychainAccess

Является ли приведенный выше сценарий разумным для создания пользователя?

Ответы

Ответ 1

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

Отсутствующие части:

  • Как вы храните и идентифицируете пользователей?
  • Как вы храните auth tokens?
  • Может ли один пользователь иметь несколько токенов?
  • Вы хотите просрочить старые токены?

У вас уже есть описание двух процессов: регистрация новых пользователей по электронной почте и регистрация новых пользователей через facebook.

На сервере я бы сохранил их вот так, users table:

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

И я бы также объединил пользователей электронной почты /facebook в таких сценариях, как это:

  • Пользователь регистрируется с помощью электронной почты, у нас есть идентификатор и адрес электронной почты.
  • Пользователь регистрирует/регистрируется с помощью facebook и предоставляет электронную почту
  • Мы проверяем, что пользователь с такой электронной почтой уже существует и устанавливает для него facebook_id.
  • Теперь пользователь может войти в систему как с facebook, так и по электронной почте

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

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

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

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

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

Это похоже на facebook, но вместо электронной почты/пароля мы проверяем facebook_id и проверяем с запросом в facebook.

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

Я предполагаю, что полезно разрешить одному пользователю иметь несколько токенов auth для входа из разных мест, поэтому вот таблица tokens:

  • ID - целое число, уникальный идентификатор, первичный ключ
  • токен - строка, уникальный токен доступа (вы можете считать его основным ключом)
  • user_id - целое число, ссылка на пользователя, которому принадлежит токен
  • created_at - дата, дата создания
  • expired - boolean, может использоваться для истечения срока годности токенов.

Обычный запрос выглядит следующим образом:

  • Есть запрос с X-auth_token
  • Найти маркер в базе данных
  • Найти подходящего пользователя
  • Разрешить пользователю доступ к своим ресурсам.

Выдача токена может быть выполнена следующим образом:

  • Есть запрос с X-auth_token
  • Найти маркер в базе данных
  • Проверьте, если now() - token.created_at > EXPIRATION_PERIOD
    • отметьте токен как истек (token.expired= True + save)
    • вернуть ошибку "Истек срок действия"
    • в следующих запросах - вернуть ту же ошибку, приложение должно попросить пользователя снова войти в систему

Ответ 2

Некоторые советы:

1) Помните, что электронная почта facebook - это не адрес электронной почты для входа в facebook, ее адрес электронной почты профиля. Если пользователь оставляет его пустым, по умолчанию используется имя пользователя@facebook.com. Это важно, потому что вы можете захотеть, чтобы пользователи проверяли регистрацию по электронной почте, это сценарий, я предлагаю вам использовать модальный, чтобы попросить пользователя ввести свой адрес электронной почты после регистрации fb.

2) Пользователи Facebook не будут иметь пароли, но они могут изменить его, используя "забыть мой пароль", и этот сценарий зависит от usecase выше (им нужен реальный адрес электронной почты).

3) Я не знаю ваш сценарий безопасности и вид приложения, которое вы создаете. Но вы всегда можете просто использовать fb api для извлечения пользовательских данных и сохранения его как пользователя по умолчанию. Пример: получить данные из fb api и сохранить пользователя как пароль [email protected]: tokenWithMd5OrSomethingLikeThat userType: "facebook". Это полезно, если вы разрабатываете небольшое приложение, которое вы не будете обновлять слишком быстро, быстрее.