atproto pds in zig pds.zat.dev
pds atproto
24

Configure Feed

Select the types of activity you want to include in your feed.

Log OAuth client auth failures

zzstoatzz (May 25, 2026, 11:14 AM -0500) 907e88e9 87363c2c

+17 -4
+17 -4
src/atproto/oauth.zig
··· 1 1 const std = @import("std"); 2 2 const auth = @import("../auth/tokens.zig"); 3 3 const config = @import("../core/config.zig"); 4 + const log = @import("../core/log.zig"); 4 5 const http_api = @import("../http/api.zig"); 5 6 const permission_sets = @import("oauth/permission_sets.zig"); 6 7 const store = @import("../storage/store.zig"); ··· 343 344 } 344 345 345 346 fn requireClientAuth(request: *http.Server.Request, allocator: std.mem.Allocator, params: anytype, client_id: []const u8) !void { 346 - const metadata = fetchJson(allocator, client_id, 256 * 1024) catch { 347 + const metadata = fetchJson(allocator, client_id, 256 * 1024) catch |err| { 348 + log.err("oauth client_auth rejected metadata_fetch_failed client={s} err={s}\n", .{ client_id, @errorName(err) }); 347 349 return oauthError(request, .bad_request, "invalid_client", "Could not fetch client metadata"); 348 350 }; 349 351 const method = zat.json.getString(metadata.value, "token_endpoint_auth_method") orelse "none"; 350 352 if (std.mem.eql(u8, method, "none")) return; 351 353 if (!std.mem.eql(u8, method, "private_key_jwt")) { 354 + log.err("oauth client_auth rejected unsupported_method client={s} method={s}\n", .{ client_id, method }); 352 355 return oauthError(request, .bad_request, "invalid_client", "Unsupported client authentication method"); 353 356 } 354 357 355 358 const assertion_type = try params.value(allocator, "client_assertion_type") orelse { 359 + log.err("oauth client_auth rejected missing_assertion_type client={s}\n", .{client_id}); 356 360 return oauthError(request, .bad_request, "invalid_client", "Missing client assertion type"); 357 361 }; 358 362 if (!std.mem.eql(u8, assertion_type, "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")) { 363 + log.err("oauth client_auth rejected unsupported_assertion_type client={s} type={s}\n", .{ client_id, assertion_type }); 359 364 return oauthError(request, .bad_request, "invalid_client", "Unsupported client assertion type"); 360 365 } 361 366 const assertion = try params.value(allocator, "client_assertion") orelse { 367 + log.err("oauth client_auth rejected missing_assertion client={s}\n", .{client_id}); 362 368 return oauthError(request, .bad_request, "invalid_client", "Missing client assertion"); 363 369 }; 364 - verifyClientAssertion(allocator, metadata.value, client_id, assertion) catch { 370 + verifyClientAssertion(allocator, metadata.value, client_id, assertion) catch |err| { 371 + log.err("oauth client_auth rejected invalid_assertion client={s} err={s}\n", .{ client_id, @errorName(err) }); 365 372 return oauthError(request, .bad_request, "invalid_client", "Invalid client assertion"); 366 373 }; 367 374 } ··· 409 416 const iat = zat.json.getInt(payload.value, "iat"); 410 417 _ = zat.json.getString(payload.value, "jti") orelse return error.InvalidJwt; 411 418 if (!std.mem.eql(u8, iss, client_id) or !std.mem.eql(u8, sub, client_id)) return error.InvalidJwt; 412 - if (!std.mem.eql(u8, aud, config.publicUrl())) return error.InvalidJwt; 413 - if (!clientAssertionTimestampIsFresh(now(), exp, iat)) return error.InvalidJwt; 419 + if (!std.mem.eql(u8, aud, config.publicUrl())) { 420 + log.err("oauth client_assertion aud_mismatch client={s} aud={s} expected={s}\n", .{ client_id, aud, config.publicUrl() }); 421 + return error.AudienceMismatch; 422 + } 423 + if (!clientAssertionTimestampIsFresh(now(), exp, iat)) { 424 + log.err("oauth client_assertion stale client={s} exp={?d} iat={?d} now={d}\n", .{ client_id, exp, iat, now() }); 425 + return error.StaleClientAssertion; 426 + } 414 427 415 428 const jwks_uri = zat.json.getString(metadata, "jwks_uri") orelse return error.InvalidClientMetadata; 416 429 const jwks_doc = try fetchJson(allocator, jwks_uri, 256 * 1024);