В Auth0 есть два способа получить токен:

  1. Создать аккаунт для пользователя
  2. Создать m2m клиент с определенными правами.

Разработчики Auth0 дали возможность хранить дополнительную мета-информацию в аккаунтах и клиентах. Если в аккаунте человека нет ограничения на объем данных - в поле можно записать текст размером до 16 мб - то для m2m у нас в распоряжении только 10 полей по 255 символов каждый. Даже на небольшой массив места не хватит.

В проекте мы активно применяем метаинформацию аккаунтов для формирования токена, такие же правила хотим применить и для m2m клиентов. Хочу напомнить, что формирование токена можно кастомизировать с помощью кода на JS, который будет вызван как коллбек на события в Auth0 Flows. К сожалению, ограничения не дают нам такой возможности. Какие у нас есть варианты:

1. Не хранить в токене m2m никакой допинформации.

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

2. Сжать данные в полях, чтобы умещались в ограничение в 255 символов.

Тут не придумаешь универсального решения - пришлось бы поддерживать собственные алгоритмы сжатия. Но даже после сжатия велик шанс, что полученная строка уместится в поле.

3. Сделать запрос на бэкенд за допинформацией в коллбеке Auth0

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

const axios = require('axios');

const getData = async function(clientId) {
  const options = {
    method: 'get',
    url: 'https://api.example.net/some-data/' + clientId,
    headers: {
      'Content-Type': 'application/json',
      'x-api-version': '3'
    }
  };

  const response = await axios.request(options);

  // Стоит проверить статус ответа и валидность данных
  console.log(response.status);
  console.log(response.data);

  // Здесь мы берем данные из ответа бэкенда
  return response.data.permissions
}

// Код коллбека Auth0, создаваемый автоматически
exports.onExecuteCredentialsExchange = async (event, api) => {

  const clientId = event.client.client_id;
  const permissions = await getAccessData(clientId);

  // Записываем данные в токен
  const namespace = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims';
  api.accessToken.setCustomClaim(namespace + "/permissions", permissions);
};

После обсуждения мы решили, что это самый оптимальный вариант:

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

Тут важно учесть, как часто токен будет формироваться и каков его лайфтайм. Для пользователей такая схема даст гораздо больше проблем, ведь так время жизни токена - всего 1 час, да и пользователей гораздо больше, чем m2m клиентов.

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