Проверка JWT из запроса публикации в чате Google

#node.js #google-api #jwt

#node.js #google-api #jwt

Вопрос:

У меня есть бот в NodeJS, подключенный к Google Chat с использованием конечных точек HTTPs. Я использую экспресс для получения запросов. Мне нужно убедиться, что все запросы поступают от Google, и я хочу сделать это, используя токен-носитель, который Google отправляет с запросами.

Моя проблема в том, что я изо всех сил пытаюсь найти способ проверки токенов.

Я захватил токен и попытался получить запросы на https://oauth2.googleapis.com/tokeninfo?id_token=ey … (где ey… является началом токена).

Который возвращает:

     "error": "invalid_token",
    "error_description": "Invalid Value"
}
 

Я попробовал то, что рекомендует Google:

 var token = req.headers.authorization.split(/[ ] /);
client.verifyIdToken({
    idToken: token[1],
    audience: JSON.parse(process.env.valid_client_ids)
}).then((ticket) => {
    gchatHandler.handleGChat(req.body, res);
}).catch(console.error);
 

И получите следующую ошибку:

Ошибка: pem не найден для конверта: {«alg»:»RS256″, «kid»:»d … 1″, «typ»:»JWT»}

Есть идеи, куда мне следует направиться отсюда?

Редактировать: https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com нашел это, исследуя, как его использовать. Ребенок соответствует тому, который я получаю.

Ответ №1:

В конце концов, это сработало.

Вам нужно нажать: https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com чтобы получить JSON-файл, содержащий ключи, связанные с их дочерними элементами.

Затем, когда поступает запрос, используйте jsonwebtoken (NPM) для декодирования токена и извлечения дочернего элемента из заголовка.

Используйте KID, чтобы найти соответствующий открытый ключ в ответе с веб-сайта выше, затем используйте функцию проверки, чтобы убедиться, что токен соответствует открытому ключу.

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

Ответ №2:

Приведенное выше решение может быть правильным для Google Chat, но, по моему опыту, службы Google (например, задачи Google) используют токены OIDC, которые можно проверить с verifyIdToken помощью функции.

Добавляю свое решение здесь, поскольку ваш вопрос / ответ был самым близким, что я смог найти для своей проблемы

Итак, в случае, если вам нужно подписать запрос из вашего собственного кода

на клиенте отправляйте запросы с помощью токена OIDC

 import {URL} from 'url';
import {GoogleAuth} from 'google-auth-library'; 

// will use default auth or GOOGLE_APPLICATION_CREDENTIALS path to SA file
// you must validate email of this identity on the server!
const auth = new GoogleAuth({});

export const request = async ({url, ...options}) => {
  const targetAudience = new URL(url as string).origin;
  const client = await auth.getIdTokenClient(targetAudience);
  return await client.request({...options, url});
};

await request({ url: 'https://my-domain.com/endpoint1', method: 'POST', data: {} })
 

на сервере проверьте OIDC (идентификационный токен)

 
const auth = new OAuth2Client();

const audience = 'https://my-domain.com';


// to validate
const token = req.headers.authorization.split(/[ ] /)[1];
const ticket = await auth.verifyIdToken({idToken: token, audience });

if (ticket.getPayload().email !== SA_EMAIL) {
 throw new Error('request was signed with different SA');
}
// all good
 

Подробнее о токенах Google OpenID Connect