25 函数 · OAuth 2.0 + OIDC 辅助 · MIT

xoauth2 函数参考

OAuth 2.0 (RFC 6749) 客户端:build.bat xoauth2 编入。授权码流程 + PKCE (RFC 7636) + token 刷新 + 五家 provider 预设;OIDC 辅助(nonce 一次性焚毁、HttpGet 拉 JWKS、GetUserInfo)。传输经 xoauth2httpproc 回调注入——测试 mock 可离线驱动全流程,宿主可替换为任意 HTTP 实现,附 xrt net/tls/http1 便捷实现 xoauth2HttpXrt(http/https、IPv6、系统或指定 CA、响应体 1MB 上限)。与 xjwt 数据耦合零依赖:OIDC 登录组合在脚本层 8 行胶水完成。

配置与预设(7 函数)

xoauth2UseGithub / UseGoogle / UseWechat / UseMicrosoft / UseCustom 预设

一行初始化:GitHub(含 api.github.com/user)、Google(OIDC:issuer + JWKS + nonce)、WeChat(OAuth only,PKCE 关)、Microsoft(端点与 issuer 按 tenant 动态生成,第三块 owned URL 由客户端持有,ClientUnit 释放)、Custom(自备 xoauth2config)。预设管 provider 知识,传输注入是独立的下一步(Config.Http = ...)。

void xoauth2UseGithub(xoauth2client* pClient, const char* id, const char* secret, const char* redirect);

xoauth2ConfigInit / xoauth2ClientUnit 生命周期

配置清零(UsePkce 默认开、AuthStyle 自动);ClientUnit 会话终止:清零敏感 state/verifier/nonce,释放预设持有的端点 URL 并清配置——复用须重新 Use* 预设。Microsoft 预设 tenant 超 256 字符拒绝(端点留 NULL)。

登录流程(3 函数)

xoauth2BeginLogin 授权入口

生成随机 state(CSRF)与 PKCE verifier/challenge(S256,尊重预设 UsePkce),UseNonce 时生成 nonce,拼授权 URL(scope/redirect 全 form 编码)。返回 URL(xrtFree),重定向用户浏览器到它。

char* xoauth2BeginLogin(xoauth2client* pClient);

xoauth2CompleteLogin 回调换 token

state 常时比较(通过即焚毁,防重放)→ 构造 token 请求(AuthStyle=BODY 凭据入体全编码 / =BASIC 走 Authorization 头)→ 焚毁 verifier → 经传输回调 POST → 响应分级解析。成功返回 token(xoauth2TokenFree 释放)。state 校验失败后必须重新 BeginLogin。

xoauth2token* xoauth2CompleteLogin(xoauth2client* pClient, const char* sCode, const char* sState);
示例 · GitHub 登录三步
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 释放

释放 token——access/refresh/id token 明文先清零再释放。

token 管理(2 函数)

xoauth2Refresh 刷新

grant_type=refresh_token 请求构造 + 传输 + 分级解析(AuthStyle 同 CompleteLogin)。旧 token 由调用方释放。错误码四级:NETWORK(连接/超时/TLS)→ TOKEN_ENDPOINT(HTTP 错误状态)→ TOKEN_DENIED(provider error 字段)→ TOKEN_RESPONSE(2xx 体解析失败)。

xoauth2token* xoauth2Refresh(xoauth2client* pClient, const char* sRefreshToken);

xoauth2TokenExpiring 过期判断

按 ExpiresAt 与当前时钟判断是否将在 leewaySeconds 内过期。provider 未返回 expires_in(如 GitHub)时视为不过期——未知 ≠ 即将过期,此类 token 通常也无 refresh_token。

OIDC 辅助(3 函数,数据耦合层)

xoauth2HttpGet 通用 GET

借客户端的传输回调 GET 任意 URL,返回响应体文本(xrtFree)。典型用途:拉取 JWKS JSON。错误分级同 token 交换。

char* xoauth2HttpGet(xoauth2client* pClient, const char* sUrl, const char* sAuthHeader, int* piStatus);

xoauth2NonceConsume nonce 消费

与 BeginLogin 生成的 nonce 常时比对,匹配即焚毁(一次性,防重放)返回 true;不匹配设 XOAUTH2_ERROR_NONCE_MISMATCH。

xoauth2GetUserInfo 用户信息

GET UserInfoUrl + Authorization: Bearer(动态分配,超长 token 不截断),返回 claims 对象(非对象 JSON 拒绝)。对非 OIDC provider(如 WeChat /sns/userinfo)同样是正路。

xvalue* xoauth2GetUserInfo(xoauth2client* pClient, const char* sAccessToken);
示例 · OIDC 登录组合(与 xjwt 的 8 行胶水)
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 verifier + 超时(默认 15s)。C 宿主栈上声明用。

xoauth2HttpXrtCreate / xoauth2HttpXrtDestroy 堆版

堆分配句柄——opaque 结构无法栈上声明时用(脚本层/绑定层的正路)。参数语义与 Init 相同。

xoauth2httpxrt* xoauth2HttpXrtCreate(void* pBorrowedEngine, const char* sCaPem, uint64_t uTimeoutUs);

xoauth2HttpXrt 传输回调

POST/GET 双方法(POST 带 form 头、GET 无实体头,Authorization 两态透传)、http/https 双 scheme、IPv6 字面量、future 化 TLS/TCP IO、xrt http1 组装与解析、响应体 1MB 上限。挂在 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。

安全基线:state/nonce 常时比较 + 一次性焚毁、verifier 用后焚毁、请求体全字段 form 编码、Basic 头 RFC 6749 §2.3.1、token 敏感字段释放前清零、expires_in 非整数拒绝。测试 166+15 项(mock 全路径/回环真实端到端/与 xjwt 组合回归)。完整源码见仓库 lib/xoauth2;与 xjwt 数据耦合(无 requires,两库互不相识)。