OAuth 2.0 для клиентских веб-приложений

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

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

В этом потоке ваше приложение открывает URL-адрес Google, который использует параметры запроса для идентификации вашего приложения и типа доступа к API, который требуется приложению. Вы можете открыть URL-адрес в текущем окне браузера или во всплывающем окне. Пользователь может пройти аутентификацию в Google и предоставить запрошенные разрешения. Затем Google перенаправляет пользователя обратно в ваше приложение. Перенаправление включает токен доступа, который ваше приложение проверяет и затем использует для выполнения запросов API.

Предпосылки

Включите API для вашего проекта

Любое приложение , которое требует Google API , необходимо включить эти интерфейсы в API Console.

Чтобы включить API для вашего проекта:

  1. Open the API Library в Google API Console.
  2. If prompted, select a project, or create a new one.
  3. API Library перечислены все доступные API, сгруппированных по семейству продуктов и популярности. Если API вы хотите включить не отображается в списке, воспользуйтесь поиском , чтобы найти его, или нажмите Просмотреть все в семействе продуктов он принадлежит.
  4. Выберите API , который вы хотите включить, а затем нажмите кнопку Включить.
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

Создать учетные данные для авторизации

Любое приложение, использующее OAuth 2.0 для доступа к API Google, должно иметь учетные данные авторизации, которые идентифицируют приложение на сервере OAuth 2.0 Google. Следующие шаги объясняют, как создать учетные данные для вашего проекта. Затем ваши приложения могут использовать учетные данные для доступа к API-интерфейсам, которые вы включили для этого проекта.

  1. Go to the Credentials page.
  2. Нажмите кнопку Создать учетные данные> OAuth идентификатор клиента.
  3. Выберите тип приложения веб - приложение.
  4. Заполните форму. Приложения , которые используют JavaScript , чтобы сделать уполномочил Google запросы API необходимо указать разрешенные происхождение JavaScript. Источники определяют домены, из которых ваше приложение может отправлять запросы на сервер OAuth 2.0. Эти причины должны придерживаться правил проверки компании Google .

Определите области доступа

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

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

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

Получение токенов доступа OAuth 2.0

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

Шаг 1. Настройте клиентский объект

Если вы используете клиентскую библиотеку Google APIs для JavaScript , чтобы справиться с потоком OAuth 2.0, ваш первый шаг заключается в настройке gapi.auth2 и gapi.client объектов. Эти объекты позволяют вашему приложению получать авторизацию пользователя и делать авторизованные запросы API.

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

Клиентская библиотека JS

Клиентская библиотека JavaScript упрощает многие аспекты процесса авторизации:

  1. Он создает URL-адрес перенаправления для сервера авторизации Google и предоставляет метод для перенаправления пользователя на этот URL-адрес.
  2. Он обрабатывает перенаправление с этого сервера обратно в ваше приложение.
  3. Он проверяет токен доступа, возвращенный сервером авторизации.
  4. Он хранит токен доступа, который сервер авторизации отправляет вашему приложению, и извлекает его, когда ваше приложение впоследствии выполняет авторизованные вызовы API.

Фрагмент кода ниже выдержка из полного примера , показанного ниже в этом документе. Этот код инициализирует gapi.client объект, который ваше приложение позже использовать будет делать вызовы API. Когда этот объект создан, gapi.auth2 объект, который приложение использует для проверки и мониторинга состояния авторизации пользователя, также инициализируется.

Вызов gapi.client.init определяет следующие поля:

  • В apiKey и clientId значения определяют учетные данные для авторизации вашего приложения. Как обсуждалось в мандатную авторизации , API Consoleсоздавая секции, эти значения могут быть получены в API Console. Обратите внимание , что clientId требуется , если приложение делает авторизационных запросов API. Приложения, которые делают только неавторизованные запросы, могут просто указать ключ API.
  • scope поле определяет пространство запятых списка доступа прицелы , которые соответствуют ресурсам , которые ваше приложение может получить доступ от имени пользователя. Эти значения информируют экран согласия, который Google отображает пользователю.

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

  • В discoveryDocs поле идентифицирует список API Discovery документов , что ваши использования приложений. Документ Discovery описывает поверхность API, включая его схемы ресурсов, и клиентская библиотека JavaScript использует эту информацию для создания методов, которые могут использовать приложения. В этом примере код извлекает документ обнаружения для версии 3 API Google Диска.

После gapi.client.init Завершает вызов, код устанавливает GoogleAuth переменного для идентификации объекта Google Auth. Наконец, код устанавливает прослушиватель, который вызывает функцию при изменении статуса входа пользователя. (Эта функция не определена во фрагменте.)

var GoogleAuth; // Google Auth object.
function initClient() {
  gapi.client.init({
      'apiKey': 'YOUR_API_KEY',
      'clientId': 'YOUR_CLIENT_ID',
      'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
      'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest']
  }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);
  });
}

Конечные точки OAuth 2.0

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

Шаг 2. Перенаправление на сервер Google OAuth 2.0

Чтобы запросить разрешение на доступ к данным пользователя, перенаправьте пользователя на сервер Google OAuth 2.0.

Клиентская библиотека JS

Вызов GoogleAuth.signIn() метод , чтобы направить пользователя на сервер авторизации Google.

GoogleAuth.signIn();

На практике, ваше приложение может установить логическое значение , чтобы определить , следует ли называть signIn() метод , прежде чем пытаться сделать вызов API.

Приведенный ниже фрагмент кода демонстрирует, как инициировать процесс авторизации пользователя. Обратите внимание на следующие моменты о фрагменте:

  • GoogleAuth объект , указанный в коде такое же , как глобальной переменной , определенной в фрагменте кода в шаге 1 .

  • updateSigninStatus функция слушатель , который слушает изменения статуса авторизации пользователя. Его роль в качестве слушателя был также определен в фрагменте кода на этапе 1:
    GoogleAuth.isSignedIn.listen(updateSigninStatus);
  • Фрагмент определяет две дополнительные глобальные переменные:

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

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

    • currentApiRequest это объект , который хранит сведения о запросе последнего API , что пользователь пытался. Значение объекта устанавливается , когда приложение вызывает sendAuthorizedApiRequest функции.

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

var isAuthorized;
var currentApiRequest;

/**
 * Store the request details. Then check to determine whether the user
 * has authorized the application.
 *   - If the user has granted access, make the API request.
 *   - If the user has not granted access, initiate the sign-in flow.
 */
function sendAuthorizedApiRequest(requestDetails) {
  currentApiRequest = requestDetails;
  if (isAuthorized) {
    // Make API request
    // gapi.client.request(requestDetails)

    // Reset currentApiRequest variable.
    currentApiRequest = {};
  } else {
    GoogleAuth.signIn();
  }
}

/**
 * Listener called when user completes auth flow. If the currentApiRequest
 * variable is set, then the user was prompted to authorize the application
 * before the request executed. In that case, proceed with that API request.
 */
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    isAuthorized = true;
    if (currentApiRequest) {
      sendAuthorizedApiRequest(currentApiRequest);
    }
  } else {
    isAuthorized = false;
  }
}

Конечные точки OAuth 2.0

Сформировать URL для доступа на запрос от OAuth 2.0 конечной точки Google, в https://accounts.google.com/o/oauth2/v2/auth . Эта конечная точка доступна по HTTPS; обычные HTTP-соединения отклоняются.

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

Параметры
client_id Необходимый

Идентификатор клиента для вашего приложения. Вы можете найти это значение в API ConsoleCredentials page.

redirect_uri Необходимый

Определяет, куда сервер API перенаправляет пользователя после того, как пользователь завершит поток авторизации. Значение должно точно соответствовать один из авторизованной URI переадресации для клиента OAuth 2.0, который был настроен на свой клиент API ConsoleCredentials page. Если это значение не совпадает с авторизованным перенаправлением URI для предоставленного client_id вы получите redirect_uri_mismatch ошибку.

Обратите внимание , что http или https схема, случай, и Слэш ( « / ») должны совпадать.

response_type Необходимый

Приложений JavaScript необходимо установить значение параметра в token . Это значение указывает сервер авторизации Google , чтобы вернуть маркер доступа как name=value пары в идентификатор фрагмента URI ( # ) , к которому пользователь перенаправляется после завершения процесса авторизации.

scope Необходимый

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

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

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

state рекомендуемые

Задает любое строковое значение, которое ваше приложение использует для поддержания состояния между вашим запросом авторизации и ответом сервера авторизации. Сервер возвращает точное значение , которое вы отправляете как name=value пары в идентификатор фрагмента URL ( # ) в redirect_uri после согласия пользователя или отклоняет запрос доступа приложения.

Вы можете использовать этот параметр для нескольких целей, таких как направление пользователя к нужному ресурсу в вашем приложении, отправка одноразовых номеров и предотвращение подделки межсайтовых запросов. Так как ваш redirect_uri можно догадаться, используя state ценность может увеличить уверенность в том, что входящее соединение является результатом запроса аутентификации. Если вы генерируете случайную строку или кодируете хэш файла cookie или другое значение, которое фиксирует состояние клиента, вы можете проверить ответ, чтобы дополнительно убедиться, что запрос и ответ исходят в том же браузере, обеспечивая защиту от таких атак, как межсайтовые атаки. запросить подлог. Смотрите OpenID Connect документацию для примера того , как создать и подтвердить state маркеров.

include_granted_scopes По желанию

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

login_hint По желанию

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

Установите значение параметра на адрес электронной почты или sub идентификатор, который эквивалентен пользователь Google ID.

prompt По желанию

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

Возможные значения:

none Не отображать экраны аутентификации или согласия. Нельзя указывать с другими значениями.
consent Запрашивать у пользователя согласие.
select_account Предложить пользователю выбрать учетную запись.

Пример перенаправления на сервер авторизации Google

Пример URL-адреса показан ниже с разрывами строк и пробелами для удобства чтения.

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

После создания URL-адреса запроса перенаправьте на него пользователя.

Пример кода JavaScript

В следующем фрагменте кода JavaScript показано, как инициировать процесс авторизации в JavaScript без использования клиентской библиотеки API Google для JavaScript. Поскольку эта конечная точка OAuth 2.0 не поддерживает совместное использование ресурсов между источниками (CORS), фрагмент кода создает форму, которая открывает запрос к этой конечной точке.

/*
 * Create form to request access token from Google's OAuth 2.0 server.
 */
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

  // Create <form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);

  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client_id': 'YOUR_CLIENT_ID',
                'redirect_uri': 'YOUR_REDIRECT_URI',
                'response_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include_granted_scopes': 'true',
                'state': 'pass-through value'};

  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

Шаг 3. Google запрашивает у пользователя согласие

На этом этапе пользователь решает, предоставить ли вашему приложению запрошенный доступ. На этом этапе Google отображает окно согласия, в котором отображается имя вашего приложения и служб Google API, к которым он запрашивает разрешение на доступ, с учетными данными для авторизации пользователя, а также краткую информацию об объемах предоставляемого доступа. Затем пользователь может дать согласие на предоставление доступа к одной или нескольким областям, запрошенным вашим приложением, или отклонить запрос.

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

Ошибки

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

admin_policy_enforced

Аккаунт Google не может авторизовать одну или несколько запрошенных областей из-за политики администратора Google Workspace. Смотрите в справочной статью Google Workspace Администратор управления , который третья сторона и внутренние приложения доступ к данным Google Workspace для получения дополнительной информации о том , как администратор может ограничить доступ ко всем областям или чувствительным и ограниченных областям , пока доступ явно не предоставляются ваш OAuth идентификатора клиента.

disallowed_useragent

Конечная точка авторизации отображаются внутри встроенного агента пользователя запрещенного Google в политике OAuth 2.0 .

Android

Android разработчики могут столкнуться сообщение об ошибке при открытии запросов на авторизацию вandroid.webkit.WebView . Разработчики должны использовать вместо Android библиотеки , такие как Google Sign-In для Android или OpenID Фонда AppAuth для Android .

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

iOS

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

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

org_internal

OAuth идентификатор клиента в запросе , является частью проекта , ограничивающего доступ к счетам Google в конкретной Google Cloud организации . Для получения дополнительной информации об этой опции конфигурации см Типа пользователя раздел в настройке вашего OAuth согласие экрана справочной статьи.

origin_mismatch

Схема, домен и / или порт JavaScript, являющегося источником запроса авторизации, могут не соответствовать авторизованному URI источника JavaScript, зарегистрированному для идентификатора клиента OAuth. Обзор уполномочил происхождение JavaScript в Google API ConsoleCredentials page.

redirect_uri_mismatch

redirect_uri передается в запросе авторизации не совпадает с авторизованным редирект URI для OAuth идентификатора клиента. Обзор уполномочил переадресацию URIs в Google API Console Credentials page.

Схема, домен и / или порт JavaScript, являющегося источником запроса авторизации, могут не соответствовать авторизованному URI источника JavaScript, зарегистрированному для идентификатора клиента OAuth. Обзор уполномочил происхождение JavaScript в Google API Console Credentials page.

Шаг 4. Обработайте ответ сервера OAuth 2.0

Клиентская библиотека JS

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

Конечные точки OAuth 2.0

Сервер OAuth 2.0 отправляет ответ на redirect_uri , указанный в вашей маркер доступа запроса.

Если пользователь одобряет запрос, ответ содержит токен доступа. Если пользователь не одобряет запрос, ответ содержит сообщение об ошибке. Маркер доступа или сообщение об ошибке возвращается в хеш-фрагменте URI перенаправления, как показано ниже:

  • Ответ токена доступа:

    https://oauth2.example.com/callback#access_token=4/P7q7W91&token_type=Bearer&expires_in=3600

    В дополнении к access_token параметра, строка фрагмента также содержит token_type параметр, который всегда имеет значение Bearer , и expires_in параметр, который определяет срок службы маркеров, в секундах. Если state параметр был указан в запросе маркера доступа, его стоимость также включено в ответ.

  • Ошибочный ответ:
    https://oauth2.example.com/callback#error=access_denied

Пример ответа сервера OAuth 2.0

Вы можете протестировать этот поток, щелкнув следующий пример URL-адреса, который запрашивает доступ только для чтения для просмотра метаданных для файлов на вашем Google Диске:

https://accounts.google.com/o/oauth2/v2/auth?
 scope=https%3A//www.googleapis.com/auth/drive.metadata.readonly&
 include_granted_scopes=true&
 response_type=token&
 state=state_parameter_passthrough_value&
 redirect_uri=https%3A//oauth2.example.com/code&
 client_id=client_id

После завершения потока OAuth 2.0, вы будете перенаправлены на http://localhost/oauth2callback . Этот URL даст 404 NOT FOUND ошибки , если ваша локальная машина не происходит , чтобы служить файл по этому адресу. Следующий шаг предоставляет более подробную информацию об информации, возвращаемой в URI, когда пользователь перенаправляется обратно в ваше приложение.

Вызов API Google

Клиентская библиотека JS

После того, как ваше приложение получит токен доступа, вы можете использовать клиентскую библиотеку JavaScript для выполнения запросов API от имени пользователя. Клиентская библиотека управляет токеном доступа за вас, и вам не нужно делать ничего особенного, чтобы отправить его в запросе.

Клиентская библиотека поддерживает два способа вызова методов API. Если вы загрузили документ обнаружения, API определит для вас функции, зависящие от метода. Вы можете также использовать gapi.client.request функцию для вызова метода API. Следующие два фрагменты демонстрируют эти параметры для привода API, about.get методы.

// Example 1: Use method-specific function
var request = gapi.client.drive.about.get({'fields': 'user'});

// Execute the API request.
request.execute(function(response) {
  console.log(response);
});


// Example 2: Use gapi.client.request(args) function
var request = gapi.client.request({
  'method': 'GET',
  'path': '/drive/v3/about',
  'params': {'fields': 'user'}
});
// Execute the API request.
request.execute(function(response) {
  console.log(response);
});

Конечные точки OAuth 2.0

После того, как ваше приложение получит токен доступа, вы можете использовать этот токен для выполнения вызовов API Google от имени данной учетной записи пользователя, если предоставлены области доступа, требуемые API. Для этого, включите маркер доступа в запросе к API путем включения либо access_token параметр запроса или Authorization HTTP заголовка Bearer значение. По возможности предпочтительнее использовать заголовок HTTP, поскольку строки запроса обычно видны в журналах сервера. В большинстве случаев вы можете использовать клиентскую библиотеку , чтобы настроить звонки на Google API , (например, при вызове Drive Files API ).

Вы можете попробовать все Google API , а также просматривать их области на OAuth 2.0 Playground .

Примеры HTTP GET

Вызов к drive.files конечных точек (Драйв Files API) с использованием Authorization: Bearer HTTP заголовок может выглядеть следующим образом . Обратите внимание, что вам необходимо указать собственный токен доступа:

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

Вот вызов того же API для идентифицированного пользователя , используя access_token параметр строки запроса:

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curl примеры

Вы можете протестировать эти команды с curl приложением из командной строки. Вот пример, в котором используется параметр заголовка HTTP (предпочтительно):

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

Или, в качестве альтернативы, параметр параметра строки запроса:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

Пример кода JavaScript

Приведенный ниже фрагмент кода демонстрирует, как использовать CORS (совместное использование ресурсов между разными источниками) для отправки запроса в Google API. В этом примере не используется клиентская библиотека API Google для JavaScript. Тем не менее, даже если вы не используете библиотеку клиента, CORS поддержки руководства в документации, библиотеки, вероятно , поможет вам лучше понять эти запросы.

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

var xhr = new XMLHttpRequest();
xhr.open('GET',
    'https://www.googleapis.com/drive/v3/about?fields=user&' +
    'access_token=' + params['access_token']);
xhr.onreadystatechange = function (e) {
  console.log(xhr.response);
};
xhr.send(null);

Полный пример

Клиентская библиотека JS

Демо-пример кода

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

Обратите внимание , что это приложение запрашивает доступ к https://www.googleapis.com/auth/drive.metadata.readonly области. Доступ запрашивается только для демонстрации того, как инициировать поток OAuth 2.0 в приложении JavaScript. Это приложение не делает никаких запросов к API.

Пример кода JavaScript

Как показано выше, этот пример кода предназначен для страницы (приложения), которая загружает клиентскую библиотеку API Google для JavaScript и инициирует поток OAuth 2.0. На странице отображается либо:

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

Вы также можете запретить доступ к приложению через Разрешения страницы вашего аккаунта Google. Приложение перечислено как OAuth 2.0 Demo для Google API Docs.

<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from API Console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>

Конечные точки OAuth 2.0

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

Для потока OAuth 2.0 страница выполняет следующие действия:

  1. Он направляет пользователя на сервер компании Google OAuth 2.0, который запрашивает доступ к https://www.googleapis.com/auth/drive.metadata.readonly области.
  2. После предоставления (или отказа) доступа к одной или нескольким запрошенным областям пользователь перенаправляется на исходную страницу, которая анализирует токен доступа из строки идентификатора фрагмента.
  3. Страница использует токен доступа для выполнения образца запроса API.

    Запрос API вызывает привод API, about.get метод для получения информации о счете Google Drive авторизованного пользователя.

  4. Если запрос выполняется успешно, ответ API регистрируется в консоли отладки браузера.

Вы можете запретить доступ к приложению через Разрешения страницы вашего аккаунта Google. Приложение будет отображаться как OAuth 2.0 Demo для Google API Docs.

Для того, чтобы запустить этот код локально, необходимо устанавливать значения для YOUR_CLIENT_ID и YOUR_REDIRECT_URI переменных , которые соответствуют вашим учетным данным авторизации . YOUR_REDIRECT_URI переменная должна быть установлена в тот же URL , где страница обслуживаемых. Значение должно точно соответствовать один из авторизованной URI переадресации для клиента OAuth 2.0, который был настроен в API Console Credentials page. Если это значение не совпадает с авторизованной URI, вы получите redirect_uri_mismatch ошибку. Ваш проект также должен быть включен соответствующий API для этого запроса.

<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*
   * Create form to request access token from Google's OAuth 2.0 server.
   */
  function oauth2SignIn() {
    // Google's OAuth 2.0 endpoint for requesting an access token
    var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

Правила проверки происхождения JavaScript

Google применяет следующие правила проверки к исходным кодам JavaScript, чтобы помочь разработчикам обеспечить безопасность своих приложений. Ваше происхождение JavaScript должно соответствовать этим правилам. См RFC 3986 раздел 3 для определения домена, хоста и схемы, указанной ниже.

Правила валидации
Схема

Источники JavaScript должны использовать схему HTTPS, а не простой HTTP. URI локального хоста (включая URI IP-адреса локального хоста) не подпадают под это правило.

Хозяин

Хосты не могут быть необработанными IP-адресами. Это правило не распространяется на IP-адреса локального хоста.

Домен
  • Принимающие домены верхнего уровня ( Top Level Domains ) должны принадлежать к списку общественного суффиксом .
  • Принимающие домены не могут быть “googleusercontent.com” .
  • JavaScript происхождение не может содержать URL Shortener доменов (например goo.gl ) , если приложение не владеет доменом.
  • Userinfo

    Источники JavaScript не могут содержать подкомпонент userinfo.

    Дорожка

    Источники JavaScript не могут содержать компонент пути.

    Запрос

    Источники JavaScript не могут содержать компонент запроса.

    Фрагмент

    Источники JavaScript не могут содержать фрагментный компонент.

    Символы Исходные тексты JavaScript не могут содержать определенные символы, в том числе:
    • Символы подстановки ( '*' )
    • Непечатаемые символы ASCII
    • Недопустимые процентные кодировки (любая процентная кодировка, которая не соответствует форме кодирования URL-адресов, состоящей из знака процента, за которым следуют две шестнадцатеричные цифры)
    • Нулевые символы (кодированный символ NULL, например, %00 , %C0%80 )

    Инкрементальная авторизация

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

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

    В этом случае при входе в аккаунте времени приложение может запросить openid и profile области для выполнения основных подписей, а затем просить https://www.googleapis.com/auth/drive.file сферы в момент первая просьба сохранить микс.

    Следующие правила применяются к токену доступа, полученному в результате инкрементной авторизации:

    • Маркер может использоваться для доступа к ресурсам, соответствующим любой из областей, включенных в новую комбинированную авторизацию.
    • При использовании токена обновления для комбинированного разрешения для получения маркеров доступа, доступа маркера представляет собой комбинированное разрешение и может быть использован для любого из scope значений , включенных в ответ.
    • Комбинированная авторизация включает все области, которые пользователь предоставил проекту API, даже если гранты были запрошены от разных клиентов. Например, если пользователь предоставил доступ к одной области с помощью настольного клиента приложения, а затем предоставил другую область для того же приложения через мобильный клиент, комбинированная авторизация будет включать обе области.
    • Если вы отзываете токен, представляющий комбинированную авторизацию, доступ ко всем областям авторизации от имени связанного пользователя аннулируется одновременно.

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

    Клиентская библиотека JS

    Для добавления областей в существующий маркер доступа, вызовите GoogleUser.grant(options) метод. В options объект идентифицирует дополнительную области , к которым вы хотите предоставить доступ.

    // Space-separated list of additional scope(s) you are requesting access to.
    // This code adds read-only access to the user's calendars via the Calendar API.
    var NEW_SCOPES = 'https://www.googleapis.com/auth/calendar.readonly';
    
    // Retrieve the GoogleUser object for the current user.
    var GoogleUser = GoogleAuth.currentUser.get();
    GoogleUser.grant({'scope': NEW_SCOPES});

    Конечные точки OAuth 2.0

    Для добавления областей в существующий маркер доступа, включают include_granted_scopes параметр в вашем запросе на сервер компании Google OAuth 2.0 .

    Следующий фрагмент кода демонстрирует, как это сделать. Фрагмент предполагает, что вы сохранили области, для которых ваш токен доступа действителен, в локальном хранилище браузера. (The полного примера код сохраняет список областей , для которых маркер доступа является действительным, установив oauth2-test-params.scope свойства в локальном хранилище браузера.)

    Фрагмент сравнивает области, для которых токен доступа действителен, с областью, которую вы хотите использовать для конкретного запроса. Если токен доступа не охватывает эту область, запускается поток OAuth 2.0. Здесь oauth2SignIn функция является такой же , как тот , который был предоставлен в шаге 2 (и который предусмотрен позже в полном примере ).

    var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    
    var current_scope_granted = false;
    if (params.hasOwnProperty('scope')) {
      var scopes = params['scope'].split(' ');
      for (var s = 0; s < scopes.length; s++) {
        if (SCOPE == scopes[s]) {
          current_scope_granted = true;
        }
      }
    }
    
    if (!current_scope_granted) {
      oauth2SignIn(); // This function is defined elsewhere in this document.
    } else {
      // Since you already have access, you can proceed with the API request.
    }

    Отзыв токена

    В некоторых случаях пользователь может захотеть отозвать доступ, предоставленный приложению. Пользователь может отменить доступ, посетив Настройки аккаунта . Смотрите раздел доступа Удалить сайт или приложение из сторонних сайтов и приложений , имеющих доступ к вашей учетной записи документа поддержки для получения дополнительной информации.

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

    Клиентская библиотека JS

    Чтобы программно отменить маркер, вызов GoogleAuth.disconnect() :

    GoogleAuth.disconnect();

    Конечные точки OAuth 2.0

    Чтобы программно отменить маркер, приложение делает запрос на https://oauth2.googleapis.com/revoke и включает в себя маркер в качестве параметра:

    curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
            https://oauth2.googleapis.com/revoke?token={token}

    The token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token will also be revoked.

    If the revocation is successfully processed, then the HTTP status code of the response is 200 . For error conditions, an HTTP status code 400 is returned along with an error code.

    The following JavaScript snippet shows how to revoke a token in JavaScript without using the Google APIs Client Library for JavaScript. Since the Google's OAuth 2.0 endpoint for revoking tokens does not support Cross-origin Resource Sharing (CORS), the code creates a form and submits the form to the endpoint rather than using the XMLHttpRequest() method to post the request.

    function revokeAccess(accessToken) {
      // Google's OAuth 2.0 endpoint for revoking access tokens.
      var revokeTokenEndpoint = 'https://oauth2.googleapis.com/revoke';
    
      // Create <form> element to use to POST data to the OAuth 2.0 endpoint.
      var form = document.createElement('form');
      form.setAttribute('method', 'post');
      form.setAttribute('action', revokeTokenEndpoint);
    
      // Add access token to the form so it is set as value of 'token' parameter.
      // This corresponds to the sample curl request, where the URL is:
      //      https://oauth2.googleapis.com/revoke?token={token}
      var tokenField = document.createElement('input');
      tokenField.setAttribute('type', 'hidden');
      tokenField.setAttribute('name', 'token');
      tokenField.setAttribute('value', accessToken);
      form.appendChild(tokenField);
    
      // Add form to page and submit it to actually revoke the token.
      document.body.appendChild(form);
      form.submit();
    }