Как аутентифицировать учетную запись службы с помощью скрипта приложений для вызова облачной функции GCP

Я изо всех сил пытаюсь запустить облачную функцию GCP из скрипта приложений. Облачная функция требует аутентификации. Однако я продолжаю получать "Ошибка 401"

В моем проекте Google;

  1. Я создал облачную функцию, требующую аутентификации
  2. Я создал учетную запись службы, у которой есть доступ к этой функции (и редактирование).
  3. Я загрузил ключ JSON для этой учетной записи службы и сохранил его как объект с именем CREDS в моем скрипте приложений.

Это мой сценарий на данный момент:

const CREDS = {....JSON Key I downloaded from Cloud Console}

function base64Encode(str){
  let encoded = Utilities.base64EncodeWebSafe(str)

  return encoded.replace(/=+$/,'')
}

function encodeJWT(){
  const privateKey = `Copied the PK from the CREDs file and replaced all the escaped whitespace as a string literal`;

  let header = JSON.stringify({
    alg: "RS256",
    typ: "JWT",
  });

  let encodedHeader = base64Encode(header);

  const now = Math.floor(Date.now() / 1000);
  let payload = JSON.stringify({
    "iss": "https://accounts.google.com",
    "azp": "OAUTH CLIENT ID I CREATED ON GCP",
    "aud": "OAUTH CLIENT ID I CREATED ON GCP",
    "sub": CREDS.client_id,
    "email": CREDS.client_email,
    "email_verified": true,
    //    "at_hash": "TMTv8_OtKA539BBRxLoTBw", //Saw this in a reverse engineered Token but didnt know what to put
    "iat": now.toString(),
    "exp": (now + 3600).toString()  
  })

  let encodedPayload = base64Encode(payload);

  let toSign = [encodedHeader, encodedPayload].join('.')
  let signature = Utilities.computeRsaSha256Signature(toSign, privateKey)
  let encodedSignature = base64Encode(signature);

  let jwt = [toSign, encodedSignature].join('.')

  return jwt;

}

function testFireStore() {
  let funcUrl = "https://[MY PROJECT].cloudfunctions.net/MyFunc"

  const token = encodeJWT()
  let options = {
    headers:{
      "Authorization": "Bearer " + token
    }
  }


  let func = UrlFetchApp.fetch(funcUrl,options)
  Logger.log(func.getContentText())
}

Фактическая функция Cloud на данный момент просто выдает "Hello World", и она отлично тестируется в консоли.

К вашему сведению, некоторые шаги я уже сделал

  • Я сгенерировал токен с помощью gcloud на своем локальном компьютере и использовал его в моем скрипте приложений, который отлично работает
  • Я взял указанный токен и реконструировал его на https://jwt.io.
  • Я использовал код здесь, чтобы создать свой Функция JWT, которую я проверил с помощью https://jwt.io, чтобы убедиться, что она в правильном формате.

person Riaz Shageer    schedule 01.06.2020    source источник
comment
Я сгенерировал токен с помощью gcloud на своем локальном компьютере и использовал его в моем скрипте приложений, он работает нормально Значит, это означает, что токен, созданный скриптом приложений, неверен?   -  person TheMaster    schedule 02.06.2020
comment
Да, я так думаю. Когда я анализирую его с помощью онлайн-анализатора в [jwt.io], он говорит, что подпись неверна, поэтому я предполагая, что существует проблема с тем, как appsscript подписывает   -  person Riaz Shageer    schedule 02.06.2020
comment
Отвечает ли это на ваш вопрос? Как авторизовать Google Speech-to -текст из скрипта Google Apps?   -  person TheMaster    schedule 02.06.2020
comment
Это похоже, но не совсем. Это дает токен доступа. Cloud Requests запрашивает токен удостоверения в формате JWT. Дело в том, что я видел это решение, и даже в документах говорится, что вы можете получить от него JWT, но не видел, где ... Если я что-то не пропустил   -  person Riaz Shageer    schedule 03.06.2020
comment
См. образец   -  person TheMaster    schedule 03.06.2020
comment
@TheMaster великолепно ... это работает для меня, я создам ответ и поставлю это решение (помечая вас) Единственная странность в том, что для того, чтобы я заставил это работать, target_audience - это что-то, что мне пришлось перепроектировать , он не работал с тем, что было в документации. Как у меня это получилось, я получил токен с помощью командной строки GCloud, а затем использовал jwt.io, чтобы декодировать и посмотреть, что Поле AUD было там .... Есть ли более простой способ сделать это в будущем?   -  person Riaz Shageer    schedule 03.06.2020
comment
Задайте новый вопрос, поскольку он достаточно отклоняется от объема исходного вопроса.   -  person TheMaster    schedule 03.06.2020


Ответы (1)


Это решение, опубликованное @TheMaster в комментариях к моему решению, решило проблему.

Что касается GCP, я включил Compute Engine и App Engine, затем использовал это решение, и оно сработало.

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

но кроме этого, все работало как шарм

person Riaz Shageer    schedule 03.06.2020