API Google Oauth2: только один токен обновления для всех пользователей?

Я использую аутентификацию OAuth2, и у меня есть CMS с несколькими пользователями, каждый со своими профилями. Бывает, что у нашей компании есть учетная запись Google с доступом к нескольким учетным записям Google Analytics. Для каждого пользователя, использующего CMS, я подключаюсь к API Google Analytics с использованием другого имени пользователя, и каждый токен пользователя сохраняется в хранилище данных базы данных. Проблема в том, что если один пользователь отключает и отменяет свой токен, ни один из других пользователей, которые используют одну и ту же учетную запись Google, не сможет получить доступ к API Google Analytics, что не имеет смысла.

enter image description here

EDIT: после дальнейшего исследования я обнаружил, что когда первый пользователь аутентифицируется, токен, сохраненный в хранилище данных, содержит "refresh_roken", а также "access_token". Однако, когда другие пользователи аутентифицируются (они используют одну и ту же учетную запись google, но разные учетные записи Google Analytics), их токены будут содержать только "access_token". Если один из них аннулирует свой токен, все потеряют свои связи.

Как я могу остановить это и каждый пользователь получит свой собственный refresh_token?


ИЗМЕНИТЬ 2:

Я храню отдельные строки в хранилище данных, по одному для каждого пользователя. Позвольте мне пояснить, если вы посмотрите на эту диаграмму, представьте себе CMS, где одному пользователю CMS нужно будет видеть статистику из "Лиз Личной учетной записи" и другой пользователь CMS должен видеть статистику из "Liz Team Account".

Оба пользователя CMS принадлежат к одной компании, и оба они используют одну и ту же учетную запись google - "[email protected]" . Пользователь CMS A подключается к API Google Analytics с помощью "[email protected]" , получает refresh_token и хочет просмотреть статистику для "Liz Website". Затем пользователь CMS B подключается к API Google Analytics также с помощью "[email protected]" , но теперь он больше не получает refresh_token, только access_token - это проблема, потому что пользователю будет предложено снова подключиться после доступа_token истекает.

То, что я обычно делал, когда один пользователь отключился, заключался в том, чтобы удалить токен из хранилища данных и отменить токен, но, возможно, я не должен его отзывать, должен ли я? В любом случае, если в моем сценарии пользователь A отключается, это удаляет его токен хранилища данных, а это значит, что мы больше не будем иметь refresh_token, поскольку у пользователя B его не было в первую очередь.

Диаграмма учетных записей пользователей: User accounts diagram

Ответ 1

Я думаю, вам нужно проверить databaseDatastore. Если все сделано правильно, хранилище данных базы данных должно хранить refreshTokens для каждого из ваших пользователей, идентифицированных userName в вашем коде.

Когда новый пользователь аутентифицируется, вы должны вставлять в него новую строку в базе данных.

 // New User we insert it into the database
 string insertString = "INSERT INTO [dbo].[GoogleUser]  ([username],[RefreshToken],[Userid]) " +
                                              " VALUES (@key,@value,'1' )";

Затем, когда вы хотите получить к нему доступ снова, вы должны снова выбрать его по имени пользователя

using (SqlCommand command = new SqlCommand("select RefreshToken from GoogleUser where UserName = @username;", myConnection))

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

 // Deletes the users data.                        
 string deleteString = "delete [dbo].[GoogleUser] from " +                                 
                                  " where username = @key";

Не видя, как вы реализовали databasedatastore, я не могу больше помочь, но это моя версия databasedatastore.cs

Update:

Если вы используете только одну учетную запись Google Analytics, вы должны использовать учетную запись службы.

Обновить в ответ на ваше обновление

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

Шаг первый:

Пользователь [email protected] регистрирует ваше приложение в аутентифицированном приложении, строка должна быть вставлена ​​в ваше имя пользователя [email protected] с обновлением. ваш databasedatastore должен обработать его сохранение.

когда истекает срок действия маркера доступа, предполагая, что вы создали базу данных правильно, он будет использовать refreshtoken для автоматического получения нового токена доступа для имени пользователя [email protected]

Шаг 2:

Некоторые другие пользователи регистрируются в [email protected], хранилище данных базы данных проверяет базу данных для имени пользователя [email protected] и получает токен обновления, связанный с [email protected], и запрашивает новый токен доступа.

Вы не должны удалять токены обновления или пользователей из базы данных, если по какой-то причине это не сработает. Это может не сработать, если пользователь перешел на учетную запись Google и отозвал ваш доступ. Должно быть только одно имя пользователя [email protected] и обновить токен, связанный с ним.

Сервисная учетная запись:

Учетная запись службы - это тип аутентификации, для которой не требуется аутентификация пользователя. Он работает, создавая аутентификацию учетной записи службы в консоли разработчика, а затем отправляя адрес электронной почты и добавляя ее в админку Google Analytics, как и любой другой пользователь. Теперь учетная запись службы имеет доступ к учетной записи Google Analytics напрямую, как пользователь.

Затем ваши данные запроса приложения из API, не запрашивая у пользователя доступа. Вы можете показать Лиз, Джим и подавать в суд на все данные, прося их аутентифицироваться.

Ответ 2

Вы описываете ожидаемое поведение. Если вы просто имеете в виду, что пользователь отключается (не отменяет разрешения приложения), попробуйте установить access_type в "автономный".

Нет разницы между "аккаунтом Google Analytics" и "учетной записью Google". Вы аутентифицируете аналитику api как учетную запись Google.

Дополнительные примечания:

они используют одну и ту же учетную запись google, но разные учетные записи Google Analytics

Google Analytics использует учетные записи Google для входа в систему. Возможно, вы имеете в виду разные профили?

Если один пользователь отключает и отменяет свой токен, ни один из других пользователей, которые используют тот же аккаунт Google, не сможет получить доступ к API Google Analytics, что не имеет смысла

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

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

Ответ 3

Я думаю, вам нужно снова обновить UpdateToken в таблице, не зависящей от пользователя. Вы можете снова обновить токен, используя:

$client->setAccessType('offline');
$client->setApprovalPrompt('force');

Теперь используйте токен обновления для аутентификации пользователя и каждый раз получать новый тип доступа, чтобы иметь токен, зависящий от пользователя, и хранить его в сеансе или db. И каждый раз, когда вы перекрестно проверяете, истек ли он или нет, и если он истек, то снова получите токен доступа, используя токен обновления.

  $client->refreshToken('stored refresh token');

Надеюсь, это будет полезно. Обратите внимание, что это синтаксис PHP script, поэтому для использования вашего языка программирования https://developers.google.com/api-client-library/

Ответ 4

Вы можете попросить Google добавить дополнительную информацию об учетной записи в область действия, чтобы устранить эту проблему. Я рекомендую добавить profile, так как он не требует никаких дополнительных запросов для пользователя и предоставляет уникальный идентификатор для учетной записи Google (а не для учетной записи Google Analytics). Используя драгоценный камень OAuth2 Ruby, ваш последний запрос может выглядеть примерно так:

client = OAuth2::Client.new(
  ENV["GOOGLE_CLIENT_ID"],
  ENV["GOOGLE_CLIENT_SECRET"],
  authorize_url: "https://accounts.google.com/o/oauth2/auth",
  token_url: "https://accounts.google.com/o/oauth2/token"
)

# Configure authorization url
client.authorize_url(
  scope: "https://www.googleapis.com/auth/analytics.readonly profile",
  redirect_uri: callback_url,
  access_type: "offline",
  prompt: "select_account"
)

Обратите внимание, что область имеет две записи, разделенные пробелами, одну для доступа только для чтения к Google Analytics, а другая - только profile, которая является стандартом OpenID Connect.

Это приведет к тому, что Google предоставит дополнительный атрибут id_token в ответе get_token. Стоит отметить, что если вы измените область действия, вы снова получите токен обновления для пользователей, которые уже прошли аутентификацию с исходной областью. Это полезно, если, скажем, у вас уже есть куча пользователей, и вы не хотите, чтобы все они были отключены от приложения в Google.;)

Чтобы получить информацию из id_token, проверить эту страницу в документах Google. В конечном итоге вы захотите использовать параметр sub, предоставленный с этой уникальной учетной записи.

О, и последнее замечание: вам не нужен prompt=select_account, но он полезен для таких ситуаций, когда ваши пользователи могут пройти аутентификацию с несколькими учетными записями Google (т.е. вы не используете это для вход/аутентификация).