@iconicompany/iauth
v0.1.0
Published
OAuth 2.0 client_credentials service tokens with an in-memory cache per scope and audience set
Readme
@iconicompany/iauth
Служебные токены OAuth 2.0 client_credentials: кеш в памяти по набору scope и аудиторий,
обновление до истечения срока, один запрос на все одновременные вызовы. Без зависимостей.
Пакет — исходники TypeScript без сборки: нужен Bun.
Окружение пакет не читает — всё передаётся параметрами.
bun add @iconicompany/iauthimport { ClientCredentials, TokenRequestError } from "@iconicompany/iauth";
const client = new ClientCredentials({
tokenUrl: "https://id.example.com/oauth/v2/token",
clientId: "service",
clientSecret: "…",
audienceStyle: "zitadel",
});
const db = client.source({
scopes: ["openid", "urn:zitadel:iam:org:projects:roles"],
audiences: ["390466787977724088"],
});
const pool = new Pool({ password: () => db.token() }); // токен на каждое соединение — из кеша
const apiKey = db.peek(); // синхронно: токен или nullПараметры
| Параметр | Умолчание | Смысл |
| -------------------------------------- | ---------- | -------------------------------------------------------------------------------- |
| tokenUrl, clientId, clientSecret | — | обязательны |
| authMethod | basic | basic — заголовок Authorization (RFC 6749 §2.3.1), post — реквизиты в теле |
| audienceStyle | resource | как аудитории попадают в запрос, см. ниже |
| refreshMarginSeconds | 60 | за сколько до конца срока обновлять |
| fetch, now | глобальные | подмена транспорта и часов |
Аудитории
| audienceStyle | Что уходит | У кого |
| --------------- | ---------------------------------------------------------- | --------------- |
| resource | resource=<aud> на каждую (RFC 8707) | стандарт |
| zitadel | scope urn:zitadel:iam:org:project:id:<aud>:aud на каждую | ZITADEL |
| audience | audience=<aud> на каждую | Auth0, Keycloak |
Кеш
Ключ — набор scope и аудиторий без повторов и порядка. token() отдаёт токен из кеша до
max(expires_in − refreshMarginSeconds, expires_in / 2), потом запрашивает новый; peek() —
до expires_in. Без expires_in срок 300 с. Кеш — в экземпляре, между процессами не делится.
Ошибки
TokenRequestError: status (null — сеть), error, description, cause. Сообщение называет
причину и не содержит секрета и токена. Повторов нет — политику выбирает вызывающий.
Разработка
bun run validate # формат, линтер, типы, тесты
RUN_LIVE=1 LIVE_TOKEN_URL=… LIVE_CLIENT_ID=… LIVE_CLIENT_SECRET=… \
LIVE_AUDIENCES="<aud1> <aud2>" bun run test:live