summaryrefslogtreecommitdiff
path: root/src/auth_manager.zig
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-13 14:24:31 -0600
committert <t@tjp.lol>2026-06-15 15:08:32 -0600
commit20e6e08a42240aef0b36ecf627cbcde921912071 (patch)
treefd7e1f860f28ffa41d33416fb6277a95e530191e /src/auth_manager.zig
parentfbee69ca8c4b485b7b2d6fe7448b13367c4716c8 (diff)
auth: flatten [auth.<name>] config + ${...} substitution
Collapse the auth schema: infer `type` from keys, replace key/key_env_var with a single `key` (resolved via substitution), flatten the exchange to flat `exchange_*` keys, and drop the auth-level headers tables in favor of reusing the provider's `extra_headers` on the auth HTTP calls. Add `${sibling}` and `${env:VAR}` substitution over auth values (GitHub Enterprise = set `domain`). Restore api_key-empty → provider-drop. Update default config, docs, and tests.
Diffstat (limited to 'src/auth_manager.zig')
-rw-r--r--src/auth_manager.zig12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/auth_manager.zig b/src/auth_manager.zig
index 87b20ae..e26e28a 100644
--- a/src/auth_manager.zig
+++ b/src/auth_manager.zig
@@ -95,7 +95,10 @@ pub const AuthManager = struct {
.oauth_device => |oauth| {
_ = self.cred_arena.reset(.retain_capacity);
const arena = self.cred_arena.allocator();
- const cred = try self.resolveOAuth(arena, oauth, prov.auth_name, force, presenter);
+ // The provider's identity headers ride on every auth HTTP call
+ // (exchange/device/poll), the same way they ride on the model
+ // request.
+ const cred = try self.resolveOAuth(arena, oauth, prov.auth_name, prov.extra_headers, force, presenter);
try patchCredential(live, prov, cred, arena);
},
}
@@ -109,6 +112,7 @@ pub const AuthManager = struct {
arena: Allocator,
oauth: panto.OAuthDeviceAuth,
name: []const u8,
+ headers: []const panto.Header,
force: bool,
presenter: ?panto.Presenter,
) anyerror!panto.ResolvedCredential {
@@ -120,7 +124,7 @@ pub const AuthManager = struct {
// Working token set; strings borrow from `loaded` or `arena`.
var ts: panto.TokenSet = if (loaded) |l| l.value else blk: {
const p = presenter orelse return Error.LoginRequired;
- const toks = try panto.oauthLogin(arena, self.io, self.client, oauth, p);
+ const toks = try panto.oauthLogin(arena, self.io, self.client, oauth, p, headers);
const fresh = try panto.tokensToTokenSet(arena, oauth, toks, now);
try self.saveToken(name, fresh);
break :blk fresh;
@@ -128,7 +132,7 @@ pub const AuthManager = struct {
// Refresh the access token if it's near expiry (or forced).
if ((force or panto.needsRefresh(ts, now, refresh_margin_secs)) and ts.refresh_token != null) {
- const toks = try panto.refreshTokens(arena, self.client, oauth, ts.refresh_token.?);
+ const toks = try panto.refreshTokens(arena, self.client, oauth, ts.refresh_token.?, headers);
var refreshed = try panto.tokensToTokenSet(arena, oauth, toks, now);
// Refresh responses may omit the refresh token / id_token; keep
// the prior values so the session stays renewable.
@@ -144,7 +148,7 @@ pub const AuthManager = struct {
if (oauth.exchange) |exchange| {
if (force or panto.needsExchange(oauth, ts, now, refresh_margin_secs)) {
const access = ts.access_token orelse return Error.LoginRequired;
- const ex = try panto.runExchange(arena, self.client, exchange, access);
+ const ex = try panto.runExchange(arena, self.client, exchange, access, headers);
ts.exchange = ex;
try self.saveToken(name, ts);
}