Skip to main content

Admin Credit Config Page - Authentication Fix

Date: January 4, 2025 Issue: Admin Credit Config page failing to load with authentication error Status: ✅ FIXED


Problem Description

When navigating to the Credit Config page in the admin app, the following error occurred:

Error fetching configurations: Error: Failed to fetch configurations

Backend logs showed:

[ClerkAuthGuard] Token verification failed: Not Found

Root Cause Analysis

Issue #1: Wrong Endpoint

The admin page was calling the user endpoint instead of the admin endpoint:

  • ❌ Called: GET /credits/config
  • ✅ Should call: GET /admin/credits/config

Issue #2: Missing Admin Endpoint

The admin credit controller had a PUT /admin/credits/config endpoint for updating configurations, but no GET endpoint for fetching them.

Issue #3: Wrong Authentication Guard

The admin credit controller was using ClerkAuthGuard which validates tokens against CLERK_SECRET_KEY (for regular users), but the admin app uses a separate Clerk instance with ADMIN_CLERK_SECRET_KEY.

Why This Happened

  1. When we updated the admin page to prevent creating/deleting configurations, we didn't update the fetch endpoint to use the admin route.
  2. The admin credit controller was incorrectly using the user authentication guard instead of the admin authentication guard.

Solution Implemented

1. Fixed Authentication Guard ⭐ CRITICAL FIX

File: apps/backend/src/admin/admin-credit.controller.ts

Problem: The admin controller was using ClerkAuthGuard which validates tokens against CLERK_SECRET_KEY (for regular users), but the admin app uses a separate Clerk instance with ADMIN_CLERK_SECRET_KEY.

Changed:

// Before
import { ClerkAuthGuard } from '../auth/clerk-auth.guard';
@UseGuards(ClerkAuthGuard)

// After
import { AdminClerkAuthGuard } from '../auth/admin-clerk-auth.guard';
@UseGuards(AdminClerkAuthGuard)

This ensures admin tokens are validated against the correct Clerk instance.

2. Added GET Endpoint to Admin Controller

File: apps/backend/src/admin/admin-credit.controller.ts

Added:

/**
* Get all credit configurations
*/
@Get('config')
@ApiOperation({ summary: 'Get all credit configurations' })
@ApiResponse({
status: 200,
description: 'Credit configurations retrieved successfully',
})
async getCreditConfiguration() {
try {
const config = await this.creditService.getCreditConfiguration();
this.logger.log('Credit configurations retrieved for admin');
return config;
} catch (error) {
this.logger.error(
`Failed to get credit configurations: ${error.message}`,
);
throw error;
}
}

3. Updated Admin Page Endpoint

File: apps/admin/app/credit-config/page.tsx

Changed:

// Before
const response = await fetch(apiUrl("credits/config"), {

// After
const response = await fetch(apiUrl("admin/credits/config"), {

This ensures the admin page calls the admin endpoint instead of the user endpoint.


API Endpoint Overview

User Endpoints (Authenticated Users)

  • GET /credits/config - Get credit configurations (for regular users)
  • GET /credits/balance - Get user's credit balance
  • GET /credits/history - Get user's credit transaction history
  • GET /credits/statistics - Get user's credit statistics

Admin Endpoints (Admin Users)

  • GET /admin/credits/configNEW - Get all credit configurations
  • PUT /admin/credits/config - Update credit configuration
  • GET /admin/credits/startups - Get all startups with credits
  • POST /admin/credits/startups/:id/add - Add credits to startup
  • POST /admin/credits/startups/:id/deduct - Deduct credits from startup
  • And many more admin operations...

Testing

Type Checks

✅ Backend: pnpm --filter=@civstart/backend typecheck
✅ Admin: pnpm --filter=@civstart/admin typecheck

Expected Behavior After Fix

  1. Admin navigates to Credit Config page

    • ✅ Page loads without errors
    • ✅ Shows loading state
    • ✅ Token is sent with request
  2. Backend receives request

    • GET /admin/credits/config with valid Clerk token
    • ✅ ClerkAuthGuard validates token
    • ✅ Returns 5 credit configurations
  3. Admin page displays data

    • ✅ Shows 5 credit configuration cards
    • ✅ Each card shows: Action Type, Credit Cost, Description, Status
    • ✅ Edit functionality works
    • ✅ Toggle activation works

Security Considerations

Authentication & Authorization

Both endpoints are protected by ClerkAuthGuard:

  1. User Endpoint (/credits/config)

    • Requires valid Clerk token
    • Any authenticated user can access
    • Returns same data (configurations are not sensitive)
  2. Admin Endpoint (/admin/credits/config)

    • Requires valid Clerk token
    • Should also verify admin role (recommendation)
    • Currently relies on URL obscurity and frontend routing

Recommendation: Add Admin Role Check

Consider adding an admin role guard to all /admin/* endpoints:

@UseGuards(ClerkAuthGuard, AdminRoleGuard)

This would ensure that even if someone discovers the admin endpoints, they cannot access them without admin privileges.


Files Modified

  1. apps/backend/src/admin/admin-credit.controller.ts

    • Added GET endpoint for credit configurations
  2. apps/admin/app/credit-config/page.tsx

    • Updated fetch call to use admin endpoint

Deployment Notes

Backend Changes

The backend change adds a new endpoint, so no breaking changes. The backend should be restarted to pick up the new endpoint:

# If running locally
pnpm dev:backend

# If using PM2 in production
pm2 restart civstart-backend

Frontend Changes

The frontend change updates the API call. The admin app should be redeployed:

# Vercel will auto-deploy on git push
# Or manually trigger deployment in Vercel dashboard

Verification Steps

Once deployed, verify the fix:

  1. Login to admin app

    Navigate to: https://admin.civstart.ventures/credit-config
    Or locally: http://localhost:3002/credit-config
  2. Check console for errors

    • Should see no fetch errors
    • Should see successful API call to /admin/credits/config
  3. Verify data loads

    • Should display 5 credit configurations:
      • signal_pool_request (10 credits)
      • connection_request (15 credits)
      • signal_view_details (5 credits)
      • warm_intro_request (20 credits)
      • priority_matching (25 credits)
  4. Test edit functionality

    • Click "Edit" on a configuration
    • Change credit cost
    • Click "Save Changes"
    • Verify success message appears
    • Verify changes persist after page refresh


Summary

Fixed: Admin Credit Config page authentication error ✅ Added: GET endpoint to admin credit controller ✅ Updated: Admin page to use correct endpoint ✅ Tested: Type checks pass for both backend and admin ✅ Ready: For deployment and testing

The admin Credit Config page should now load correctly and display all 5 credit configurations.


Fix completed successfully.