Как обрабатывать детальные разрешения

Обзор

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

Что такое детальное разрешение?

Представьте, что вы разрабатываете продуктивное приложение, которое запрашивает области как электронной почты, так и календаря. Ваши пользователи могут захотеть использовать ваше приложение только для Календаря Google, но не для Gmail. Благодаря детальным разрешениям OAuth пользователи могут предоставить разрешение только Календарю Google, но не Gmail. Позволяя пользователям предоставлять доступ к определенным данным, это сводит к минимуму раскрытие данных, укрепляет доверие и дает пользователям возможность контролировать свою цифровую жизнь с учетом конфиденциальности. Важно разработать приложение для обработки таких сценариев.

Когда запрашивается более одной области без входа в систему

Области входа и отсутствия входа

Для приложений, которые запрашивают как области входа, так и области без входа, пользователи сначала видят страницу согласия для областей входа ( email , profile и openid ). После того как пользователи согласятся поделиться своей основной идентификационной информацией (имя, адрес электронной почты и фотография профиля), они увидят экран детального согласия для областей без входа в систему. В этом случае приложение должно проверить, какие области предоставлены пользователями, и не может предполагать, что пользователи предоставляют все запрошенные области. В следующем примере веб-приложение запрашивает все три области входа и область без входа на Диск Google. После того как пользователи дадут согласие на области входа, они увидят экран детального согласия для разрешения Google Диска:

Области входа и отсутствия входа

Более одной области без входа в систему

Экран детального согласия на разрешения будет отображаться пользователям, когда приложения запрашивают более одной области без входа в систему. Пользователи могут выбрать, какие разрешения они хотят одобрить для совместного использования с приложением. Ниже приведен пример экрана согласия с детальными разрешениями, запрашивающего доступ к сообщениям Gmail пользователя и данным Календаря Google:

Более одной области без входа в систему

Для приложений, которые запрашивают только области входа ( email , profile и openid ), экран согласия разрешений #inspect-your-application-codegranular не применим. Пользователи либо одобряют, либо отклоняют весь запрос на вход. Другими словами, если приложения запрашивают только области входа (одну, две или все три), экран согласия с детальными разрешениями неприменим.

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

Количество областей входа Количество областей без входа в систему Экран согласия с детальными разрешениями
1-3 0 Непригодный
1-3 1+ Применимый
0 1 Непригодный
0 2+ Применимый

Определите, затронуты ли ваши приложения

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

Как определить, использует ли ваше приложение несколько областей

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

Проверьте код вашего приложения

Просмотрите разделы кода вашего приложения, в которых вы выполняете вызовы к конечным точкам авторизации Google OAuth, чтобы запросить разрешение у пользователей. Если вы используете одну из клиентских библиотек Google API, вы часто можете узнать, какие области охватывают запросы вашего приложения, на этапах инициализации клиента. Некоторые примеры показаны в следующем разделе. Вам следует обратиться к документации SDK, которые ваше приложение использует для обработки Google OAuth 2.0, чтобы определить, затронуто ли ваше приложение, используя в качестве справки рекомендации, показанные в следующих примерах.

Службы идентификации Google

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

const client = google.accounts.oauth2.initTokenClient({
  client_id: 'YOUR_CLIENT_ID',
  scope: 'https://www.googleapis.com/auth/calendar.readonly \
  https://www.googleapis.com/auth/contacts.readonly',
  callback: (response) => {
    ...
  },
});

Питон

В следующем фрагменте кода используется модуль google-auth-oauthlib.flow для создания запроса авторизации; Параметр scope включает две области без входа в систему. Экран детального согласия на разрешения будет отображаться, когда веб-приложение запрашивает авторизацию у пользователей.

import google.oauth2.credentials
import google_auth_oauthlib.flow

# Use the client_secret.json file to identify the application requesting
# authorization. The client ID (from that file) and access scopes are required.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
    'client_secret.json',
    scopes=['https://www.googleapis.com/auth/calendar.readonly',
                    'https://www.googleapis.com/auth/contacts.readonly'])

Node.js

Следующий фрагмент кода создает объект google.auth.OAuth2 , который определяет параметры в запросе авторизации, параметр scope которого включает две области, не относящиеся к входу. Экран детального согласия на разрешения будет отображаться, когда веб-приложение запрашивает авторизацию у пользователей.

const {google} = require('googleapis');

/**
  * To use OAuth2 authentication, we need access to a CLIENT_ID, CLIENT_SECRET, AND REDIRECT_URI
  * from the client_secret.json file. To get these credentials for your application, visit
  * https://console.cloud.google.com/apis/credentials.
  */
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for read-only Calendar and Contacts.
const scopes = [
  'https://www.googleapis.com/auth/calendar.readonly',
  'https://www.googleapis.com/auth/contacts.readonly']
];

// Generate a url that asks permissions
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  /** Pass in the scopes array defined above.
    * Alternatively, if only one scope is needed, you can pass a scope URL as a string */
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true
});

Проверка исходящего сетевого вызова

Метод проверки сетевых вызовов будет зависеть от типа клиента вашего приложения.

При проверке сетевых вызовов найдите запросы, отправленные на конечные точки авторизации Google OAuth, и проверьте параметр scope .

Эти значения приводят к отображению экрана согласия с детальными разрешениями.

  • Параметр scope содержит области входа и области без входа.

    Следующий пример запроса содержит все три области входа и одну область без входа для просмотра метаданных файлов Google Диска пользователя:

    https://accounts.google.com/o/oauth2/v2/auth?
    access_type=offline&
    scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile%20openid%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly&
    include_granted_scopes=true&
    response_type=code&
    redirect_uri=YOUR_REDIRECT_URL&
    client_id=YOUR_CLIENT_ID
  • Параметр scope содержит более одной области без входа.

    Следующий пример запроса содержит две области без входа в систему для просмотра метаданных Google Диска пользователя и управления определенными файлами Google Диска:

  • https://accounts.google.com/o/oauth2/v2/auth?
    access_type=offline&
    scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&
    include_granted_scopes=true&
    response_type=code&
    redirect_uri=YOUR_REDIRECT_URL&
    client_id=YOUR_CLIENT_ID

Лучшие практики для обработки детальных разрешений

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

  1. Ознакомьтесь с Службами API Google: Политика в отношении пользовательских данных и убедитесь, что вы их соблюдаете.
  2. Запросите конкретные области, необходимые для задачи. Вы должны соблюдать политику Google OAuth 2.0, согласно которой вы запрашиваете только те области, которые вам необходимы . Вам следует избегать запроса нескольких областей при входе в систему, если только это не необходимо для основных функций вашего приложения. Объединение нескольких областей вместе, особенно для начинающих пользователей, незнакомых с функциями вашего приложения, может затруднить понимание необходимости этих разрешений. Это может вызвать тревогу и удержать пользователей от дальнейшего взаимодействия с вашим приложением.
  3. Прежде чем запрашивать авторизацию, предоставьте пользователям обоснование. Четко объясните, почему вашему приложению требуется запрошенное разрешение, что вы будете делать с данными пользователя и какую выгоду пользователь получит от одобрения запроса. Наше исследование показывает, что эти объяснения повышают доверие и вовлеченность пользователей.
  4. Используйте добавочную авторизацию всякий раз, когда ваше приложение запрашивает области, чтобы избежать необходимости управлять несколькими токенами доступа.
  5. Проверьте , какие области действия предоставлены пользователями. При одновременном запросе нескольких областей пользователи могут не предоставить все области, запрошенные вашим приложением. Ваше приложение должно всегда проверять, какие области были предоставлены пользователем, и обрабатывать любой отказ в областях, отключив соответствующие функции. Следуйте политикам Google OAuth 2.0 по обработке согласия для нескольких областей и запрашивайте согласие у пользователя повторно только в том случае, если он четко указал на намерение использовать конкретную функцию, для которой требуется данная область.

Обновите свое приложение для обработки детальных разрешений.

Android-приложения

Вам следует обратиться к документации SDK, которые вы используете для взаимодействия с Google OAuth 2.0, и обновить свое приложение для обработки детальных разрешений на основе лучших практик .

Если вы используете auth.api.signin SDK из Play Services для взаимодействия с Google OAuth 2.0, вы можете использовать функцию requestPermissions для запроса наименьшего набора необходимых областей и функцию hasPermissions для проверки того, какие области пользователь предоставил при запросе детальных разрешений.

Расширения Chrome

Вам следует использовать Chrome Identity API для работы с Google OAuth 2.0 на основе лучших практик .

В следующем примере показано, как правильно обрабатывать детальные разрешения.

манифест.json

В примере файла манифеста объявляются две области без входа в систему для приложения расширения Chrome.

{
  "name": "Example Chrome extension application",
  ...
  "permissions": [
      "identity"
    ],
  "oauth2" : {
      "client_id": "YOUR_CLIENT_ID",
      "scopes":["https://www.googleapis.com/auth/calendar.readonly",
                "https://www.googleapis.com/auth/contacts.readonly"]
  }
}

Неправильный подход

Все или ничего

Пользователи нажимают кнопку, чтобы начать процесс авторизации. В этом фрагменте кода предполагается, что пользователям предоставляется экран согласия «все или ничего» для двух областей, указанных в файле manifest.json . Он не проверяет, какие области действия предоставлены пользователями.

oauth.js

...
document.querySelector('button').addEventListener('click', function () {
  chrome.identity.getAuthToken({ interactive: true },
      function (token) {
          if (token === undefined) {
            // User didn't authorize both scopes.
            // Updating the UX and application accordingly
            ...
          } else {
            // User authorized both or one of the scopes.
            // It neglects to check which scopes users granted and assumes users granted all scopes.

            // Calling the APIs, etc.
            ...
          }
      });
});

Правильный подход

Наименьшие объемы

Выберите наименьший набор необходимых областей

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

В этом примере предполагается, что обе области, объявленные в файле manifest.json , представляют собой наименьший набор необходимых областей. Файл oauth.js использует API Chrome Identity для инициации процесса авторизации в Google. Вам следует включить детализированные разрешения , чтобы пользователи имели больший контроль над предоставлением разрешений вашему приложению. Ваше приложение должно правильно обрабатывать ответы пользователей, проверяя, какие области авторизуются пользователями.

oauth.js

...
document.querySelector('button').addEventListener('click', function () {
  chrome.identity.getAuthToken({ interactive: true, enableGranularPermissions: true },
      function (token, grantedScopes) {
          if (token === undefined) {
            // User didn't authorize any scope.
            // Updating the UX and application accordingly
            ...
          } else {
            // User authorized the request. Now, check which scopes were granted.
            if (grantedScopes.includes('https://www.googleapis.com/auth/calendar.readonly'))
            {
              // User authorized Calendar read permission.
              // Calling the APIs, etc.
              ...
            }
            else
            {
              // User didn't authorize Calendar read permission.
              // Update UX and application accordingly
              ...
            }

            if (grantedScopes.includes('https://www.googleapis.com/auth/contacts.readonly'))
            {
              // User authorized Contacts read permission.
              // Calling the APIs, etc.
              ...
            }
            else
            {
              // User didn't authorize Contacts read permission.
              // Update UX and application accordingly
              ...
            }
          }
      });
});

Приложения для iOS, iPadOS и macOS

Вам следует ознакомиться с документацией SDK, которые вы используете для взаимодействия с Google OAuth 2.0, и обновить свое приложение для обработки детальных разрешений на основе лучших практик .

Если вы используете библиотеку Google Sign-In для iOS и macOS для взаимодействия с Google OAuth 2.0, вам следует просмотреть документацию по обработке детальных разрешений.

Веб-приложения

Вам следует обратиться к документации SDK, которые вы используете для взаимодействия с Google OAuth 2.0, и обновить свое приложение для обработки детальных разрешений на основе лучших практик .

Доступ на стороне сервера (офлайн)

Серверный (автономный) режим доступа требует выполнения следующих действий:
  • Поднимите сервер и определите общедоступную конечную точку для получения кода авторизации.
  • Настройте URI перенаправления вашей общедоступной конечной точки в Credentials page консоли Google Cloud.

В следующем фрагменте кода показан пример NodeJS, запрашивающий две области без входа в систему. Пользователи увидят экран согласия с детальным разрешением.

Неправильный подход

Все или ничего

Пользователи перенаправляются на URL-адрес авторизации. В этом фрагменте кода предполагается, что пользователям предоставляется экран согласия «все или ничего» для двух областей, указанных в массиве scopes . Он не проверяет, какие области действия предоставлены пользователями.

main.js

...
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for two non-Sign-In scopes - Google Calendar and Contacts
const scopes = [
  'https://www.googleapis.com/auth/contacts.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Generate a url that asks permissions for the Google Calendar and Contacts scopes
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  // Pass in the scopes array defined above
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true
});

async function main() {
  const server = http.createServer(async function (req, res) {
    // Example on redirecting user to Google OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }
    // Receive the callback from Google OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the Google OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) {
        // User didn't authorize both scopes.
        // Updating the UX and application accordingly
        ...
      } else {
        // User authorized both or one of the scopes.
        // It neglects to check which scopes users granted and assumes users granted all scopes.

        // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        // Calling the APIs, etc.
        ...
      }
    }
    res.end();
  }).listen(80);
}
Правильный подход

Наименьший объем

Выберите наименьший набор необходимых областей

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

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

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

main.js

...
const oauth2Client = new google.auth.OAuth2(
  YOUR_CLIENT_ID,
  YOUR_CLIENT_SECRET,
  YOUR_REDIRECT_URL
);

// Access scopes for two non-Sign-In scopes - Google Calendar and Contacts
const scopes = [
  'https://www.googleapis.com/auth/contacts.readonly',
  'https://www.googleapis.com/auth/calendar.readonly'
];

// Generate a url that asks permissions for the Google Calendar and Contacts scopes
const authorizationUrl = oauth2Client.generateAuthUrl({
  // 'online' (default) or 'offline' (gets refresh_token)
  access_type: 'offline',
  // Pass in the scopes array defined above
  scope: scopes,
  // Enable incremental authorization. Recommended as best practices.
  include_granted_scopes: true,
  // Set to true to enable more granular permissions for Google OAuth 2.0 client IDs created before 2019.
  // No effect for newer Google OAuth 2.0 client IDs, since more granular permissions is always enabled for them.
  enable_granular_consent: true
});

async function main() {
  const server = http.createServer(async function (req, res) {
    // Redirect users to Google OAuth 2.0 server.
    if (req.url == '/') {
      res.writeHead(301, { "Location": authorizationUrl });
    }
    // Receive the callback from Google OAuth 2.0 server.
    if (req.url.startsWith('/oauth2callback')) {
      // Handle the Google OAuth 2.0 server response
      let q = url.parse(req.url, true).query;

      if (q.error) {
        // User didn't authorize both scopes.
        // Updating the UX and application accordingly
        ...
      } else {
        // Get access and refresh tokens (if access_type is offline)
        let { tokens } = await oauth2Client.getToken(q.code);
        oauth2Client.setCredentials(tokens);

        // User authorized the request. Now, check which scopes were granted.
        if (tokens.scope.includes('https://www.googleapis.com/auth/calendar.readonly'))
        {
          // User authorized Calendar read permission.
          // Calling the APIs, etc.
          ...
        }
        else
        {
          // User didn't authorize Calendar read permission.
          // Calling the APIs, etc.
          ...
        }

        // Check which scopes user granted the permission to application
        if (tokens.scope.includes('https://www.googleapis.com/auth/contacts.readonly'))
        {
          // User authorized Contacts read permission.
          // Calling the APIs, etc.
          ...
        }
        else
        {
          // User didn't authorize Contacts read permission.
          // Update UX and application accordingly
          ...
        }
      }
    }
    res.end();
  }).listen(80);
}

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

Доступ только на стороне клиента

  • Для приложений, которые используют библиотеку JavaScript Google Identity Services для взаимодействия с Google OAuth 2.0, вам следует ознакомиться с этой документацией по обработке детальных разрешений.
  • Для приложений, которые напрямую выполняют вызовы с помощью JavaScript к конечным точкам авторизации Google OAuth 2.0, вам следует ознакомиться с этой документацией по обработке детальных разрешений.

Проверьте обновленное приложение на обработку детальных разрешений.

  1. Опишите все случаи, когда пользователи могут отвечать на запросы разрешений, и ожидаемое поведение вашего приложения. Например, если пользователь авторизует только две из трех запрошенных областей, ваше приложение должно вести себя соответствующим образом.
  2. Протестируйте свое приложение с включенным детальным разрешением. Есть два способа включить детальные разрешения:
    1. Проверьте экраны согласия OAuth 2.0 вашего приложения, чтобы узнать, включены ли уже для вашего приложения подробные разрешения . Вы также можете создать новый идентификатор клиента Google OAuth 2.0 для Интернета, Android или iOS через консоль Google Cloud в целях тестирования, поскольку для них всегда включено детальное разрешение.
    2. Установите для параметра enable_granular_consent значение true при вызове конечных точек авторизации Google OAuth. Некоторые SDK имеют явную поддержку этого параметра. Для других ознакомьтесь с документацией, чтобы узнать, как добавить этот параметр и его значение вручную. Если ваша реализация не поддерживает добавление этого параметра, вы можете создать новый идентификатор клиента Google OAuth 2.0 для Интернета, Android или iOS через консоль Google Cloud только в целях тестирования, как указано в предыдущем пункте.