Как создать службу общего входа через несколько доменов? - PullRequest
30 голосов
/ 29 ноября 2010

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

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

Я проверил их сеансовые куки, чтобы понять, что они делают в процессе.Первоначально, каждая ссылка на продукт имеет "goto" uristub, то есть:

https://MY_COMPANY.campfirenow.com/id/users/[int_identifier]/goto

Используя FireCookie и вкладку NET в Firebug, я могу видетькуки, которые установлены и перенаправления, которые происходят в процессе.URL goto запускает перенаправление 302 на:

https://MY_COMPANY.basecamphq.com/login/authenticate?sig=[BASE64_ENCODED_AND_ENCRYPTED_DATA]

Идентификатор сеанса воссоздается, скорее всего, для целей CSRF.Некоторые данные в файлах cookie, а также в параметре GET sig были частично расшифрованы с использованием base64_decode:

// sig GET param
array(2) {
  [0]=>
���ף�:@marshal_with_utc_coercionT7�z��<k��kW"
  [1]=>
  string(18) "���k�<kn8�f���to��"
}

// _basecamp_session cookie session param
string(247) {
:_csrf_token"1Sj5D6jCwJKIxkZ6oroy7o/mYUqr4R5Ca34cOPNigqkw=:session_id"%060c0804a5d06dafd1c5b3349815d863"
flashIC:'ActionController::Flash::FlashHash{:
@used{: auth{"
              MY_COMPANY{:
                       user_idi�3
:identity_idi�W����������s�]��:�N[��:

߾����� "

Кодировка нарушаетБлок кода. Спасибо за помощь!

Ответы [ 7 ]

60 голосов
/ 01 января 2011

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

Я объясню: Вы хотите иметь возможность перейти с site1.com на site2.com и сообщить site2.com, что вы являетесь пользователем, который вошел на сайт site1.com.

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

давайте начнем с наивного решения, а затем поработаем над решением некоторых проблем, которые оно ставит: Предположим, у вас есть таблица пользователей в некоторой внутренней базе данных, а у вашего пользователя есть некоторый идентификатор. Теперь предположим, что пользователь прошел аутентификацию на сайте site1.com, и он является пользователем 123 из вашей БД. Наиболее наивным решением было бы позвонить на site2.com/url/whwhat?myRealID=123 и пусть site2 проверит этот идентификатор и "поверит" пользователю, что это действительно он.

Проблема: любой (даже действительный пользователь вашего сайта), увидевший вашу ссылку, может создать ссылку с myRealID = 123 или попробовать другие значения для нее. и site2.com примет его как этого пользователя.

Решение: позволяет не использовать предположительные идентификаторы. Предположим, что вы добавляете в свою таблицу пользователей уникальный GUID, а если у пользователя 123 есть guid 8dc70780-15e5-11e0-ac64-0800200c9a66, то позвоните на site2.com/url/whwhat?myGuid=8dc70780 -15e5-11e0-ac64-0800200c9a66.

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

Решение: используйте личный ключ, сохраненный на вашем сервере, чтобы подписать строку, содержащую следующие элементы данных, текущую метку времени, сайт назначения (то есть "site2.com"), указанный GUID, эту подпись можно перевести в высказывание «Это доказательство того, что эта ссылка была создана сайтом в указанное время для пользователя, который имеет этот GUID для аутентификации на этом домене» и отправляет его на site2.com вместе с отметкой времени и GUID. Теперь, когда site2.com получает ссылку, он может удостовериться, что она подписана правильно, и если какой-то посредник или изначально пользователь попытается изменить ее каким-либо образом (моё изменение времени или GUID), тогда подпись не будет соответствовать и site2. com откажется аутентифицировать пользователя.

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

Решение: добавить одноразовый номер к переданным параметрам. Одноразовый номер - это просто случайное число, которое ваша система аутентификации должна удостовериться, что оно не позволяет вам проходить аутентификацию с этим номером более одного раза (отсюда и имя N (umber) -ONCE). Обратите внимание, что это означает, что каждая ссылка, которую вы создаете на site1.com и которая ведет на site2.com, должна иметь отдельный одноразовый номер, который необходимо сохранить на сервере для последующей проверки.

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

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

Эяль

5 голосов
/ 05 января 2011

Вы можете попробовать внедрить решение Global Network Auto-Login в виде переполнения стека.
Здесь есть проницательный пост о его блестящей реализации Кевином Монтрозом здесь .

Для этого потребуются файлы cookie, HTML5 localStorage , Javascript, Iframe и множество проверок безопасности, но я думаю, что оно того стоит.

1 голос
/ 05 января 2011

Предоставление пользователям возможности использовать их решение на Facebook / yahoo / gmail / openID - это только начало, но это не решает проблему внедрения или использования собственного решения.

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

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

0 голосов
/ 19 января 2011

Используйте что-то вроде .NET Passport (IE. Windows Live Id) или как Facebook сделал это с их API, который можно открыто просматривать.

0 голосов
/ 05 января 2011

Почему бы не использовать Open ID для этой цели.

OperID будет оптимальным решением для этой проблемы.

0 голосов
/ 04 января 2011

Посмотрите на Jasig CAS http://www.jasig.org/cas.Я думаю, что это будет делать то, что вы хотите.Он с открытым исходным кодом и имеет ряд плагинов, позволяющих вам аутентифицироваться, используя несколько источников аутентификации и из нескольких доменов / языков.

0 голосов
/ 31 декабря 2010

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

Как уже упоминалось в FlipScript , возможно, использование OAuth / OpenID может быть для вас шагом вперед?

...