From ad2682c55da8aa5b3a1b461ff1fe3eae5b9f11c3 Mon Sep 17 00:00:00 2001 From: Head of Product & Engineering Date: Mon, 6 Apr 2026 01:15:27 +0200 Subject: [PATCH] fix: guard against empty locationId in OAuth callback and log token fields GHL returns an empty locationId when the user authorizes at agency level instead of selecting a specific sub-account location. Without this guard the token was silently stored under an empty key, making every subsequent webhook fail with "no token for location". Also logs location_id/company_id/user_type from the token response to make future OAuth install debugging easier. Co-Authored-By: Paperclip --- internal/ghl/oauth.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/ghl/oauth.go b/internal/ghl/oauth.go index df05885..2536b2a 100644 --- a/internal/ghl/oauth.go +++ b/internal/ghl/oauth.go @@ -90,6 +90,12 @@ func (h *OAuthHandler) HandleCallback(w http.ResponseWriter, r *http.Request) { return } + if tokenResp.LocationID == "" { + slog.Error("ghl oauth token missing locationId", "company_id", tokenResp.CompanyID, "user_type", tokenResp.UserType) + http.Error(w, "GHL token response did not include a locationId — ensure you selected a sub-account (Location), not an Agency, during authorization", http.StatusBadRequest) + return + } + expiresAt := time.Now().Add(time.Duration(tokenResp.ExpiresIn) * time.Second) record := &store.TokenRecord{ LocationID: tokenResp.LocationID, @@ -196,5 +202,6 @@ func (h *OAuthHandler) postToken(ctx context.Context, data url.Values) (*TokenRe if err := json.Unmarshal(body, &tokenResp); err != nil { return nil, fmt.Errorf("failed to parse token response: %w", err) } + slog.Info("ghl token response fields", "location_id", tokenResp.LocationID, "company_id", tokenResp.CompanyID, "user_type", tokenResp.UserType) return &tokenResp, nil }