fix: GitHub integration not showing as connected after App install#608
Conversation
…mbient-code#602) Fix multiple issues preventing GitHub App installations from being reflected as "Connected" in the integrations UI: - Forward OAuth `code` param from GitHub callback to backend for verified ownership via token exchange (reuses existing helpers) - Fix `connectGitHub()` return value: backend returns `message`, not `username` - Fix `GitHubConnectResponse` type to match actual backend response - Fix cache invalidation: mutations now also invalidate `['integrations', 'status']` (used by the Integrations page), not just `['github', 'status']` - Remove `redirect_uri` override from connect URL so GitHub uses the configured Callback URL in App settings - Add debug logging to installation lookup and status queries Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code ReviewSummaryThis PR fixes GitHub App installation integration issues by implementing verified ownership via OAuth code exchange and correcting type mismatches between frontend and backend. The changes are well-structured and follow established patterns, but there are several areas requiring attention before merge. Issues by Severity🚫 Blocker IssuesNone identified - No issues that absolutely prevent merge. 🔴 Critical Issues1. Missing Test Coverage for New OAuth Code Path (
Example test structure needed: It("Should verify ownership when OAuth code is provided", func() {
requestBody := map[string]interface{}{
"installationId": 12345,
"code": "valid-oauth-code",
}
// Mock HTTP responses for OAuth exchange
// Assert ownership verification succeeds
})
It("Should reject installation when user doesn't own it", func() {
requestBody := map[string]interface{}{
"installationId": 12345,
"code": "code-for-different-user",
}
// Assert returns 403 Forbidden
})🟡 Major Issues1. Inconsistent Error Handling Pattern (
if err != nil {
log.Printf("LinkGitHubInstallationGlobal: OAuth code exchange failed for user=%s: %v", userIDStr, err)
// Fall through to best-effort enrichment below
}
if err != nil {
// OAuth exchange is optional - installation can proceed without verification
// for backward compatibility with GitHub App installations that don't use OAuth flow
log.Printf("LinkGitHubInstallationGlobal: OAuth code exchange failed for user=%s: %v", userIDStr, err)
}2. Potential Token Leak via Query Parameters (
const code = url.searchParams.get('code')
const code = url.searchParams.get('code')
// Clear sensitive OAuth code from URL to prevent browser history exposure
if (code) {
window.history.replaceState({}, document.title, url.pathname + '?installation_id=' + installationId)
}3. Type Mismatch Not Fully Corrected (
c.JSON(http.StatusOK, gin.H{
"message": "GitHub App installation linked successfully",
"installationId": installation.InstallationID,
})
export type GitHubConnectResponse = {
message: string;
installationId: number; // ✅ Correct
};
return response.message; // ✅ Correct
🔵 Minor Issues1. Debug Logging Should Use Structured Logging (
log.Printf("getGitHubStatusForUser: querying status for user=%s", userID)
log.Printf("getGitHubStatusForUser: user=%s action=query_status", userID)
2. Cache Invalidation Could Be More Granular (
queryClient.invalidateQueries({ queryKey: ['integrations', 'status'] });
queryClient.invalidateQueries({
queryKey: ['integrations', 'status'],
exact: true // Only invalidate exact match, not partial matches
});
3. Missing Comment on redirect_uri Removal (
// Let GitHub use the Callback URL configured in the App settings
// rather than overriding with redirect_uri (which GitHub ignores
// unless it matches a configured callback URL)
// GitHub App installations redirect to the Callback URL configured in App settings.
// The redirect_uri parameter is ignored by GitHub unless it exactly matches
// a pre-configured callback URL. Since our callback URL is already configured
// in the GitHub App settings, we omit redirect_uri to use the default.
// See: https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-login-with-github-button-with-a-github-appPositive Highlights✅ Excellent Type Safety - Fixed type mismatches between frontend and backend systematically RecommendationsHigh Priority (Before Merge)
Medium Priority (Can Address in Follow-up)
Low Priority (Nice-to-Have)
Code Quality Checklist✅ Follows CLAUDE.md backend patterns Final VerdictApproval Status: This PR solves the core issue effectively and is architecturally sound. The critical missing piece is test coverage for the OAuth verification path, which is a security-critical code change. The other issues are minor and can be addressed quickly. Suggested Actions:
Estimated Time to Address: ~1 hour 🔍 View AI decision process (logs available for 90 days) 📋 View memory system files loaded (click to expand)What Amber Loaded for Code ReviewAmber automatically loaded these repository standards from the memory system:
Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines. |
Fix multiple issues preventing GitHub App installations from being reflected as "Connected" in the integrations UI:
codeparam from GitHub callback to backend for verified ownership via token exchange (reuses existing helpers)connectGitHub()return value: backend returnsmessage, notusernameGitHubConnectResponsetype to match actual backend response['integrations', 'status'](used by the Integrations page), not just['github', 'status']redirect_urioverride from connect URL so GitHub uses the configured Callback URL in App settingsfix #602