Pull to refresh

Comments 218

Была очень похожая проблема совсем недавно, и решили ее похожим образом, еще правда нигде не зарелизили, но алгоритм рабочий, я даже сначала когда увидел статью думал кто-то из наших написал. Спасибо. Очень здорово видеть что мысли с кем то сходятся.
О, и правда здорово! Когда зарелизите, я бы с радость поглядел, если это будет возможно!)
И у нас такая штука была :) почти самая распространенная разработка «за линией фронта», как видно.
Ну… Видимо, часто встречающаяся проблема, после которой либо решают не использоваться авторизацию через внешние ресурсы, либо используют, но уже извращая по своему)
Вам не кажется, что ID связи — избыточно? В статье написано, что идентификатор в соцсети — он сам по себе уникален. А в совокупности с типом сети, так совсем уникален.
Увы, я человек, выросший на CMS и фреймворках, где всё имено свой идентификатор) На самом деле, особой избыточности он не создает, зато однозначно идетнифицирует запись в БД, например, для логирования
Каждую запись можно однозначно идентифицировать по ID пользователя + ID ресурса. По этим полям также стоит создать составной первичный ключ.

ID самой связи не нужно даже для логирования: вы никогда не захотите сохранять в логах ID связи; намного больший смысл имеет логировать информацию о пользователе и связанном ресурсе.
Просто ID, в частности, использует ORM для связи между собой моделей, потому и такой выбор) Так что я не спорю с вашим утверждением, оно очень даже логично)
Ну, во всякого рода ORM, на любой платформе и с любым паттерном DataAccess (ActiveRecord, Reposotory), ID связи все же очень удобно, ибо позволяет работать со связью как с сущностью. Это было бы ни к чему, будь свять чистой связью. Но нет — тут связь хранит данные — «ID пользователя на внешнем ресурсе» и уже может считаться отдельным объектом ORM и для простоты имеет свой суррогатный ключ (Id).
Более, того, я бы назвал это не просто «связью», а, если хотите, сущностью «Пользователь ресурса» (т.е., параллельно с «Пользователем» и «Ресурсом»).
Да, вы правы, в этом случае это действительно ближе к сущности, чем к связи.
Как мы ниже разобрались, таблица связи так же ненормализована) Вот если ее нормализовать, выделится две отдельных таблицы, одна из которых будет действительно связной парой «ID пользователя — ID элемента связи», и в таком случае ей не нужен будет ID)
Верно, но это сложнее и не нужно. Предложенной вами схемы вполне достаточно и работать с ней просто.
Суррогатный ключ полезен по многим причинам, потому имеет множество сторонников.
Ой, как же я раньше не заметил этот комментарий!

Я вот — человек, выросший на COBOLе. И ничего, живу. В том смысле, что аргументом — тезис «я вырос на…» являться не хочет.
Не, ну как бы… Кому что по духу) Я, может, и си знаю, и жаву, и делфи, но люблю только делфи, не смотря на его быдлокод. Хотя не, вру, уже не люблю. Я бы даже сказал, лютобешенно ненавижу) Потому и перешел на веб)
Ежики плакали и кололись, но продолжали писать скрипт для слияния аккаунтов.
Всмысле скрипт, запускающий слияние клонов по запросу от пользователя. Этакая самоирония была.
Кстати, неплохая идея. Но не исключены эксцессы, плюс, опять же, пользователю желательно не давать в руки управляющие структуры)
Лучше дать возможность сказать «это — тоже я!», а не требовать какого-то ещё выбора какой-то учётки после логина по OpenID. Этот OpenID для того и делался, чтоб залогинившись им больше не нарываться на лишние вопросы по самоидентификации.

Кстати, связать два своих аккаунта вполне можно тем же самым механизмом, каким Вы связываете свой аккаунт с внешними OpenID-учётками.
Вот как раз адекватных алгоритмов по связыванию своего аккаунта с внешними я нашел не так много) Потому и создал эту концепцию) Привязывая себя, человек так и так говорит «Это я», и всего один раз. Это (в случае, если он вошел через внешний ресурс) или регистрация, или просто один вход в систему) После чего используй свой опен-айди сколько угодно)
Но для такого связывания было бы удобно, если б увидев из-под новой учётки на сайте свои следы (комменты и т.п.), сделанные из-под старой учётки, я мог зайти в профиль старой и нажать там кнопку «это тоже был я», которая бы попросила меня авторизоваться каким-либо из способов от той старой.
Какая-то уже страсть получается) Это я, это тоже я, а вон то не я, и вообще, меня тут не было) Путаница будет) плюс, опять же, если физическая учётка обладает набором каких-то свойств и данных, вроде той же кармы, как здесь, элементарно, не будет смысла сидеть под разными аккаунтами и будет интерес связать их вместе сразу, чтобы всё «капало» на него
Дык речь о том и идёт — указал, что то тоже ты — учётки объединил.
Дык, всё равно получается, заставлять пользователя ручками указывать, что вон тот человек — тоже ты. Ибо кликать на него, нажимать «Это я», переходить к форме валидации, и так далее. Одни и те же действия, только в другой последовательности, только в БД еще и плодятся сущности пользователей)
Скажите, а зачем пользователю может понадобиться авторизовываться на сайте то через один сторонний сервис, то через другой?
А если он по какой-то причине хочет авторизовываться то так, то эдак, не значит ли это, что ему действительно нужны несколько несвязанных между собой аккаунтов?
Ну в первую очередь такая система нужна даже не столько пользователю, сколько создателям сайта, ибо им важен контроль за учётными записями. Если бы тот же контакт не следит за количеством клонов каких-нибудь Жириновских или Медведевых, представляете, сколько бы их было у вас в друзьях?)

А для пользователя эта ведь может быть полезна, в частности, в двух ситуациях:
1) По какой-то причине он удалился из какой-либо социальной сети. В таком случае, войти через нее он уже не сможет, и его аккаунт останется мертвым грузом.
2) Какой-то из сервисов отпадет, по причине ли самого сервиса или нашего сайта, но отпадет. Тогда будут другие варианты
В обоих ситуациях пользователь уже не сможет авторизоваться при помощи этого стороннего сервиса. А значит, не сможет связать этот аккаунт с другими, если не сделал этого предварительно. Или вы думаете, что пользователи будут думать о таких ситуациях наперед? :)
За них будем думать мы) Эти случаи работают в том случае, если пользователь их уже привязал) Если он их не привязал, значит, у него до сих пор нет для них учётной записи, и если сервисы отключены, он их и в самом деле не сможет привязать, а значит, ему надо будет авторизоваться либо через сам сайт, либо через другие ресурсы) Потому я и написал, что в случае входа через внешний ресурс пользователю будут выдаваться ограниченные права до тех пор, пока он не привяжется. Такова реализация)
В таком случае, авторизация через сторонние сервисы имеет сомнительную ценность. Пользователю предлагают авторизоваться, совершив какие-то действия, и после этого оказывается, что у него неполноценный аккаунт. Не проще ли было изначально регистрироваться напрямую?
Впрочем, я не уверен, возможно, для каких-то проектов это и имеет смысл. Буду рад увидеть примеры таких проектов.
Про изначальную регистрацию, такая мысль была, правда, для другого проекта. Может быть, в будущем, напишу про нее, или дополню эту статью, там как раз всё сводилось к созданию таких «спящих» учёток при «Создании материала без регистрации», и предусматривалась дальнейшая возможность вывода их из комы и оживления)
Лично я пару раз пользовался тем, что я из Facebook != я из Twitter, получал разные аккаунты и было мне счастье.
Ну, как я уже писал чуть ниже, от регистрации многих физических аккаунтов никто не застрахован) Если так кому-то надо, он может зарегистрировать одного себя и привязать к твиттеру, и второго себя, и привязать к фейсбуку) Реализация, в основном, поможет тем, кто не создает мультов, а всё на одном делает)
Есть другой случай. К примеру, на сайте 3DNews.ru чтобы отправить отзыв на ту или иную статью, нужно быть зарегистрированным либо в Facebook, либо в ВКонтакте, либо в Twitter, четвёртого, что называется, «не дано».

Как быть тем умным пользователям, мнение которое не самое бессмысленное, но они не зарегистрированы в этих социальных сетях? Как им пройти авторизацию на 3DNews.ru и написать свой отзыв на статью?
Это надо спрашивать уже у 3DNews.ru)
Я потому и оставил штатную регистрацию)
по-быстрому зарегистрироваться в одной из этих соцсетей, и потом залогиниться этим логином на 3dньюз.
Автор комментом выше предлагал оставить штатную регистрацию, но по мне так это не особо отличается от быстрой регистрации в соцсети.
Другой вопрос в том, что, быть может, вам соцсеть вообще не нужна, и вам не было смысла туда регистрироваться, а вас принуждают. Не есть хорошо. У меня у самого есть несколько знакомых, которых принципиально нет ни в одной сети, даже в твиттере)
Зато без учетной записи на вашем сервисе — они просто спать не могут.

Fake-accounts никто пока не отменял, и я согласен с olegchir: мало того, что процедура регистрации у вас и «у них» мало отличается, так twitter-account еще и пригодится в дальнейшем, а ваш — эммм… при всем уважении…

;-)

Нет, ну тут всё зависит от проекта) Эта система планировалась для большого проекта с высокой посещаемостью и вообще нагруженностью контентом) Так что...)

Я ж не претендую) Просто высказал идею «плюшки»)
Большие проекты, насколько могу судить, вырастают из маленьких, а не вылупляются с готовыми миллиардами активных аккаунтов.
Посему данная вещь будет выступать в качестве плюшки, возможно, включаемой потом) Для начала, как вы и сказали, надо набрать контенгент, а потом выкатить им) Пользователи, они, как дети, радуются новым игрушкам, даже если они не понятны!

Это как в футураме, «Сначала мы создадим новый Слёрм, который будет хуже предыдущего, а когда через некоторое время люди начнут говорить, что старый был лучше, мы вернем классический Слёрм»)
У нас например такая задача, мы показываем в лидерборде игры его друзей в зависимости от того под каким аккаунтом он зашел, если с фейсбука, то друзей с фейсбука которые играли в эту игру, если с вконтакта соответственно ну и так далее…
Тоже хорошее решение, кстати. И статистику вести можно!)
Так у вас есть возможность связать два аккаунта, с которых уже велись игры? Игры тогда тоже объединяются в один список?
Мне просто интересно, насколько далеко вы решили зайти с этой идеей.
Например, когда не помнишь под каким аккаунтом входил. Я вот на кинобазе той же был зарегистрирован, составил себе списки и забыл под чем заходил. Пока подбирал насоздавал еще кучу аккаунтов. Так и не нашел, хотя думаю, что это может быть один из аккаунтов Google. В итоге сижу под другим.
Хороший пример, кстати) Спасибо)
Проблему из этого примера ваше решение, насколько могу судить, не только не решит, а даже усугубит. blare использует разные аккаунты с одного сервиса, поэтому когда он начнет вспоминать, какой именно — ваш алгоритм пойдет по ветке:
В случае же, когда ключи не совпали, стоит поругать человека за попытку похитить чей-то идентификатор, или вежливо переспросить, вошел ли он под своей учёткой, или по привычке залез на страницу своей девушки/парня.
А мне показалось, что всё же имелся в виду мой вариант… Ну, думаю, человек нам разъяснит, если решит ответить)
Так и не нашел, хотя думаю, что это может быть один из аккаунтов Google.
Ну, у человека могло быть несколько логинов на гугле, через которые он пытался приноннектиться. Так же, как могло быть несколько на контакте, фейсбуке и иже с ними
например, пофиксать так:

1. успешный набор операций для работы в гетерогенной среде (внутренние пользователи, внешние пользователи, еще какие-нибудь пользователи — неважно)

2. возможность любой набор элементов этой среды обозвать «аккаунтом»

3. если сессия имеет доступ к одному аккаунту, то она имеет доступ и ко всем пересекающим его аккаунтам
Разумеется.

Я про описанную схему БД.
Ну, если я вас правильно понял по пункту 2, вы предлагаете, при входе через какой-нибудь твиттер или еще что считать эту учётную запись «физической», и уже от нее отталкиваться, привязывая к ней, скажем, логин и пароль на сайте, и другие внешние логины?

Звучит интересно…
Звучит интересно, но оратор, кажется, имел в виду не это. Если сравнивать провайдеров OpenID/OAuth с фруктами: два яблока, три апельсина и восемь вишенок — это «аккаунт».
Ну, вполне возможно, но в любом случае, его коммент натолкнул меня на мысли) *прикинулся Хаузом*
у нас есть 3 типа объектов:
* сессии пользователей,
* аккаунты сервисе,
* аккаунты на внешних провайдерах аутентификации.

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

например, такая ситуация:

аккаунт_1: твиттер_А, фэйсбук_Б
аккаунт_2: твиттер_А, фэйсбук_В
аккаунт_3: вконтакте_Ц, фэйсбук_В

множества аккаунт_1 и аккаунт_2 пересекаются — у них есть общий твиттер. Значит им пользуется один человек.

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

в нашем случае ситуация с аккаунтами противоположная: зайдя на сайт (получив сессию) пользователю хорошо бы иметь возможности всех своих аккаунтов одновременно. В примере который был выше, если человек зашел с аккаунтом аккаунт_1, то реально он получает возможности сразу трех аккаунтов: твиттер_А, фэйсбук_Б, фэйсбук_В, вконтакте_Ц (потому что множества их привилегий пересекаются).

То же самое происходит и при регистрации нового аккаунта. Если человек регает аккаунт с доступом до твиттер_А, то система воспринимает его как «своего человека». Ему можно даже предложить не регистрировать новый аккаунт )))

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

Привязывать к твиттеру физическую запись — частный случай этой системы. Более экономичный, более простой, но и более геморный для пользователя ;)

Пара очевидных проблем:

* Как и у всех супер-масштабируемых супер-функциональных монстров тут же вылазят проблемы производительности. Тут нужно писать умные алгоритмы, которые не убьют сервер на первой тысяче зашедших пользователей. Например, можно кэшировать данные об пересекающихся аккаунтах прямо в БД, в каких-нибудь «метааккаунтах», причем начинать кэширование еще на этапе регистрации.

Инфу про множества, модели, гомоморфизм, алгоритмы на графах можно выдернуть из запылившихся книжек по матлогу и дискретке. Например, Ершов-Палютин — праздник какой-то, но туда очень долго втыкать чтобы чото понять. Если понимаешь не с нуля, а просто вспоминаешь — гораздо приятней.

* Если злоумышленник похитит учетку на любом из внешних провайдеров авторизации (стибрит пароль на один из твиттеров), то он украдёт вообще все права, а не какую-то конкретную их часть. Собственно, в юниксах пользователи и группы на то и созданы, чтобы такого не происходило ;)
Ну, если вы не вспомните, под каким аккаунтом заходили, то и привязать его к другим аккаунтам не сможете ;)
А специально привязывать все свои аккаунты при регистрации, только чтобы потом можно было зайти под любым из них… ну, может быть кто-то так и будет делать, но, по-моему, тогда уж проще зарегистрироваться на сайте напрямую. Или же всегда использовать один и тот же аккаунт ФБ/Гугла для авторизации на всех сайтах.
Ну, никто не заставляешь привязывать все. Скажем, на сайте будет панель различных вариантов, хоть пять, хоть десять, а ты можешь привязать себе один удобный и входить через него)
Да-да, это понятно. И, возможно, действительно будет кому-то удобно.
Но я отвечал конкретно про случай, когда можно забыть, под каким аккаунтом заходил. Если его ни с каким другим аккаунтом не связывал, то тут уже ничего не поделаешь, остается только вспоминать.
А единственный способ такую ситуацию предотвратить в концепции связывания аккаунтов — сразу же, при регистрации, связать все аккаунты, под которыми, возможно, будешь заходить в будущем. Но мне такое поведение пользователей не представляется вероятным.
Вопрос с памятью решает ограничение прав. Человек, вошедший через сторонний сервис, в любом случае будет всегда видеть большое предупреждение об этом и просьбу привязаться/зарегистрироваться. Как только он это сделает, он получит полноправный аккаунт на сайте, а до этого физически он не будет создаваться на сервере) И даже если он потом забудет, можно будет, например, высылать ему на почту уведомления вида «Вы привязали аккаунт Вконтакте в вашей учётной записи %login%»)
В общем, я думаю, мы уже выяснили плюсы и минусы такого подхода. Читателю остается решить: применять связывание аккаунтов у себя на проекте или не применять.
Согласен. Хотя, сколько я здесь начитался комментариев, появилось много различных вариантов) Надо будет их в дальнейшем скомпилировать, сравнить)
Значит нужен поиск по таким аккаунтам.
Или, скажем, я ввожу свой ник в поиск, а там показан провайдер под каким зарегистрирован юзер, тогда, хотя бы, сузится круг поиска.
Вот тоже хороший вариант. Хотя, в принципе, в учётке каждого пользователя будет написан его идентификатор в той или иной службе, так что вопрос с поиском это само собой разумеющееся)
Хмм, а я бы не рассматривал это как данность. Идентификатор пользователя в сторонней службе — его личная информация. Обычно пользователю, который авторизуется через OpenID и т.п., предлагается ввести никнейм, который и будет отображаться в публичном профиле.
Кстати, так как идентификатор на стороннем сервисе — личная информация пользователей, то и поиск по этому параметру делать не стоит.
Ну на этот случай можно сделать приватность, типа, галочки «Показывать другим мои идентификаторы в социальных сетях» или «Выводить в поиске мои идентификаторы», что-то такое
кроме галочки, нужно таки поле для правки локального ник-нейма и аватарки

кстати, gravatar поддерживаете?
На счет таких вещей пока не задумывался, всё это чистая теория (ну, так, с небольшими набросками). Правка никнейма… Ну, возможна, никнейм будет отличаться от логина (хотя может и совпадать). Ну и аватар, вестимо)
пользователь не обязан помнить, чем он зарегистрировался вот на этом сайте, чем на вооон том, и чем на этаком третьем. Он заходит на сайт и видит: «о! я есть и вконтакте, и в твиттере, и в фейсбуке! а через что я тут регился? и регился ли вообще? а, попробую наудачу „
а, попробую наудачу

в этом вся русская душа! )
если на сайте есть возможность входа под «учетками» разных ресурсов, то он может банально забыть под какой он заходил на этот сайт до этого (ведь это модная тенденция сейчас — входить под «учетками» разных ресурсов), либо просто поменялись его предпочтения.
На этот случай у него будет одна общая для всех физическая учётка, имя и пароль от которой будут заботливо лежат на почте) Может, конечно, я и не в праве решать за всех пользователей, но мне так было бы удобно)
неа, я имел ввиду про учетки разных ресурсов(вчера заходил под гмэйл, сегодня под ФБ, но т.к. я связал все их между собой, то для системы пофиг под чем я зайду завтра). Я-то как раз вижу пользу в такой штуке :)
Ну, да) Главное, она будет знать, кто зашел)
и, кстати, чтобы предупредить вопрос в духе — как это поможет… в случае если пользователь зашел под не привязанной учеткой, то просить его ввести е-мэйл(или если ресурс не отдает почту), т.к. почта уникальна для ресурса и к тому же не все ресурсы отдают почту, насколько я помню. Соответственно привязка будет по почте. Понятно, что если задаться целью, то и в этом случае можно наплодить регистраций, но это позволит свести их к минимуму.

А удобство есть во всем этом есть, хотя возможно придется что-то сделать дополнительно для связи разных учеток (в духе «введите емэйл»).
Спасибо за поддержку) Мнения здесь разделились, от «Пользователю нужна легкость» до «Пользователю нужен контроль»)
очень многие для регистрации учёток используют одноразовые почтовые ящики
Да, сейчас, увы, пошла на них мода. Потому, логин-пароль, а там дальше человек может как угодно указывать себя к почтам, фейсбукам и т.д. Что для него удобнее. Представляете, если случайно забыть или потерять доступ к хабру, где кармы больше десяти, и рейтинга +100500?) Ахтунг!)
Я, как пользователь, могу тупо не помнить, кокй из соц. сетей я зашел на этот сайт — Твиттером, Фейсбуком или гуглоаккаунтом
Один сайт поддерживает ФБ, другой ВКонтакте, а третий оба. Запомнить какой и почему выбрал на третьем может быть не просто.
Суть данного решения, я так понимаю, сводится к тому, что пользователь сам выбирает, привязать ли новый логин к существующему аккаунту или создать новый. Т.е. никакой автоматической привязки нет. А значит любой человек может создавать себе несколько разных аккаунтов как ни крути.

Вопрос: а для чего кому-то логиниться через разные сервисы, когда проще зайти один раз и чтоб тебя запомнили? Это и проще и меньше информации о себе предоставляешь неизвестному ресурсу.
Ну такие случаи бывают, когда полезна регистрация с различных сервисов.
У меня, например, приложение в Контакте, которое сейчас переносится на отдельный домен и будет работать, как независимый сервис. Суть приложения — поиск фотографов, моделей и т.д. У каждого пользователя есть профайл с фотографиями, темами в обсуждениях, комментариями, личными сообщениями. Важно связать аккаунты так, чтобы можно было пользоваться сервисом и через приложение в Контакте, и через независимый сайт.

Как раз сейчас работаем над связкой аккаунтов. Тут ещё появляется и другая проблема, чтобы не просто связать 2 логина, а еще и синхронизировать контент внутри каждого логина и исключить противоречия, например, когда под одним аккаунтом пользователь написал, что живёт в Москве, а под другим, что в Питере.
Ну вот в вашем случае, могу предположить, что можно на вашем отдельном домене создать некий третий вариант учётной записи, в которую можно заходить или через контакт, или через независимый сайт, а там уже выбрать, откуда синхронизовать данные, из первого или из второго
Автоматической привязки да, нету, потому что при входе через внешний ресурс никакой физической учётной записи не создается. только временная сессия. И, конечно же, человек может создать сколько угодно разных физических учётных записей непосредственно на сайте, но от этого, увы, не застрахован никто. Эта реализация создана для того, чтобы предотвратить клоны полу-учёток одного пользователя)

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

А вот по поводу «меньше информации»… ну, тут мне тяжело что-то сказать. Это палка о двух концах) Например, тот же контакт никаких имен и паролей не передает, только ключ, все данные вводятся на стороне сервера контакта)
Это, видимо, на мой комментарий ответ (:

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

Я не знаю API контакта. Неужели там нет методов для запроса информации о пользователе после авторизации?
Ну, во-первых, возможен вариант, например, вы сидите в интернет-кафе, и тут бух — обрывается сессия — время кончилось) Хорошо, если все данные сессии удаляются, а если они хранятся? Получится, что вы оставили админам все ваши куки и тд) Ну или, элементарно, даже вариант с ревнивой подружкой подойдет)
А по поводу запросов информации, а это как предоставишь пользователю. Можно дать ему только одну функцию, по сути, получения того самого ключа, а можно полностью обменяться информацией. В данной реализации не планировать обмениваться никакой информацией с удаленными сервисами, только использовать их для идентификации)
Прочитал и придумал себе правило для будущих проектов: «Сто раз взвесь все за и против прежде чем решить использовать внешнюю авторизацию».
Вот мы пришли к тому же решению во время обсуждения, потому пока и нет реализации, только теория, как бы мы это сделали, если бы сделали)
Я начал реализовывать так: есть сущность пользователя и есть сущность провайдера авторизации. Кстати, туда же я отнёс и классический способ авторизации через емейл. И получается связь один ко многим. То есть на одну сущность пользователя может приходиться от 1 до N сущностей провайдеров.

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

А по поводу первой привязки… Вариантов всего два — или ты зашел под физической учёткой и привязал внешнюю, или вошел под внешней с ограниченными правами, и будешь обладать таковыми до тех пор, пока не создать или не войдешь в физическую учётку. В случае, если ты вошел под внешней, которая уже привязана, ты просто авторизуешься под своей физической учёткой)
И получается связь один ко многим. То есть на одну сущность пользователя может приходиться от 1 до N сущностей провайдеров.

На самом деле это связь многое к многому.
На одну сущность пользователя — N сущностей провайдеров, а на одну сущность провайдера — M сущностей пользователей. К примеру, вы можете искать всех пользователей, у которых есть провайдер Твиттер, или выбрать всех провайдеров пользователя Васи Пупкина. В общем, many-to-many, а не one-to-many
Если фактически, то один-ко-многим, т.к. тип провайдера у меня ENUM-поле, а не отдельная сущность. А гипотетически да.
Ну это уже вопрос реализации и нормализации БД) Так что может быть по всякому)
…а потом вспомни обо всех потерянных пользователях, которые выматерились, увидев требование локальной авторизации и ушли навсегда.

Мне кажется, собственную авторизацию могут позволить себе в наше время только гиганты.
Собственно, для такого проекта и было это обсуждение)
От слов «Возвращенный от ресурса ключ...» и до "… выводить ссылку на этого человека)." раз 5 прочитал но не понял что за пояски и зачем… Толи у вас там термины поперемешались, толи я в матчасти плохо разбираюсь, но… Зачем юзеру вводить в форму свой ID провайдера? Неужто для получения его ID недостаточно ему нажать на стандартный «авторизоваться через facebook»?

«мы сравниваем пришедший от ресурса ключ с нашим.» Чего? Кто такой наш ключ?

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

По поводу «мы сравниваем...», смысл в том, что во время авторизации сайт присылает нам некоторый хэш, сделанный из кучи параметров, в том числе, и ID пользователя.
Но при этом, пользователь, который хочет привязать сайт, вводить тот ID, который хочет привязать, в соответствующее поле для ввода. Вот уже из этого, введенного, ID, мы делаем хэш по тому же алгоритму, что и тот, который пришел к нам от сайта.

А по поводу «регистрации без авторизации», это в смысле, если у нас еще нет физической учётки на сайте, а мы нажали «Войти через...»
Пару раз перечитал ваше сообщение, но так и не понял смысла сего действия.
Возьмём конкретный пример — авторизацию через ВКонтакте.
Зачем заставлять пользователя вводить id и идентифицировать его по хэшу, если ВКонтакте предоставляет id пользователя? Хэш используется в целях безопасности, для проверки соответствия полученного вашим сайтом id посланному ВКонтакте.
Ну вот для безопасности это и делается. Да, чисто практически, можно оставить вместо поля для ввода одну кнопку — авторизоваться через контакт, и по умолчанию сразу привязывать полученный ID. С точки зрения легкости? Да. С точки зрения безопасности? Не знаю. Но в случае поля для ввода мы избегаем сначала запроса к контакту, а потом поиска по базе, мы сначала ищем по базе, а потом делаем запрос. Малая выгода, но в масштабах проекта, для которого это обсуждалось, в принципе, дало бы выигрыш.
С точки безопасности всё идентично, ВКонтакте помимо id отсылает и хэш — добавляем проверку хэша и всё.
Зачем искать id по своей базе? Он либо есть (а значит есть и привязанный к нему аккаунт — исходя из статьи), либо его нет.
И даже если бы этот поиск имел необходимость, запрос к ВКонтакте был бы необходим. Для того, чтобы подтвердить, что введённый id действительно принадлежит пользователю.
Как зачем искать? Чтобы увидеть, есть ли кто-то в нашей базе уже под этим идентификатором, или нет, я же писал в статье. Логично, что он либо есть, либо его нет)

Хотя, можете почитать комменты, мы тут много проблем из этих уже обсудили)
Хорошо, мы увидели, что в нашей базе есть пользователь с таким id — что дальше?
Чтобы выдать сообщение «Пользователь с таким id уже есть» не нужно заставлять пользователя писать свой id.
Исходя из статьи и ваших комментариев видится, что Вы ещё не до конца разобрались с принципами внешней авторизации. Было бы интересно прочитать продолжение статьи, о применении теории на практике.
Ну да, многие комментарии я писал, еще не обсуждая другие нововведения) В частности, вместо поля для ввода сразу делать кнопку «привязать», чтобы скрипт вернул от, например, контакта, который сразу проверить на существование и привязать, без различных генераций своих ключей)

А по поводу теории, буду разрабатывать) Надеюсь, будущая статья будет востребована (хотя писать буду, скорее всего, под кохану)
А что если не создавать на вашей аккаунт в чистом виде? Поясню.
Допустим есть какая-то общая информация, доступная при логине через сторонний сервис. Для каждого сервиса создаётся таблица с доступными через него полями и какими-то идентификаторами пользователей, которые через данный сервис у вас авторизовались. Собственно для базовой работы этого должно быть достаточно.
Если вам нужны какие-то дополнительные данные, вы можете или настоять на их принудительном вводе для получения доп. прав или, как делают авиакомпании, «накапливать» их — как, например, покупая билет я ввожу свои данные один раз, а в следующий мне их уже предлагают выбрать автоматически. Ну это как пример просто. Тогда эти данные сохраняются в ещё одной таблице метаданных и между ними и текущим аккаунтом (записью в таблице регистрации определённого провайдера авторизации) формируется связь. Достаточно иметь ID записи метаданных в таблице провайдера.
Теперь случай если юзеру надо привязать сюда же ещё одного провайдера — вы предлагаете где-то опцию «привязать другой аккаунт» — тогда юзер авторизуется ещё где-то и, если у него для одной из авторизаций уже есть метаданные, то другая линкуется к этой же метазаписи. Если вдруг есть для обоих, предлагается их смержить, выбирая значения конфликтующих полей.
Если рассматривается вариант когда юзер не хочет светить свои внешние аккаунты или их просто нет — ваша личная авторизационная система становится просто ещё одним провайдером и действуе точно так же как все остальные.
Ну это просто ночные мысли вслух, раз уж просили комментов =)
Суровый коммент, пришлось собрать мозги в кучку, чтобы вникнуть) в принципе, тоже адекватная реализация) Хотя, по сути, тоже присутствует определенное связывание)
после полуночи все комменты превращаются в тыквы становятся суровыми =)
связывание, похоже, избегаемо только если забить на привязку нескольких аккаунтов. А если нужны какие-то сторонние данные, то их всё равно привязывать. Ну или хранить в той же таблице где и id/тип логина.
Просто, как правило, сами виджеты авторизации получают только ID, и, иногда, Имя-Фамилия-Аватар) Всё остальное делается кучей других OpenApi запросов)
Тоже об этом подумал. Т.е. структура базы такая же, просто поля логин и пароль в таблице оказываются необязательными.

Только теперь нужно будет мотивировать пользователя не заводить логин-пароль, а заполнить список логинов на остальных сайтах и подтвердить их внешней авторизацией, при необходимости сливая уже существующие профили в один.
Ну, всё снова сводится к собиранию учёток) Так что пусть уж будет одна накопительная, физическая)
Так я и не предлагаю ее отменять, пусть будет. Но только на уровне внутренней логики. Не заставляйте пользователя помнить еще один логин и пароль, он не для этого к вам через другой сайт авторизовывался.
Ну, чисто теоретически, указанная реализация предполагает вход через сторонние сервисы как быструю кнопку «войти», так как, если человек сидит на сторонних сервисах, соответственно, куки у него обновляются регулярно, а значит, запросов логинов-паролей от самих этих сервисов быть не должно
Может быть, конечно. Но я, как пользователь, предпочел бы чтобы я мог вообще не задумываться о создании аккаунта. Надоело, честно говоря, за последнее время.
Ну вот это уже переход в своеобразный вебтриноль) Когда пользователь вообще не заморачивается ничем) С этим сложнее)
Все-таки, логин желательно заставлять вводить. По многим причинам. А вот пароль — да, делать обязательным только при прямой регистрации.
Ну, в качестве логина можно использовать любое поле) Главное, чтобы оно было уникальным)
Причины нужно рассмотреть и прикинуть, стоит ли того — пользователи не любят думать :)

Хотя я понимаю, что если, например, есть возможность оставлять комментарии, то хорошо бы чтобы пользователя можно было как-то обозначить, и пользователи не могли бы притворяться друг другом. Но и тут можно попытаться использовать логин внешнего сервиса + иконку этого сервиса. Получается уникально (кроме вконтактовских id12345, которые будут слабоотличимы)
Ну, в принципе, такие сервисы присылают минимум информации, которую можно использовать)
Негодование добропорядочного пользователя, у которого после авторизации через сторонний сервис просят создать аккаунт, мне кажется важнее борьбы с мультами. Я считаю, что после авторизации через сторонний сервис пользователя можно попросить только дополнительную необходимую информацию (которую сервис авторизации не предоставляет) и дать ему полноценно пользоваться ресурсом. Иначе вся красота такой авторизации (быстро дать пользователю доступ) теряется.
Ну, на счет этого, согласен, стоит подумать) Но просто тот сайт, для которого разрабатывалась эта концепция, предусматривает вообще пользователя как очень активное существо на сайте с кучей принадлежащих ему материалов) Так что… Заполнить небольшую формочку регистрации (быть может даже, состоящую только из полей логина и пароля) ему не должно составить труда)
тут, кстати говоря, как пользователю мне например важнее не плодить ещё раз сущность логина-пароля / измысливать новые. заполнить свои публичные данные — это ОК (особенно если без этого никак), а вот повторный ввод логинов-паролей как-то аннигилирует прибыль авторизации на сторонних площадках
Можно пойти на компромисс в таком случае:
1. Пользователь имеет возможность добавить в свой созданный аккаунт другой сторонний сервис (по Вашему алгоритму из профиля). Но если он этого не сделает перед входом — создавать новый полноценный аккаунт.
2. Если пользователь таким образом случайно заполучил >1 аккаунта и у себя в в профиле (который он считает основным) хочет привязать их к себе — возникает ситуация, что пользователь подтвердил что он это он — но такой сервси уже привязан к другому аккаунту. В этом случае можно эти аккаунты объединить. Берём за основу главный аккаунт (к которому сливаем данные), а всё остальное перекинуть из другого привязанного аккаунта, а сам аккаунт — удалить. В большинстве случаев такое перекидывание ограничится сменой user_id в нескольких таблицах в БД. Операция быстрая и не должна вызвать проблем. Могут возникнуть неприятности, если урлы контента пользователя зависили от его учётки — но это тоже решаемо. В зависимости от политики сайта можно либо проставлять редиректы со старого аккаунта либо просто 404. Ситуация не очень частая, но оставляет довольными большинство, как мне кажется.
Отличие только в том, что мы перекладываем проблемы с пользователя (ручное создание аккаунта после авторизации через сторонний сервис) на себя (слияние двух учётных записей в одну — если такая необходимость вдруг появляется).
Просто в таком случае будут плодиться сущности пользователей без паролей, которые привязаны только к внешнему ресурсу и не имеют логина на самом сайте. Такого не хотелось бы. А вот редко какой человек уже захочет разбираться, сколько каких учёток он там создал, скорее, просто забьет на созданную ранее, и будет входить через созданную сейчас, или будет использовать обе параллельно. Хотя я могу и ошибаться)
Мне вот что до сих пор непонятно. Если не хочется учетных записей, которые авторизуются только через сторонние сервисы, то зачем вообще давать пользователям эту возможность, создавая проблемы как им, так и себе? Почему не оставить только стандартную регистрацию? Дань моде?
Бывает, что меньше фич — это лучше.
Вот потому я и начал статью с того, что велось обсуждение) Конечный вариант так и не был пока выбран, но родил вот такой вот вариант, как если бы его делал я)
Обычно человека зайти на сайт через сторонний сервис мотивирует:
1. Желание обозначить себя в жизни сайта (прокомментировать, создать пост, залить фотографии, поиграть)
2. Нежелание придумывать логин/пароль, оставлять почту, кликать по ссылкам подтверждения, читать капчу.

Если он после такой авторизации не получает полного доступа к сайту без создания аккаунта — его надежда не оправдается.

Плодиться сущности без паролей и логинов в огромном количестве не будут. Это в общей массе людей будет незначительная доля тех кто заходит через все сервисы подряд. И у таких пользователей всегда будет возможность собрать свои аккаунты в 1 подтвердив авторизацию из главного аккаунта.

И в общем случае подтверждённый аккаунт стороннего сервиса мало чем отличается от аккаунта с логином/паролем. Из минусов — отсутствие по умолчанию email-а пользователя для его уведомления. Но ведь если пользователь захочет — он всегда может его оставить.
И не брать в расчёт момент, что вконтакте, твиттер или фейсбук вдруг заблокирует Ваш сайт для своих пользователей.

У меня есть несколько сервисов, где я регистрировался для «посмотреть», приходилось вводить свою почту. И теперь мне регулярно приходят письма от них. Чтобы удалиться/отписаться нужно туда войти, пароль от таких сервисов (которыми заведомо не будешь пользоваться) запоминается не на долго. Восстановление — лишняя операция. Универсальный пароль — опасно. Я был бы очень рад войти туда через учётку в социальной сети, но возможности небыло.

Я просто за то чтобы использовать авторизацию через сторонние сервисы таким способом для которых она изначально предназначалась. А проблемы архитектуры конкретного проекта раскладывать не на пользователей, а решать силами разработчиков.
Ну, на большинстве сайтов авторизация через сторонние ресурсы используется, как правило, в основном для постинга комментов, и прочих незначительных действий. Разрабатываемая реализация предполагала другие возможности учёток)

И вот вы сказали, что в любом пользователь сможет привязать свои аккаунты к одному, тогда какая разница, сделать это потом, или сразу?
Почему повторный? Вводить логин-пароль нужно только один раз — при регистрации) А как она будет — сразу, или при нажатии кнопки «ВОйти через...», а потом «Я хочу зарегистрироваться», это уже дело второе) Суть в том, что в итоге получится одна запись и один логин с паролем)
Вводить имя и пароль бывает нужно при авторизации через сторонние сервисы. Несколько странно после этого вводить имя и пароль при регистрации уже на сайте. Я думаю, именно это имел в виду hydralien.
Ну, учитывая, что человек может захотеть воспользоваться другим паролем, было бы странно насильно приклеивать к учётке имя и пароль на удаленный ресурс. Тем более, учитывая, что их невозможно получить) Так что, это не такая большая проблема
You can use the existing implementation:
www.janrain.com/products/engage/get-janrain-engage

Janrain will back token (secret key) and you can get all profile information.

Additionally you can auto-register/auto-login this user using social email from social provider (Facebook etc).

As a result you can have common registration (username/pass) and via social providers.

По-моему, это просто обертка над OpenID-подобными API различных сервисов. Речь в этом посте совсем о другом — что делать, если на каком-то сайте пользователь зарегистрирован через _несколько_ сторонних сервисов. И неважно, реализовано ли взаимодействие с аутентификационными сервисами через обертку навроде этого Engage, или написан свой велосипед.
Многие велосипеды уже придуманы: github.com/plataformatec/devise — решение для Ruby on Rails. Всё, что вы могли себе представить, плюс то, чего не могли.
Почему не создать N нормализованных таблиц, на каждый из типов аутентификации?

Прям сейчас у вас есть некоторая нелогичность в схеме: одна группа методов аутентификации (твиттеры, фейсбуки и прочие) хранятся в наборе из 2х таблиц, другой метод — в отдельное (аутентификация по логину и паролю).

В случае, если пользователю аутентификация по логину и паролю не нужна — пароль всегда будет пустой. Более того, в этой ситуации поле «пароль» вообще рудиментарное.

Моё предложение:
1. Отдельная таблица, хранящая отвязанные от типов аутентификации поля (id PK, screen_name, register_date, last_login_date, ...)
2. По таблице на каждый метод аутентификации:
— auth_password: id, user_id, login (в случае, если в системе нужен отличный от screen_name), password, salt, email (вероятно для восстановления пароля. вычеркнуть, если не нужно)
— auth_facebook: id, user_id, facebook_uid
— auth_openid: id, user_id, openid_provider, openid_token

Что нам это даёт: стройная логичная схема которая может быть расширена до любых методов аутентификации, даже тех, которые не вместятся в описываемую вами схему.
Вариант вполне приемлем, только, согласно теории нормализации баз данных, я разъединил таблицу auth_facebook)
Разъединили на что?
И что в моём варианте не нормализовано?
В том смысле, что у вас хранятся отдельные таблицы для каждого сервиса. А это не кошерно, хотя бы потому, что мы не знаем, сколько у нас будет внешних ресурсов. А так как ручками править базу после запуска проекта это не комильфо, то такие вещи не нормализованы. Потому и, как у меня в варианте, создается отдельная таблица со списком внешних ресурсов.

А вот, следуя вашей логики, таблицу связей, в принципе, можно сделать таблицей логинов на этих ресурсах, это да)
Эм «не кошерно»? Так не кошерно или расходится с НФ? Давайте сначала определимся, следуем мы теории проектирования или это ваши субъективные предпочтения?

После старта проекта модифицировать и схему базы и код вполне себе штатная ситуация, это называется развитие проекта.

Ваша реализация потребует модификации кода, для добавления нового типа аутентификации, но вы, почему-то, считаете модификацию кошерным процессом. Равно как и модификацию таблицы-справочника провайдеров авторизаций — тоже кошерной. Я вашу логику категорически не понимаю.

Давайте теперь представим систему аутентификации аналогичную банковскому сейфу, в котором необходимо использовать два ключа. Озвучьте, что придётся модифицировать в вашем варианте (только не забывайте, что вы следуете теории нормализации и что ключи сливать в одно поле нельзя) и что нужно будет сделать в моём варианте.
Я написал «не кошерно», в смысле, что там не хорошо делать, потому что расходится с НФ.
В моем случае, модификация кода представляет собой, по сути, добавление нового плагина (модуля, хелпера, как угодно назвать можно), который следует API сайта, для того каждому удаленному ресурсу и дается свое машинное имя, чтобы по нему вызывать соответствующие функции. А вот при добавлении модуля таблицу удаленных служб нужную строчку добавляет сам модуль, никакой ручной модификации.

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

>> В моем случае, модификация кода представляет собой, по сути, добавление нового плагина
И что? Что смертельного в схеме структуры таблиц? Вы ни разу не писали проектов, на которых в миграциях периодически спускалисьмодификации?

Про сейф: представьте, что появляется тип аутентификации, для которого нужно вводить 2 пароля. Его вводят 2 человека. Как вы будете это у себя хранить?
У меня я бы сделал таблицы связей «ID ячейки — ID ключа1 — ID ключа2» и «ID ключа — ID человека». Ибо у человека может быть несколько ключей, и ячейку открывают обязательно два ключа. Заранее скажу, на случай будущих вопросов, вместо первой таблицы можно вообще сделать прямую связь «ID ячейки — ID ключа», тогда количество ключей, открывающей ту или иную ячейку, не лимитировано. Вся эта система учитывает, что как у ячейки могут меняться ключи, так и у ключа владельцы.

А по поводу нормализации, учитывая, что вы хотите разбирать таблицу, содержащую список доступных служб, на отдельные таблицы служб, совмещенные сразу с таблицей привязки, да, это не нарушение, в принципе, но по третьей форме нормализации, так как содержимое всех таблиц вида auth_facebook, auth_vkontakte и т.д. одинаковое, то логичнее службы вынести в отдельную таблицу. Плюс, частично, она не соответствует нормальной форме Бойса-Кодда.
Содержимое разное. Это абсолютно разные сущности, которые отражают разные объекты реального мира. То, что у них поля одинакового типа ни капли их не делает «одинаковыми». Это просто совпадение. Такие совпадения никак не должны влиять на процесс проектирования.

>> У меня я бы сделал таблицы связей
Т.е. я правильно понимаю, что в вашу текущую реализацию эта схема аутентификации не «помещается» и вам приходится модифицировать схему?

Тогда я не понимаю преимуществ вашего подхода: он недостаточно гибкий, чтобы хранить любой возможный способ аутентификации. В вашем варианте вы данные валите в кучу, в угоду того, что не нужно модифицировать таблицы. Да-да, вы пытаетесь мне укзаать на 3НФ, а сами при этом числовые идентификаторы из fb хранить рядом со строковыми для openid. Не находите противоречий?
Ну вот по поводу таблицы связей, да, согласен, она у меня тоже не нормализована, если на то пошло, ибо статья писалась поздно и думать было тяжко) Каюсь, мой косяк) Если разбить таблицу связей на две, получится, по сути, та же банковская система.

Но вот вопрос в другом. А зачем вам в таблицах auth_vkontakte, auth_facebook и т.д. хранить что-то, кроме ID на этом ресурсе и ID на нашем? Все механизмы получения/обработки/проверки токенов будут делать наши подключаемые модули, хранить токены, как мне кажется, нет смысла, ибо (кто его знает), вдруг, каким-то образом, изменится механизм их генерации, или что?

Я делал из расчета, что нам нужен только настоящий ID на внешнем ресурсе)
Кстати, дополнение, идентификатор в любом случае записывается в БД как строка, будь он числом или строкой. Ибо работа с ним всегда будет, как со строкой
Ну это у вас так :-) А у меня это по-честному число:

CREATE TABLE auth_facebooks(
id INT (11) NOT NULL AUTO_INCREMENT,
facebook_id BIGINT (20) UNSIGNED NOT NULL,
user_id INT (11) NOT NULL,
PRIMARY KEY (id),
INDEX auth_facebooks_user USING BTREE (user_id),
UNIQUE INDEX facebook_id USING BTREE (facebook_id),
CONSTRAINT auth_facebooks_user FOREIGN KEY (user_id)
REFERENCES users (id)
)

Нет, ну если с такой точки зрения, то конечно проще разделять, ибо объединять вообще никак не получится))
Вот как раз потому, что если что-то изменится — я хочу иметь мух полностью отделённых от котлет.

Новый метод аутентификации — новая таблица. Я считаю, что это разумно.
А разве только хранимый в базе идентификатор на внешнем ресурсе, это не та самая муха?
Та самая муха — это способ аутентификации.

Я не вижу смысла валить всё в кучу и ограничивать себя.

Как я понял — ваше решение проверку боем и сферическим методом аутентификации с 2 токенами (2 паролями) не выдержало и пришлось таки изменять схему (делая её ещё более ненормализованной).

В моём случае — это будет ещё одна специфическая таблица, в которой будет ровно столько столбцов ровно того типа, что мне нужно :-)
Ну, кстати, мне тут предложили вариант, что вообще не нужно поле для ввода ID на внешке, достаточно надпись, например, «Вконтакте», а рядом сразу кнопку «Привязать», по которой сразу произойдет авторизация и получение хэша и айди от контакта, и в таком случае мы сразу заносим этот ключ в БД, без генерации своего токена) Мое поле для ввода было, как… Даже не знаю) То ли дань безопасности, то ли усталость мозга)

Просто у меня все функции авторизации были модульными, они никак не мешали и легко отключались бы. А если убрать генерацию токена, за ними останется одна функция вообще — получить из набора данных тот самый идентификатор и занести его в БД)
Я в своем проекте на django реализовал следующее (с помощью django_authopenid): к стандартной регистрации/авторизации добавляется авторизация по openid. Если пользователь авторизуется вторым способом, то после возврата положительного значения openid-сервером ему предлагается связать свой openid с реальным аккаунтом (если еще не создан -то создастся на основе принятых данных).
а какие логин и пароль будут (если будут) у созданного аккаунта?
Пользователю за твиттер-логином запросто можно разрешить изменить эти два значения.
Пароль генерируется автоматически. Логин берется от openid-провайдера (если занят — предлагается ввести другой). В дальнейшем юзер заходит по openid.
Ну вообще-то звучит неотличимо от моей реализации) Ибо пользователю так же, при входе с внешнего ресурса, предлагается или привязать себя, или создать новый акк)
тут разница в «привязать или создать» vs «привязать или оставить как есть». Нельзя заставлять OpenID-пользователя придумывать для вашего сайта пару логин-пароль.
Ну, по сути, мы заставляем не Опен-Айди пользователя придумать ник, а обычного, чтобы создать реального себя на сайте. А Опен-Айди это будут, по сути, плюшки)
это убой системы OpenID
Почему? OpenID служит, в первую очередь, для входа на сайт. Если уж на то пошло, OpenID можно оставить по факту для входа, а не для регистрации, и тогда проблема сама исчезнет.

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

Да ну? Фицпатрику расскажите.

OpenID — это способ идентификации пользователя. ЖЖ — это пример сайта, который родился и набрал первые 10М пользователей до появления каких-бы-то-ни-было сторонних авторизационных сервисов. Им можно :-)

Сегодня на дворе не 1999, а 2011. Веб-сто-ноль, то-сё. Тыц в кнопочку твиттера — всем привычен и понятен. А процедура регистрации ради неведомого рая в будущем — увольте.
Ну, не спорю) Просто, чтобы и волки сыты, и овцы целы, такого в принципе редко удается добиться, как правило, пастух остается без какой-либо конечности) Тут уже придется, как в старом анекдоте, «обработать молотком, зубилом, напильником» под конкретные нужды)

Тут много разных вариантов предлагалось, в том числе, которым не нужна привязка, но я всё-таки озадачусь этим вопросом, когда буду писать такую штуку!)
На мой взгляд, нет ничего страшного в том, что пользователь может войти через разные службы. Достаточно просто свести их количество к минимуму. В своих проектах я использую логинзу, но допускаю только 3 службы — фэйсбук, твиттер и вконтакт. Эти три почти полностью покрывают аудиторию. А в своих приложениях я держу таблицу profiles, которая содержит UID учетки в стороннем сервисе и поля для дополнительных характеристик профилей.
А я пользуюсь OpenID только от Gmail, иначе — регистрируюсь.
Ждем появления сервиса наподобие AntiReg для твиттера.

Регистрирует для тебя fake-twitter account, и сразу через него же и логинит на злобный сайт, не пускающий по OpenID.

;-)
Мы в Loginza реализовали механизм связывания учетных записей (пока через только через кабинет clip2net.com/s/SvZV), но в скором времени добавим и в виджет.

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

Надеюсь был полезен :)
Два соображения.

Во-первых, я думаю, имеет смысл человеку, залогинившемуся через СтороннийСервис1 — подкладывать куку, которая будет тише воды ниже травы вплоть до попытки логина через СтороннийСервис2. Когда это произойдет — имеет смысл спросить: «А не хотите ли вы, милейший, привязать еще какой-нибудь аккаунт?». Даже если сначала моя любовница с моего компьютера залогинится на ваш сервис вконтактегом, а потом супруга попытается логиниться фейсбукегом — такое предложение не вызовет подозрений. Минусы очевидны, но зато и плюс огромен (на мой взгляд) — ненавязчивость предложения. Все-таки процентов, думаю, 95 пользователей (все не гики, у которых по сто аккаунтов во всех немыслимых сервисах) — пользуются для авторизации на сторонних сервисах чем-то одним.

Во-вторых, многие сервисы отдают e-mail — вот он, ваш уникальный ID. А при логине через, например, твиттер, который почтовый адрес не отдает — можно ненавязчиво попросить ввести именно его. Это быстрее и проще для пользователя, чем создавать учетку. И вот тут-то — оп-па — можно прозрачно создать локальный аккаунт и дальше двигаться по вашей схеме. Пользователь может даже не предполагать, что у него появилась учетка на вашем сервисе, а вы его следующий логин через OpenID — спокойно провяжете с существующим аккаунтом.
Ну, во-первых, если клянчить почту, это не кошерно. Почта это дело личное, и если она не является логином на сайт, просить ее не хорошо)

А во-вторых… Мне нравится идея с кукой) Надо подумать)
Клянчить вообще нехорошо ;-)

Я предлагал ненавязчиво предложить ее ввести. Это не криминал — почту принято использовать для восстановления пароля, пользователи к этому привыкли.
Я тут так подумал… есть помоему решение лучше. А именно: пользователь при регистрации выбирает себе уникальный ЛОГИН. Важно, чтобы это был логин, а не эмейл, с которым пользователь себя ассоциирует.
Затем, при авторизации, пользователь вводит только его. Метод авторизации выбирает сама система.
Подвариант — при авторизации пользователь вбивает логин и выбирает сервис, через который хочет авторизоваться. Авьоризуемся сразу на обоих (учитывая что многие залогинены уже на сервисах и поставили галочку «больше не спрашивать» то вызов второй процедуры с большой вероятностью авторизации пройдет по тихому), и если втопой сервис не совпадает с первым — привязываем автоматически.
Ну в принципе, как вариант облегчения моего алгоритма) Я тоже основывался на уникальном каком-то поле, будь то логин, пароль или девичья фамилия матери) Просто, если спросить у пользователя одно поле логина, почему бы не спросить у него и второе поле пароля? Не велика потеря будет)
Тогда потеряется вообще вся идея с OpenID/OAuth/т.д. авторизациями жеж…
Основная масса негодования здесь приходится на то, что один раз придется заполнять имя и пароль) Хотя, по сути, выполнив эту процедуру, получишь кучу готовых к работе внешних логинов, не заморачиваясь) Честно, не знаю… Мне, например, было бы не в падлу привязать себя и потом пользоваться)
Не заполнять, а придумывать и помнить!

Ибо соображения безопасности не дают вводить то, что уже даёт доступ к чему-то ещё. Это весьма весомое препятствие желанию зарегистрироваться.
Я тут уже в разных местах поотписывал, и не помню где, но смысл в том, что сама структура будущего проекта предполагает, что важна физическая учётка, а нее OpenID логины) Логины на то и логины, что через них входить, а не работать)
Дык делайте себе ту физическую учётку. Но на кой к ней требовать ещё один логин с паролем-то?
OpenID не позволит создать в полной мере уникального пользователя на сайте, потому что его уникальность будет именно в том, что он зарегистрирован на нашем сайте, а не на фейсбуке или контакте.

Для этого и велось наше обсуждение и была написана эта статья, чтобы сделать способ оставить фактически одну учётную запись, но просто позволить входить в нее с других. По факту, пароль и логин вводится только один раз, остальное — ряд простых действий, которые пользователь и так будет делать, потому что ему необходимо будет, как минимум, заполнить данные своего аккаунта
Похоже, Вы за своими мыслями пока не видите моей аргументации…
Почему просто не использовать e-mail как идентификатор? Ведь почти все сторонние сервисы авторизации дают к нему доступ
Ни фэйсбук, ни вконтакте, ни твиттер не дают доступа к email'ам пользователя.
На fb, правда, есть собственная почта — но её пользователь должен включать вручную.
Да, я писал об этом выше, почта это слишком личная информация)
Насчет твитера и контакта не знаю, но фейсбук отдает email пользователя совершенно точно, достаточно лишь указать это в списке запрашиваемых ресурсов.
В принципе, такие нюансы можно предусмотреть в тех модулях, которые разбирают пришедший от внешнего сервиса ответ, и там уже разбирать полученную информацию, как надо)
Я правильно понял, что вы описали инструмент дающий возможность пользователю руками связать разные свои профили в разных системах?

И в чем ценность всех этих рассуждений? Поймите, нет никакой проблемы в том, чтобы дать пользователю возможность вручную связывать аккаунты. Любой более-менее опытный человек придумает как это реализовать на техническом уровне.

Придумайте лучше как их связывать без участия пользователя.
Увы, как бы далеко ни шагал прогресс и робототехника, всегда останутся вещи, которые сможет делать только человек. Я стараюсь найти такой вариант) Если получится — здесь будет соответствующая статья)
Всегда есть промежуточный шаг.
Не заставлять пользователя это делать насильно, а помогать ему разобраться с проблемой, давать подсказки, давать возможности.

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

Проверь, не авторизован-ли он в других соц. сетях когда он регистрируется или авторизуется и спроси — не его-ли это аккаунт. Зачем городить страничку, где мне надо указать какие-то непонятные для меня ID?

Вообще, не техническую проблему решай, а пользовательскую. И вот решения того, как реализовать такие процессы, когда система угадывает проблемы пользователя или предлагает ему новые возможности за бесплатно — вот это будет очень интересно почитать.
Ну вообще, согласен, юзабилити и дружелюбие рулят) Просто я описывал строго алгоритмическую последовательность, не включающую в себя различные фишки вроде «Может быть, это вы?», потому что это уже вопрос развития системы) Мне был интересам сам механизм однозначной идентификации)
Главное, это то, что у меня внешние логины не обладают учётной записью, под это и всё остальное вытекает, а если сделать некие полу-аккаунты физическими, то вполне возможно и то, что написали вы)
Плюс стосемьсот.

За фразу «не техническую проблему решай, а пользовательскую», сказанную на собеседовании, я бы немедленно взял на работу.
Пара ¢:

Можно было бы стащить foaf с обоих аккаунтов, если бы его хоть кто-то отдавал нормально (я, кстати, близок к тому, чтобы написать про иэ́блю с foaf даже от тех, кто декларирует, что отдает — lj, ya.ru, …). Совпадения ников и частичное — foaf'ов может гарантировать с высокой долей вероятности причастность одного аккаунта другому. Для твиттер-логина после, скажем, fb — сейчас можно вручную пройти по всем «друзьям» и спросить: «а вот такой никнейм — тебе ль не друг»? Хотя имитировать foaf наколеночными запросиками — как-то не по-пацански.

Можно еще после логина через шмиттер — прогнать сразу OAuth-запрос и через гмэйсбук и рконтакте, а потом (если пришел редирект, — сиречь, такой пользователь в гмэйсбуке зарегистрирован), мягенько, ненавязчиво, приспросить: «Мил человек, а давай мы тебе еще провяжем с нашим аккаунтом — вот эти сервисы, ты же вроде там зарегистрирован?
Про собеседование спасибо, я запомню) Правда, полезно)

А вообще, идея хорошая, но… Разве то, что пользователь ходит по сайту, а система сама там шарится в его куках и сессия, отправляя запросы на различные вконтактики и фейсбуки, это… не нагло?)
В куках шариться вам так и так не позволят — частная собственность.

А отправить запросы… Знаете, тут нужно считать КПД и класть с пробором на параноиков. Вы стянуть же ничего не пытаетесь, так? Помогаете? — Несомненно.

Пользователь, как я выше уже писал, будет счастлив, если ему помогут. А гиков (и меня, да) — нужно изолировать от нормального общества.

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

Кроме шуток.
Рад, что мы оставили друг у друга хорошие впечатление… эээ… друг о друге))
Интересно, мы реализовали на 90% похожий подход, и работает отлично. К сожалению, проект пока в стадии «закрытая бета», но саму библиотеку, которая реализует принцип связей я показать могу — делал от нее форк, чтобы добавить дополнительных сервисов авторизации: Django Social Auth. Каждый сервис авторизации предоставляет информацию чтобы в будущем точно определить однажды авторизовавшегося пользователя повторно. Нафиг клонов :)

В целом принцип авторизации такой:
1. При заходе нового пользователя через любую из соцсетей, в таблице пользователей создается новый юзер, используя те, порой очень скудные данные, которыми с нами соизволил поделиться провайдер авторизации. Эта запись считается «неполной» до прохождения полной регистрации. Тогда же создается привязка в таблице номер 3 в вашей классификации (таблицы 2 у нас просто нет).
2. В неполной учетной записи пользователь не может менять свой юзерпик и делать другие мелочи, но вся основная функциональность работает, и вся деятельность пользователя, что для нас важно, сохраняется.
3. Когда потом он проходит полную регистрацию он получает возможность добавлять или убирать связи. Для неполных эккаунтов пройти регистрацию чуть проще, чем с нуля.
4. Есть базовый способ слияния записей: если система видит, что e-mail, который отдает социальный сервис при авторизации, совпадает с имеющимся в базе, то привязка идет к тому же пользователю.
Ну, как вариант, очень даже) Вот только какие сервисы у вас отдают email?)
Google OAuth. Плюс на яндексе имя для авторизации + @yandex.ru = email :)
А, ну может) Просто, насколько я видео, авторизация через гугл и яндекс пока не распространена повсеместно) В основном, это те самые контакт, фейсбук и твиттер)
Да, с этими /печаль.
И не говорите. Самому удобнее было бы через гугол авторизоваться
мы остановились на следующих сервисах: гугл, ЖЖ, яндекс, вконтакте, твиттер, фейсбук и просто openid (url для авторизации). любопытная подробность: при логине через openid на гугл почтовый адрес не показывается, а вот через oauth — пожалуйста. это была одна из причин, по которой мы стали использовать oauth для гугла, вторая — это из-за заморочек с поддоменами, но это длинная скучная телега.
Ну, кстати, с поддоменами мне тоже придется еще возиться, а вот это уже наталкивает на размышления о том, что уникальным ключом регистрации на сайте всё же сделать не почту, а логин)
у нас логин=почта :) самое простое оказалось решение.
А поддомены пользователей по какому идентификатору берете? По принципу контакта, кто успел, тот и взял?
здесь у нас попроще — поддомены только для корпоративных пользователей.
При использовании OpenID для гугла можно запросить email добавлением дополнительного параметра в authenticationUrl (что-то вроде ext1.required=email).
Facebook позволяет получить email. Для этого необходимо добавить в OAuth authorization url параметр scope=email. Вот twitter и VK не выдают мыл.
Ну, поскольку такие службы выдают разное количество и качество инфы, единым у них остается идентификатор пользователя) Так что, либо делать мою реализацию так, как подсказал zerkms, чтобы была возможность по разному обрабатывать такие данные, либо ограничиться моим способом привязки)
Ну лично мое мнение — Ваш способ не очень, поскольку требует при заходе с любого ресурса проведения полноценной регистрации. В идеале этого быть не должно. Пользователь должен иметь возможность войти с помощью твиттера, дозаполнить необходимые поля (email, если какой-нибудь твиттер его не предоставляет), и полноценно работать с системой. А потом при желании ткнуть кнопку наподобие «Я могу еще заходить с ресурса YYY», и смерджить 2 аккаунта. Ключевое здесь — алгоритм мерджа акков, не всегда его можно реализовать.
Так получается, то, что вы описали, и есть, по сути, ветвь моего алгоритма. Ибо, регистрацию можно сделать прозрачной. Человек, даже если зайдет под аккаунтом внешнего ресурса, как вы говорите, должен будет заполнить информацию, но это заполнение может быть и регистрацией, после которой он может привязать другие внешние логины. А вообще, то, что вы сказали, это правдиво, я давно начинался здесь полезных советов и уже обдумываю способ такой связи аккаунтов)) Так что, спасибо за комментарий)
Название статьи порадовало)
Sign up to leave a comment.

Articles