Аутентификация с помощью OAuth2 для приложения * и * веб-сайта

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

Google заявляет, что "Вы можете использовать систему проверки подлинности Google как способ аутсорсинга аутентификации пользователей для своего приложения. Это может устранить необходимость создания, поддержки, и защитить имя пользователя и пароль." , что и я хочу сделать. Однако, когда я просматриваю все их примеры и еще много чего, я могу только найти материал о том, что веб-сайт или приложение аутентифицируют пользователя в отношении сервисов Google.

И действительно, когда я отправляюсь регистрировать свое приложение ( "клиент" ) с Google OAuth2, есть варианты для клиентов веб-сайта и "установленных" клиентов (т.е. для мобильного приложения), но не для обоих. Я могу создать двух отдельных клиентов, но я прочитал проект OAuth2, и я думаю, что будет проблема, о которой я сейчас расскажу.

Вот как я это сделал:

OAuth2 flow diagram

  • Пользователь запрашивает MyApp для доступа к своим личным данным.
  • Приложение использует класс Android AccountManager для запроса токена доступа для API Google.
  • Android говорит пользователю: "Приложение MyApp хочет получить доступ к вашей базовой информации в Google. Это нормально?"
  • Пользователь говорит "да".
  • AccountManager подключается к серверу Google OAuth2, используя учетные данные, хранящиеся на телефоне, и запрашивает токен доступа.
  • Возвращается токен доступа (который следует за зелеными линиями).
  • AccountManager возвращает токен доступа в MyApp.
  • MyApp отправляет запрос на MySite для личных данных пользователя, включая токен доступа.
  • MySite необходимо проверить пользователя, используя токен доступа. Он проверяет токен как описано здесь, с Google - "Google, этот токен действителен?".
  • Теперь я хочу, чтобы Google сказал: "Да, тот, кто дал это вам, действительно тот пользователь.", но то, что я думаю, действительно произойдет (на основе проекта OAuth2 и документации Google), заключается в том, что он будет скажем, "Нет, этот токен действителен только для MyApp, а вы MySite. GTFO!".

Итак, как мне это сделать? И ПОЖАЛУЙСТА не говорите "Использовать OpenID" или "Не использовать OAuth2" или другие подобные бесполезные ответы. О, и я действительно хотел бы использовать приятный пользовательский интерфейс AccountManager, а не crappy popup WebView s

Изменить

Предварительный ответ (я отчитаюсь, если это сработает!) от Николая - это то, что он действительно должен работать, а серверам Google будет все равно, откуда появился токен доступа. Кажется немного небезопасным для меня, но я увижу, если это сработает!

Update

Я реализовал этот шаблон с Facebook вместо Google, и он полностью работает. Сервер OAuth2 не заботится о том, откуда появился токен доступа. По крайней мере, Facebook этого не делает, поэтому я полагаю, что Google тоже не работает.

В свете этого очень плохой идеей хранить токены доступа! Но мы также не хотим, чтобы нажимать на серверы Facebook/Google, чтобы проверять аутентификацию для каждого запроса, так как это замедлит все. Вероятно, лучше всего добавить дополнительный cookie файл проверки подлинности для вашего сайта, который вы раздаете, когда их токен доступа проверен, но более простой способ - просто обработать токен доступа, как пароль, и сохранить его. Вам не нужно его солить, поскольку токены доступа действительно очень длинные. Таким образом, вышеприведенные шаги выглядят примерно так:

9. MySite необходимо проверить пользователя, используя токен доступа. Сначала он проверяет свой кеш с хэшированными действительными токенами доступа. Если хеш маркера найден там, он знает, что пользователь аутентифицирован. В противном случае он проверяет с помощью Google как описано здесь, с Google - "Google, этот токен действителен?".

10. Если Google говорит, что токен доступа неверен, мы указываем пользователю GTFO. В противном случае Google говорит "Да, это действительный пользователь", и мы затем проверяем нашу зарегистрированную базу данных пользователей. Если это имя пользователя Google (или идентификатор Facebook, если используется Facebook) не найдено, мы можем создать нового пользователя. Затем мы кэшируем хешированное значение токена доступа.

Ответ 1

Вам, вероятно, нужен OpenID Connect, который использует токены OAuth для аутентификации. Что касается AccountManager, текущая поддержка OAuth немного взломана, новый Google Play Services, который будет выпущен в ближайшее время, должен, надеюсь, сделать Это лучше. См. Здесь demo.

Ответ 2

Я только что отправил ответ в аналогичный вопрос StackOverflow.

Google вызывает это Гибридные приложения и объясняет, как "Android приложение получает автономный доступ для веб-back-end" .

Суть его в том, что вам нужно передать массированную строку scope в GoogleAuthUtil.getToken, чтобы заставить ее вернуть код авторизации (а не токен OAuth2). Этот код авторизации может быть передан из вашего мобильного приложения на ваш сервер и обменен на токен Token и токен обновления OAuth2, согласно этой схеме.

Параметр scope должен выглядеть примерно так:

oauth2:server:client_id:<your_server_client_it>:api_scope:<scope_url_1> <scope_url_2> ...

Ответ 3

Вы можете использовать маркер доступа, полученный мобильным приложением в другом месте. Drive SDK имеет приятное и простое введение, которое проходит через поток https://developers.google.com/drive/quickstart-android

Ответ 4

Как минимум с Google, токен доступа в конце концов истекает. Вот почему андроид AccountManager имеет метод invalidateAuthToken - срок действия кэшированного токена доступа истек, и вам нужно сообщить AccountManager, чтобы он оставил вам старую и вместо этого получил новую. Это делает несколько более безопасным кэширование токена, поскольку сам токен не дает вам вечного доступа в качестве этого пользователя. Вместо этого, когда он действителен, он просто говорит: "В какой-то момент в недавнем прошлом этот токен был приобретен доверенным источником".

Вот несколько вещей, которые я нашел полезными при работе с токенами. Первая - конечная точка Google tokeninfo. Сам токен - это только JSON с кодировкой base64. Это означает, что он не зашифрован, поэтому вы должны быть уверены, что используете HTTPS для связи. Однако это также означает, что вы можете проверить токен и лучше понять, что происходит.

https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=

Если ваш токен был "abcdef", вы должны перейти к:

https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=abcdef

и Google распакует вам токен. Это простой объект JSON, который включает поле "expires_in", в котором указывается количество секунд, для которых токен все еще действителен. В 6:03 в приведенном ниже видео вы можете увидеть распакованный токен:

https://developers.google.com/events/io/sessions/383266187

Это видео содержит подробный обзор OAuth2 и стоит посмотреть полностью, если вы собираетесь иметь дело с OAuth и токенами. Оратор также обсуждает другие формы токенов Oauth2, которые не являются токенами доступа, которые не истекают.

Другим полезным ресурсом является игровая площадка OAuth. Это позволяет делать основные вещи, такие как области запросов, составлять запросы и возвращать токены. Эта ссылка, похоже, работает спорадически, и в Chrome мне пришлось установить приложение Oauth Playground:

https://developers.google.com/oauthplayground/

И вот учебник Тима Брея, докладчика на видео, объясняющего, как использовать токены доступа для связи с сервером из приложения Android. Это было полезно для меня, потому что я начал понимать, как разные вещи в консоли API Google работают вместе:

http://android-developers.blogspot.in/2013/01/verifying-back-end-calls-from-android.html

Что касается фактического ответа на ваш вопрос, я бы сказал, что вам никогда не нужно кэшировать токен доступа на сервере. Как пояснялось в разделе "Проверка обратных вызовов от Android" выше, проверка токена почти всегда является быстрым статическим вызовом, что означает, что нет никаких причин для кэширования токенов:

Библиотеки могут кэшировать сертификаты Google и обновлять их только при необходимости, поэтому проверка (почти всегда) - быстрый статический вызов.

Наконец, вы можете использовать AccountManager для получения токенов доступа. Однако вместо этого Google вместо этого рекомендует использовать класс GoogleAuthUtil в библиотеке Служебных услуг:

Вкратце, в чем отличие от использования запроса OAuth2 getAuthToken и getToken

Здесь обратите внимание на комментарий Тима Брея, того же парня, который снова появился из вышеупомянутых ссылок, заявив, что они прилагают усилия к маршруту GoogleAuthUtil. Обратите внимание, однако, что это означает, что вы будете ограничены аутентификацией Google. Я считаю, что AccountManager можно использовать, чтобы получить, например, токен Facebook, а не в случае с GoogleAuthUtil.

Ответ 6

Когда нам нужно было что-то сделать на сервере OAuth без Google, мы сохранили токены в базе данных на веб-сайте. Затем приложение будет использовать веб-службы для запроса маркера, когда это необходимо для запроса данных.

Пользователь может выполнять регистрацию OAuth либо в Интернете, либо в приложении. Они поделились одним и тем же токеном приложения, чтобы они могли использовать один и тот же токен доступа. После регистрации мы будем хранить токены доступа и обновления в БД для использования с нужным им приложением.