Skip to content

feat(auth): add Discord as auth provider with guild membership verification#1354

Merged
evanjacobson merged 19 commits intomainfrom
feature/user-profile-connect-social-accounts
Mar 23, 2026
Merged

feat(auth): add Discord as auth provider with guild membership verification#1354
evanjacobson merged 19 commits intomainfrom
feature/user-profile-connect-social-accounts

Conversation

@evanjacobson
Copy link
Contributor

@evanjacobson evanjacobson commented Mar 20, 2026

Summary

  • Add Discord as an OAuth auth provider on the user profile page, using a separate Discord OAuth app (distinct from the existing bot)
  • Add Discord guild membership verification — checks if the user is a member of the Kilo Discord server via the bot API
  • Auto-verify guild membership when a user first links their Discord account; re-verify button available for non-members
  • New DB migration adds discord_server_member and discord_server_member_at columns to kilocode_users

Verification

  • pnpm typecheck — passes
  • pnpm test — passes
  • Link Discord account on profile page
  • Guild membership auto-verifies after linking
  • Re-verify button works for non-members
  • Soft delete nullifies new Discord columns

Visual Changes

New "Discord Server Membership" card on the user profile page showing:

  • Prompt to link Discord if not connected
  • Green checkmark with verification date if user is a Kilo Discord member
  • "Not a member" status with invite link and re-verify button otherwise

Loom (Kilo Team only)

https://www.loom.com/share/3512eb86ef38454d86c95fa7cbfc51f1

Other PRs for this feature

#1356

Reviewer Notes

  • Discord OAuth app env vars (DISCORD_OAUTH_CLIENT_ID, DISCORD_OAUTH_CLIENT_SECRET) are separate from the existing bot token (DISCORD_OAUTH_BOT_TOKEN) — the bot token is used server-side for guild membership checks
  • discord_provider_account_id was intentionally excluded from the getDiscordGuildStatus response to minimize API surface
  • Guild check errors are caught and sanitized to avoid leaking internal details (rate limits, missing env vars) to the client

Add Discord OAuth provider (identify+email) to NextAuth, following
the existing GitHub/GitLab/LinkedIn pattern. Includes DB migration
for discord_server_member tracking columns, GDPR soft-delete coverage,
DiscordLogo component, and provider metadata registration.
Add backend service to check Discord guild membership via Bot API,
tRPC routes for querying/verifying status, and DiscordGuildStatus
UI component on the Connected Accounts page.
Use DISCORD_OAUTH_CLIENT_ID, DISCORD_OAUTH_CLIENT_SECRET, and
DISCORD_OAUTH_BOT_TOKEN for the user-linking OAuth app, keeping
the existing DISCORD_* vars untouched for the bot integration.
When a user lands on /connected-accounts with Discord linked but
never verified, automatically trigger the guild membership check
instead of requiring a manual button click.
…useEffect dependency array. The mutate function is referentially stable, so this resolves the @tanstack/query/no-unstable-deps lint error.
…ider ID from response

Wrap checkDiscordGuildMembership in try/catch to prevent leaking
internal error details (rate limits, missing env vars) to the client.
Remove discord_provider_account_id from getDiscordGuildStatus response
since the client never uses it.
…ame, clear on unlink

- Remove discord_server_member boolean; use discord_server_membership_verified_at
  timestamp alone (non-null = member, null = not verified/not a member)
- Add display_name column to user_auth_provider and store Discord username
- Clear discord_server_membership_verified_at when unlinking Discord
- Regenerate migration (0057) to reflect new schema
…xception

- Remove client-side auto-verify useEffect; verify guild membership
  server-side during account creation and linking instead
- Extract tryVerifyDiscordGuildMembership helper to avoid duplication
- Replace console.error with captureException for Discord API errors
- Simplify DiscordGuildStatus component to be purely declarative
@evanjacobson evanjacobson marked this pull request as ready for review March 21, 2026 01:49
@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 21, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

No new issues found in the incremental diff.

Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
src/lib/integrations/discord-guild-membership.ts 16 Unbounded Discord API call can stall auth flows
src/components/profile/DiscordGuildStatus.tsx N/A Query failures are rendered as "not a member"

Resolved in new commits: the previous src/lib/user.ts error-swallowing concern is addressed by logging Discord verification failures to Sentry.

Files Reviewed (3 files)
  • packages/db/src/migrations/0058_social_connect.sql - 0 issues
  • packages/db/src/migrations/meta/_journal.json - 0 issues
  • src/lib/user.ts - 0 new issues; previous Sentry logging concern resolved

Fix these issues in Kilo Cloud


Reviewed by gpt-5.4-20260305 · 533,150 tokens

… and added an error message when membership check fails
Regenerated drizzle migration as 0058 to resolve collision with
0057_backfill_billing_misclassified from main.
Report caught errors with operation tag and user context instead of
silently swallowing them. Also rename migration 0058 for clarity.
@evanjacobson evanjacobson merged commit e6ec716 into main Mar 23, 2026
18 checks passed
@evanjacobson evanjacobson deleted the feature/user-profile-connect-social-accounts branch March 23, 2026 18:55
emilieschario added a commit that referenced this pull request Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants