Является ли эта настройка использования исполняемого файла веб-приложения и API безопасной и разумной?

Эта проблема

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

"webapp": {
  "access": "ANYONE",
  "executeAs": "USER_DEPLOYING"}

Для пользователей внутри нашего домена мы можем использовать Session.getActiveUser(). . Затем мы можем сравнить это с нашей базой данных и показать конфиденциальные данные, которые должны быть видны только этой учетной записи.

Однако для пользователей за пределами нашего домена Session.getActiveUser() дает пустую строку '', поэтому мы не можем использовать ее для запроса информации в нашей базе данных, поэтому нам нужно что-то другое. Мы пришли к следующей настройке.

Альтернативная установка

Мы развертываем веб-приложение с помощью "executeAs": "USER_ACCESSING" и "oauthScopes": ["https://www.googleapis.com/auth/userinfo.email"]. Разворачиваем другой скрипт как исполняемый файл API (и следуем инструкциям здесь), с привилегированной учетной записью. Основной файл Code.gs веб-приложения выглядит следующим образом.

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index.html');
}

function getUserBackendData(){
  //works for users outside our domain
  var activeUserEmail = Session.getActiveUser();

  var apiKey = 'abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc'
  var scriptId = 'ababababababababababababababababababababababab';
  var token = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd'; //very secret

  var url = 'https://script.googleapis.com/v1/scripts/'+ scriptId +':run?key='+ apiKey;
  var functionCallData = 
      {
        "function": 'retrieveData',
        "parameters": [activeUserEmail],
        "devMode": false};
  var options = {
    'method' : 'post',
    'contentType': 'application/json',
    'payload' : JSON.stringify(functionCallData),
    'headers': {'Authorization': 'Bearer '+  token}
  };

  return UrlFetchApp.fetch(url, options).getContentText();
}

Идея состоит в том, что это позволяет нам выполнять функцию retrieveData(activeUserEmail) в нашем исполняемом файле API в качестве привилегированного пользователя, используя веб-приложение для определения адреса электронной почты пользователя, обращающегося к приложению. Причина, по которой Session.getActiveUser() теперь работает для пользователей за пределами нашего домена, заключается в том, что мы используем "executeAs": "USER_ACCESSING".

Вопросы)

Мы обеспокоены тем, что 1) существует более простой/лучший способ сделать это и 2) пользователь, обращающийся к веб-приложению, может каким-то образом получить токен, используемый для вызова функции в исполняемом файле API, который, как мы опасаемся, может быть использован для кражи личных данных.

Этот вопрос и ответ затрагивает проблему 2. К сожалению, в ответах не цитируется какая-либо официальная документация/ресурсы (и не все согласны) . Причем там секретный библиотечный ключ отсутствует в исходном коде веб-приложения (он есть в файле манифеста), тогда как в нашем случае секретный токен есть в исходном коде.

Вопрос. Является ли эта альтернативная установка безопасной и разумной?

Обновление: я только что нашел этот ответ, написанный пользователем, который кажется заслуживающим доверия. В ответе говорится, что пользователь веб-приложения не сможет увидеть код веб-приложения, даже если приложение развернуто как «Любой, даже анонимный». Однако это утверждение подстраховано фразой «То, о чем я знаю».


person jano    schedule 02.08.2019    source источник
comment
Я не думаю, что вы должны писать токен в своем скрипте. Не из-за проблем с безопасностью, поскольку пользователи не могут видеть библиотеку, а из-за того, что у нее есть срок годности. Вы должны попытаться сгенерировать его по коду. Это может вам помочь . Также это   -  person Jescanellas    schedule 05.08.2019
comment
@Jescanellas спасибо за ваш комментарий. Re: пользователи не видят библиотеку; Я предполагаю, что под библиотекой вы имеете в виду файл сценария Google Apps, и я предполагаю, что вы имеете в виду, что даже файл, соответствующий веб-приложению, не может быть проверен (и, надеюсь, не отлажен и т. д.). Это ценная информация для меня, может у вас есть источник?   -  person jano    schedule 05.08.2019
comment
Re: Вы должны попытаться сгенерировать его по коду; обратите внимание, что моя настройка не типична в том смысле, что обычно сервер запрашивает у пользователя токен (что предполагает взаимодействие с пользователем), с помощью которого сервер может получить доступ к данным пользователя. Ваша первая ссылка кажется быть о типичной ситуации. Также кажется, что StateTokenBuilder (ваша вторая ссылка) разработан, чтобы помочь в типичной настройке ...   -  person jano    schedule 05.08.2019
comment
... В моей настройке сервер/бэкэнд/привилегированный пользователь не нуждается в токене для доступа к данным пользователей, вместо этого скрипт веб-приложения запускается, когда пользователь сообщает привилегированному пользователю запустить функцию, для которой ему нужен токен связан с привилегированным пользователем. Предполагая, что нам действительно нужен секрет, которым мы не хотим делиться с пользователем, будь то сам токен или что-то для его создания (например, токен обновления), моя трудность заключается в том, что скрипт, выполняемый от имени пользователя, может только информация о доступе, доступная пользователю, за исключением, может быть, источника скрипта (или чего-то еще).   -  person jano    schedule 05.08.2019
comment
Спасибо, что указали на проблему с истечением срока действия токенов. Я не думал так много. Возможно, это все еще может работать, если вместо этого мы будем жестко кодировать токен обновления в веб-приложении. Опять же, мне было бы интересно узнать, разумно ли это, и какие существуют альтернативы, если таковые имеются. Может быть, более разумно иметь облачную функцию Google, которая, в свою очередь, вызывает исполняемый файл API, но я я не в себе.   -  person jano    schedule 05.08.2019
comment
Дело в том, что если вы сделаете это в Apps Script, весь процесс OAuth 2 будет автоматизированный, поэтому вам не нужно ничего с этим делать, если только нет проблем с разрешениями. Итак, о безопасности я не нашел ничего явного, но, поскольку это делается с помощью Apps Script, он настолько безопасен, насколько могут быть OAuth 2 и Apps Script, поэтому я бы не беспокоился об утечке данных.   -  person Jescanellas    schedule 05.08.2019
comment
@Jescanellas, вы говорите, что процесс автоматизирован, но эта ссылка не дает понять, что вы предлагаете мне автоматизировать и как это сделать. Страница, на которую вы ссылаетесь, указывает на краткие руководства, и я просмотрел node.js. быстрый старт. В этом примере действительно есть хороший код, автоматизирующий процесс получения токена, отправляя пользователя по URL-адресу, где он получает код, который можно преобразовать в токен. На самом деле это код, который я использовал для создания токенов, позволяющих моему веб-приложению получить доступ к моему исполняемому файлу API...   -  person jano    schedule 05.08.2019
comment
... Но опять же токен связан с привилегированным пользователем, а не с пользователем веб-приложения. Таким образом, нет смысла включать такой код в мою текущую настройку, поскольку, конечно, нецелесообразно требовать от привилегированного пользователя/серверного демона щелчка по графическому интерфейсу, пока пользователь веб-приложения ждет. Я подумал, что все это можно обойти путем жесткого кодирования токена обновления, хотя я не смотрел, как из этого генерировать токены доступа.   -  person jano    schedule 05.08.2019
comment
Извините, что не объяснил себя лучше. Быстрые старты, которые вы нашли, действительно являются примерами создания токенов, но поскольку они не предназначены для запуска в скриптах приложений, их необходимо генерировать. Примера скрипта приложений нет, потому что он делает это сам, вам не нужно ничего делать. Любой вызов API, который вы делаете из Apps Script, будет запрашивать разрешения для вашей учетной записи Google. После того, как вы предоставили разрешения, вы можете увидеть области действия Oauth вашего скрипта в меню «Вид» -> «Показать файл манифеста». Как только пользователь выполнит ваше веб-приложение как USER_ACCESSING, приложение будет использовать OAuth, чтобы запросить разрешения для своей учетной записи Google.   -  person Jescanellas    schedule 06.08.2019
comment
@Jescanellas Re: Любой вызов API, который вы выполняете из Apps Script, будет запрашивать разрешения для вашей учетной записи Google. Я понимаю, что обычно этот сценарий приложений будет управлять областями действия, поэтому, если вы используете, например. DriveApp.getFiles() пользователю веб-приложения предлагается предоставить приложению разрешение на просмотр файлов на его диске. Если области управляются автоматически, эти области не будут видны в файле манифеста, верно? Я всегда ищу их в File > Project Properties > Scopes...   -  person jano    schedule 06.08.2019
comment
... В любом случае, если я делаю запрос к моему исполняемому файлу API, мне нужен токен, если я прокомментирую строку 'headers': {'Authorization': 'Bearer '+ token}, я получаю сообщение об ошибке. В запросе отсутствуют необходимые учетные данные аутентификации. Ожидаемый токен доступа OAuth 2, файл cookie для входа или другие действительные учетные данные для аутентификации. См. developers.google.com/identity/sign-in/web/devconsole. -проект. Единственная область, которая автоматически вводится таким образом при использовании UrlFetchApp, — это script.external_request. И опять же, даже если скрипт запросит правильные области видимости, он запросит доступ не у того пользователя...   -  person jano    schedule 06.08.2019
comment
... Чтобы избежать ненужных сложностей с базами данных, предположим, что только привилегированный пользователь имеет доступ к электронной таблице, содержащей все конфиденциальные данные. Поэтому, если пользователь веб-приложения разрешает приложению доступ к своим файлам на диске Google, это бесполезно, поскольку файл находится не на его диске. Электронной таблицей нельзя поделиться с пользователями веб-приложения, поскольку пользователи должны иметь доступ только к той строке электронной таблицы, которая содержит их информацию...   -  person jano    schedule 06.08.2019
comment
... Вот почему я ввел исполняемый файл API в свою настройку, чтобы его мог выполнить привилегированный пользователь. Я не знаю другого способа вызова моего исполняемого файла API, кроме UrlFetchApp.   -  person jano    schedule 06.08.2019


Ответы (1)


В большинстве случаев вместо использования исполняемого файла API, вероятно, более разумно делать запросы к веб-приложению. Можно сделать запрос на получение или отправку в веб-приложение таким образом, чтобы веб-приложение знало, кто делает запрос (т. е. Session.getActiveUser работает в веб-приложении).

Подробнее см. (мой другой ответ) здесь: https://stackoverflow.com/a/59428929/11873333

person jano    schedule 09.01.2020