From 919fc0c66ebc096a44cc8cc4d1683ef5c99b4977 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Thu, 18 Jun 2026 03:30:45 -0500 Subject: [PATCH] Log OAuth code grant failures --- src/atproto/oauth.zig | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/atproto/oauth.zig b/src/atproto/oauth.zig index 65cd496..eeec9fc 100644 --- a/src/atproto/oauth.zig +++ b/src/atproto/oauth.zig @@ -445,20 +445,36 @@ fn authorizationCodeToken(request: *http_api.Request, allocator: std.mem.Allocat const client_id = try requireParam(request, params, allocator, "client_id"); const client_metadata = try fetchClientMetadataForAuth(request, allocator, client_id); try requireClientAuth(request, allocator, params, client_id, client_metadata.value); - const oauth_request = (try store.consumeOAuthCode(allocator, code)) orelse return oauthError(request, .bad_request, "invalid_grant", "Invalid code"); + const oauth_request = (try store.consumeOAuthCode(allocator, code)) orelse { + log.err("oauth code grant invalid_code client={s} code_len={d}\n", .{ client_id, code.len }); + return oauthError(request, .bad_request, "invalid_grant", "Invalid code"); + }; if (!std.mem.eql(u8, redirect_uri, oauth_request.redirect_uri) or !std.mem.eql(u8, client_id, oauth_request.client_id)) { + log.err("oauth code grant mismatch request={s} row_client={s} token_client={s} row_redirect={s} token_redirect={s}\n", .{ oauth_request.request_id, oauth_request.client_id, client_id, oauth_request.redirect_uri, redirect_uri }); return oauthError(request, .bad_request, "invalid_grant", "Mismatched token request"); } if (!try pkceMatches(allocator, code_verifier, oauth_request.code_challenge)) { + log.err("oauth code grant pkce_reject request={s} client={s} verifier_len={d}\n", .{ oauth_request.request_id, client_id, code_verifier.len }); return oauthError(request, .bad_request, "invalid_grant", "Invalid PKCE verifier"); } - const did = oauth_request.sub orelse return oauthError(request, .bad_request, "invalid_grant", "Code was not authorized"); - const account = (try store.findAccount(allocator, did)) orelse return oauthError(request, .bad_request, "invalid_grant", "Account not found"); - const expected_jkt = oauth_request.dpop_jkt orelse return oauthError(request, .bad_request, "invalid_grant", "Authorization request is not DPoP-bound"); + const did = oauth_request.sub orelse { + log.err("oauth code grant unauthorized_code request={s} client={s}\n", .{ oauth_request.request_id, client_id }); + return oauthError(request, .bad_request, "invalid_grant", "Code was not authorized"); + }; + const account = (try store.findAccount(allocator, did)) orelse { + log.err("oauth code grant account_not_found request={s} client={s} did={s}\n", .{ oauth_request.request_id, client_id, did }); + return oauthError(request, .bad_request, "invalid_grant", "Account not found"); + }; + const expected_jkt = oauth_request.dpop_jkt orelse { + log.err("oauth code grant missing_dpop_binding request={s} client={s} did={s}\n", .{ oauth_request.request_id, client_id, did }); + return oauthError(request, .bad_request, "invalid_grant", "Authorization request is not DPoP-bound"); + }; _ = dpop.verifyRequest(allocator, request, null, expected_jkt) catch |err| { + log.err("oauth code grant dpop_reject request={s} client={s} did={s} err={s}\n", .{ oauth_request.request_id, client_id, did, @errorName(err) }); return handleAuthorizationDpopError(request, allocator, err); }; try issueTokenResponse(request, allocator, account, oauth_request.client_id, oauth_request.scope, null, oauth_request.dpop_jkt, oauth_request.auth_method); + log.info("oauth code grant issued request={s} client={s} did={s} auth_method={s}\n", .{ oauth_request.request_id, client_id, did, oauth_request.auth_method orelse "unknown" }); } fn refreshToken(request: *http_api.Request, allocator: std.mem.Allocator, params: anytype) !void { -- 2.51.2