OAuth на мобильном телефоне, использующем прокси-сервер, слишком много проблем?
Последние несколько дней я потратил на подготовку и запуск реализации OAuth. Не на Android, а на моем веб-сервере, который будет выступать в качестве прокси для защищенной службы OAuth. Я как раз собираюсь внедрить свой Android-клиент, и моя голова все еще волнуется из-за проблем безопасности и реализации.
OAuth достаточно грязный, когда клиент просто веб-браузер. У вас есть следующие серии шагов:
- (клиентский веб-браузер) сделать запрос на мой прокси-сервер
- (прокси-сервер) запрашивает неавторизованный токен у поставщика OAuth (например, API веб-службы)
- (прокси-сервер) попросить поставщика OAuth разрешить пользователю авторизовать токен. Перенаправить веб-браузер на URI авторизированного поставщика OAuth
- (Поставщик OAuth) после того, как пользователь завершит авторизацию, перенаправит браузер на ваш URI обратного вызова
- (proxy server::callback URI) Exchange авторизационный токен для токена доступа и затем сохраните его для будущих вызовов
- Выполните вызовы API для поставщика OAuth и верните ответный документ в клиентский веб-браузер
Теперь этого вполне достаточно. Но при использовании той же механики с мобильным приложением в качестве клиента оно становится еще более сложным. Проблема, конечно, заключается в том, что вам нужно выполнить акробатику, чтобы внедрить сеанс браузера в поток кода вашего мобильного приложения во время танца OAuth. Это означает, что вам нужно еще больше усложнить танец OAuth следующим образом (я использую приложение Android для этого примера, чтобы конкретизировать вещи):
- (мобильное веб-приложение:: собственный код) сделать запрос от прокси-сервера, используя Java/HTTP
- (прокси-сервер) запрашивает неавторизованный токен у поставщика OAuth (например, API веб-службы)
- (прокси-сервер) возвращает ответный документ в мобильное веб-приложение, которое содержит URI перенаправления для авторизации пользователя провайдером OAuth, предпочтительно запутанный, чтобы скрыть ключ потребителя и другие подробности для предотвращения отслеживания "по воздуху".
- (мобильное веб-приложение) Запустите веб-браузер с URL-адресом авторизации с установленным фильтром намерений. Однако сохраните, а затем замените указанный URI обратного вызова прокси-сервера специальным "фальшивым" URI, созданным для простой идентификации URI фильтром намерений (см. Следующие шаги)
- (Поставщик OAuth) после того, как пользователь завершит авторизацию, перенаправьте браузер на ваш "фальшивый" URI обратного вызова.
- (мобильное веб-приложение) Фильтр намерений обнаруживает "ложный" URI обратного вызова и использует этот сигнал для восстановления контроля. Восстановите URI обратного вызова прокси-сервера и используйте Java/HTTP для выполнения запроса.
- (proxy server:: callback URI) Обменяйте токен авторизации на токен доступа и сохраните его для будущих вызовов, как и раньше
- Выполните вызовы API для поставщика OAuth и верните ответный документ в мобильное веб-приложение.
Это довольно отвратительно, как вы можете видеть. Если есть намного более простой способ сделать это, то я очень хочу это услышать. Насколько я знаю, есть только две другие альтернативы, каждая со своими значительными проблемами.
1) Забудьте про прокси-сервер и делайте все прямо из мобильного веб-приложения. Большая дыра в безопасности заключается в том, что вы должны "запекать" свой потребительский ключ OAuth и хранить секрет в своем приложении. Если злоумышленник декомпилирует ваш код и отыщет эти строки - довольно простая операция для тех, кто имеет опыт обратного инжиниринга, он может нанести ущерб вашему приложению и пользователям.
2) Переключитесь на XAuth, где пользователь предоставляет вам свои логин и пароль, и вы "соглашаетесь" не хранить их и не обменивать их напрямую на токен доступа с сервером XAuth. Первая проблема - завоевание доверия пользователей к предоставлению этой информации, проблема, которую OAuth был создан для решения, и, конечно, как насчет людей, которые не соблюдают свое обязательство отказаться от данных для входа? Хуже того, сервер XAuth должен поддерживать XAuth и предлагать HTTPS (SSL) соединения, и я видел множество веб-API, которые тоже не поддерживают. Разумеется, SSL-соединение необходимо, потому что без него вы отправите имя пользователя и пароль по сети в виде простого текста при выполнении запроса XAuth.
http://blog.zyber17.com/post/1283741364/why-xauth-is-a-really-dumb-idea
К вашему сведению, хотя он не использует прокси-сервер, следующий пример иллюстрирует метод, который я описал выше, для внедрения сеанса браузера в OAuth-взаимодействие вашего мобильного приложения и перехвата URI обратного вызова:
http://blog.doityourselfandroid.com/2010/11/10/oauth-flow-in-android-app/
Таким образом, это выглядит довольно уродливо, если вы смотрите на него, и я даже не стал испытывать дополнительное раздражение от создания и управления вашим собственным идентификатором пользователя для пользователя, чтобы вы могли правильно просматривать его токены доступа, хранящиеся на вашем прокси-веб-сервере (включая беспорядок еще один PIN-код или код доступа для пользователя для управления).
Интересное примечание: проводя некоторые исследования безопасности сеансов веб-браузера Android, я с удовлетворением обнаружил, что у вас нет доступа к текущей веб-странице HTML. Если бы вы могли получить к нему доступ, то враждебный Android-кодировщик мог бы легко узнать имя пользователя и пароль, тем самым полностью разрушив цель и намерение OAuth. Я был встревожен, узнав, что может быть способ получить этот HTML с помощью объекта CacheManager. Любопытно, что этот объект теперь устарел и планируется удалить в соответствии с документацией по Android, поэтому мы надеемся, что это означает, что Google обнаружил (потенциальную) дыру в безопасности и предпринимает шаги по ее удалению в следующей сборке:
http://developer.android.com/reference/android/webkit/CacheManager.html
В заключение я хотел бы услышать мысли тех, кто боролся с этими же проблемами при создании своих приложений OAuth.
- росшлер
1 ответ
Janrain выпустил библиотеку, которая предоставляет некоторый клей UI и систему входа в систему через прокси-сервер; он поддерживает несколько популярных провайдеров идентификации OAuth (например, Google/FB). В конце потока входа вы получаете HTTPS POST от устройства, предоставляющего вам токен, который можно обменять на идентификатор пользователя и другую информацию, и канал для возврата токена доступа на устройство.
http://www.janrain.com/products/engage/mobile
https://github.com/janrain/engage.android
Раскрытие: я работаю в Janrain, в этой библиотеке.