Конфигурация и пресеты (7 функций)
xoauth2UseGithub / UseGoogle / UseWechat / UseMicrosoft / UseCustom пресеты
Инициализация одной строкой: GitHub (включая api.github.com/user), Google (OIDC: issuer + JWKS + nonce), WeChat (только OAuth, PKCE выключен), Microsoft (эндпоинты и issuer генерируются по tenant — третий owned-URL, удерживаемый клиентом и освобождаемый ClientUnit), Custom (свой xoauth2config). Пресеты несут знания о провайдере; инъекция транспорта — отдельный следующий шаг (Config.Http = ...).
xoauth2ConfigInit / xoauth2ClientUnit жизненный цикл
Обнуляет конфигурацию (UsePkce по умолчанию включён, AuthStyle авто); ClientUnit завершает сессию: обнуляет чувствительные state/verifier/nonce, освобождает принадлежащие пресету URL эндпоинтов и чистит конфигурацию — перед повторным использованием выполните пресет заново. tenant Microsoft длиннее 256 символов отклоняется (эндпоинты остаются NULL).
Поток входа (3 функции)
xoauth2BeginLogin вход в авторизацию
Генерирует случайный state (CSRF) и PKCE verifier/challenge (S256, с учётом UsePkce пресета), nonce при UseNonce и собирает URL авторизации (scope/redirect полностью form-кодируются). Возвращает URL (xrtFree) — перенаправьте туда браузер пользователя.
xoauth2CompleteLogin обмен кода
Сравнение state за константное время (при совпадении сжигается, защита от повтора) → сборка запроса токена (AuthStyle=BODY кладёт полностью закодированные учётные данные в тело; =BASIC шлёт заголовок Authorization) → сжигание verifier → POST через транспортный колбэк → градуированный разбор ответа. Успех — токен (освободить xoauth2TokenFree). После несовпадения state нужен новый BeginLogin.
xoauth2client oauth;
xoauth2UseGithub(&oauth, sClientId, sSecret, "https://app.example/cb");
oauth.Config.Http = xoauth2HttpXrt; /* инъекция транспорта */
oauth.Config.HttpContext = pHttp; /* дескриптор из xoauth2HttpXrtCreate */
char* url = xoauth2BeginLogin(&oauth); /* 302 на страницу авторизации */
/* ...пользователь авторизуется; колбэк с code + state... */
xoauth2token* tok = xoauth2CompleteLogin(&oauth, sCode, sState);
if ( tok ) {
/* tok->AccessToken / RefreshToken / ExpiresAt */
xoauth2TokenFree(tok); /* чувствительные поля уже обнулены */
}
xoauth2TokenFree освобождение
Освобождает токен — открытый текст access/refresh/id токенов beforehand обнуляется.
Управление токенами (2 функции)
xoauth2Refresh обновление
Собирает запрос grant_type=refresh_token, прогоняет через транспорт и разбирает градуированный ответ (AuthStyle как в CompleteLogin). Старый токен освобождает вызывающий. Четыре уровня ошибок: NETWORK (соединение/таймаут/TLS) → TOKEN_ENDPOINT (ошибочный HTTP-статус) → TOKEN_DENIED (поле error от провайдера) → TOKEN_RESPONSE (сбой разбора тела при 2xx).
xoauth2TokenExpiring проверка истечения
Сверяет ExpiresAt с текущими часами: истечёт ли токен в течение leewaySeconds. Если провайдер не вернул expires_in (например, GitHub) — считается неистекающим: неизвестный срок ≠ вот-вот истечёт, и у таких токенов обычно нет refresh_token.
Помощники OIDC (3 функции, слой сопряжения на данных)
xoauth2HttpGet универсальный GET
Выполняет GET через транспортный колбэк клиента для любого URL и возвращает текст тела ответа (xrtFree). Типичное применение — загрузка JWKS JSON. Градуировка ошибок как при обмене токена.
xoauth2NonceConsume потребление nonce
Сравнение за константное время с nonce, сгенерированным BeginLogin; при совпадении сжигается (однократно, защита от повтора) и возвращается true; несовпадение устанавливает XOAUTH2_ERROR_NONCE_MISMATCH.
xoauth2GetUserInfo данные пользователя
GET UserInfoUrl с Authorization: Bearer (динамическое выделение — длинные токены не обрезаются), возвращает объект claims (не-объектный JSON отклоняется). Также верный путь для не-OIDC провайдеров (например, WeChat /sns/userinfo).
xoauth2token* tok = xoauth2CompleteLogin(&oauth, code, state);
int st;
char* jwksJson = xoauth2HttpGet(&oauth, oauth.Config.JwksUrl, NULL, &st);
xjwtjwks* keys = xjwtJwksParse(jwksJson); /* строка на входе */
xjwtcheck ck; xjwtCheckInit(&ck);
ck.Issuer = oauth.Config.Issuer; /* знание пресета — просто строка */
ck.Audience = oauth.Config.ClientId;
xvalue* claims = xjwtVerifyJwks(tok->IdToken, keys, &ck);
char nonce[128];
xjwtClaimString(claims, "nonce", nonce, sizeof(nonce));
xoauth2NonceConsume(&oauth, nonce); /* константное время + сжигание */
Транспорт из комплекта (5 функций)
xoauth2HttpXrtInit / xoauth2HttpXrtUnit стековый вариант
Создаёт или заимствует net engine + верификатор системного/своего CA + таймаут (по умолчанию 15 с). Для C-хостов со стековым объявлением.
xoauth2HttpXrtCreate / xoauth2HttpXrtDestroy кучный вариант
Дескриптор в куче — когда непрозрачную структуру нельзя объявить на стеке (естественный путь для уровня скриптов). Параметры как у Init.
xoauth2HttpXrt транспортный колбэк
Два метода POST/GET (POST с form-заголовками, GET без заголовков сущности; Authorization передаётся в обоих), схемы http/https, литералы IPv6, будущий TLS/TCP-ввод-вывод, сборка и разбор http1 из xrt, лимит тела ответа 1 МБ. Подключается на Config.Http.
Утилиты и ошибки (5 функций)
xoauth2PkceGenerate / xoauth2StateGenerate / xoauth2UrlEncode офлайн-инструменты
PKCE code_verifier (случайные 43 символа) + challenge (BASE64URL(SHA256(verifier)), воспроизводимо проверяется); случайный state (URL-safe); процентное кодирование URL — всё доступно офлайн для тестов и нестандартных сценариев.
xoauth2LastError чтение ошибки
Возвращает код ошибки домена xoauth2 (XOAUTH2_ERROR_*, восемь значений), 0 для чужих доменов. Читайте сразу после сбоя. Четыре уровня прямо отображаются на семантику HTTP: STATE_MISMATCH→400, TOKEN_DENIED→401, ENDPOINT/RESPONSE→502, NETWORK→504.