Единый вход OmniAuth с помощью Devise, invalid_credentials

У меня есть 3 веб-приложения - A, B и C. Приложение A содержит базу данных пользователей. При доступе к приложению B и приложению C я хотел бы, чтобы пользователь был перенаправлен в приложение A для аутентификации, а затем возвращен обратно в любое приложение, к которому он пытался получить доступ. В то же время они должны быть авторизованы во всех приложениях. Если у кого-то нет лучшего решения, я выбрал комбинированное решение OmniAuth/Devise, как описано в этот пост в блоге.

Я развил и обновил до Rais 3.1.2 образец приложения A и образец приложения B/C.

Приложение А — поставщик — https://github.com/RobZolkos/sso-devise-omniauth-provider

Приложение B/C — клиент — https://github.com/RobZolkos/sso-devise-omniauth-client

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

Я упустил что-то простое, чтобы эти примеры приложений работали?


person robzolkos    schedule 21.11.2011    source источник
comment
провайдер получает и отправляет, кажется, работает нормально, вы возвращаете токен и секрет от провайдера после публикации?   -  person Benjamin Udink ten Cate    schedule 21.11.2011
comment
После поста возвращаю токен но не секрет. Строка рендеринга json: render :json =› {:access_token =› access_grant.access_token, :refresh_token =› access_grant.refresh_token, :expires_in =› Devise.timeout_in.to_i}   -  person robzolkos    schedule 21.11.2011
comment
Я попытался сделать то же самое и столкнулся с той же проблемой. Похоже, что пользователь никогда не входит в систему. Если я попытаюсь вывести warden.session в журнал (в приложении провайдера), я получу исключение Warden::NotAuthenticated. То есть фильтр authenticate_user! перед возвращает false, и поэтому он не работает.   -  person Frost    schedule 01.12.2011


Ответы (2)


Я нашел две проблемы:

  1. Начиная с версии 0.2.1 omniauth изменил имя параметра аутентификации с access_token на oauth_token при получении доступа (запрос POST /oauth/token).
  2. Начиная с версии 0.3.0, omniauth изменил метод передачи oauth_token в запросе аутентификации (GET /auth/josh_id/user.json). До 0.3.0 токен передавался через параметр запроса oauth_token, но начиная с 0.3.0 он стал передаваться через заголовок HTTP_AUTHORIZATION.

Я не знаю, как красиво получить токен из заголовка (я думаю, его можно получить с помощью devise), поэтому я уродливо взламываю клиент для отправки oauth_token через параметр GET следующим образом (в lib/josh_id.rb):

def raw_info
  @raw_info ||= access_token.get("/auth/josh_id/user.json?oauth_token=#{access_token.token}").parsed
end

Вы можете найти полностью рабочий код в наших репозиториях на github:

person Dmitry Lihachev    schedule 06.12.2011
comment
Этот патч уже применяется в github.com/joshsoftware/sso-devise-omniauth-provider Я настоятельно рекомендую вам использовать github.com/applicake/doorkeeper - person Dmitry Lihachev; 12.03.2013

У меня нет опыта работы с oauth в rails, но я объясню процесс, который я использовал для создания собственного провайдера на Java. Это должно быть легко применить в рельсах. Если вы используете Devise с omniauth, вам нужно выяснить, как они обеспечивают поддержку OAuth и какая версия.

Основы

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

  • Все запросы OAuth зависят от правильного заголовка OAuth в запросе. Правильный заголовок означает:

    1. All oauth attributes and their values have been alphabetically sorted
    2. Предоставляются все ключи/токены, активные для конкретного запроса Потребителя.
    3. Запрос подписывается с использованием всех соответствующих секретов. Секреты известны поставщику и потребителю, но не включаются в заголовок.
    4. Поставщик генерирует ту же подпись. Если да, то запрос действителен. Одноразовый номер может использоваться для предотвращения повторных атак.

Двунаправленный поток (потребитель против поставщика)

  1. Потребитель запрашивает ресурс, предоставляя Consumer_key.
  2. Провайдер проверяет подпись на основе Consumer_key и Consumer_secret
  3. Доступ к ресурсу предоставлен

Трехсторонний поток (человек против потребителя против поставщика)

  1. Ресурс потребительского запроса, предоставляющий его Consumer_key
  2. Потребитель получает неподписанный oauth_token и oauth_token_secret от поставщика.
  3. Пользователь (лицо с учетной записью пользователя у провайдера) входит в систему у провайдера, чтобы авторизовать oauth_token, предоставляя oauth_request_token и Consumer_key
  4. У потребителя есть авторизованный request_token
  5. Потребитель использует request_token для запроса access_token, предоставляя oauth_request_token и Consumer_key
  6. Провайдер предоставляет access_token и access_token_secret для конкретного ресурса.
  7. Потребитель использует access_token, чтобы что-то сделать
  8. Провайдер аннулирует access_token по истечении определенного времени
  9. Потребитель снова использует request_token, чтобы получить новый access_token, если срок его действия истек.

Подходящим ресурсом для oauth является официальный сайт. Трехсторонние примеры можно найти на площадке oauth Google.

person Benjamin Udink ten Cate    schedule 21.11.2011