feat: Add API key regenerate/revoke from admin dashboard#15
Conversation
Adds admin-level key management that uses session authentication,
solving the chicken-and-egg problem where you needed an API key
to regenerate your API key.
Changes:
- Add POST /admin/api-keys/{key_id}/regenerate endpoint
- Add POST /admin/api-keys/{key_id}/revoke endpoint
- Add Regenerate/Revoke action buttons to API Keys table
- Add confirmation modals with warnings about key invalidation
- Show new key once after regeneration with copy button
- Add partial templates for success/revoked states
Stu Mason + AI <me@stumason.dev>
Pull Request Review: API Key Regenerate/Revoke from Admin DashboardSummaryThis PR adds admin-level API key management functionality, solving a chicken-and-egg problem where users needed an API key to manage API keys. The implementation adds two new endpoints that use session-based admin authentication instead of API key authentication. Detailed Analysis1. Security ReviewStrengths:
Concerns:
2. Code Quality IssuesCritical:
Important: 3. Style & Consistency
4. Functional ReviewUI/UX Strengths:
Edge Cases Covered:
Edge Cases Missing:
5. Testing ConcernsNo automated tests for new endpoints. Should add:
6. RecommendationsRequired Changes:
Suggested Improvements: Recommendation: Request ChangesThis is a valuable feature with good implementation, but the multi-tenant authorization check is critical before merge. The security model is sound otherwise. |
- Add "Create API Key" button for when no keys exist - Add "Create New Key" button in header when all keys are revoked - Add POST /admin/api-keys/create endpoint for creating keys - Exclude /admin/api-keys/ from CSRF (uses session auth) - Add CSRF token to fetch requests for key management Stu Mason + AI <me@stumason.dev>
BREAKING CHANGE: API endpoints now ALWAYS require authentication. Previously, if no API_KEY env var was set, all data endpoints were publicly accessible. This was a dangerous default for health data. Now authentication is required regardless of configuration: - Use X-API-Key header with a per-user key (from OAuth flow) - Or use X-API-Key header with the master API_KEY (if configured) This ensures health data is never accidentally exposed publicly. Stu Mason + AI <me@stumason.dev>
Pull Request ReviewThis PR adds API key management from the admin dashboard. Overall well-designed but has critical security issues. CRITICAL Security Issues
Other Issues
Positive Aspects
Minor Issues
Recommendation: REQUEST CHANGESFix critical issues 1-3 before merging. The feature is well-designed but security must be addressed. Files reviewed:
|
Pull Request Review: API Key Management from Admin DashboardSummaryThis PR adds admin-level API key management (regenerate, revoke, create) using session authentication. It solves the chicken-and-egg problem where API keys were needed to manage API keys. The implementation includes UI buttons, confirmation modals, CSRF protection, and proper success/error feedback. Detailed Analysis1. Security Analysis✅ Strengths
|
- Fix ruff formatting in routes.py - Add confirmation dialog before closing modal if key not copied - Update README to reflect that API auth is always required - Remove references to old "open access" mode Stu Mason + AI <me@stumason.dev>
The api_key_guard function (currently unused) still had the old insecure behavior that skipped auth when no API_KEY was configured. Removed this to prevent future accidents and ensure consistency. Stu Mason + AI <me@stumason.dev>
Pull Request Review: API Key Management from Admin DashboardSummaryThis PR adds admin dashboard functionality for managing API keys (create, regenerate, revoke) without requiring an API key for authentication. This solves a critical UX problem where users needed an API key to manage their API keys (chicken-and-egg problem). Overall Assessment: REQUEST CHANGES While the feature implementation is solid, there are several security concerns and potential bugs that should be addressed before merging. Security Issues🔴 Critical: Missing Authorization Check on Key OperationsLocation: The regenerate/revoke/create endpoints check authentication (
Fix needed: # In admin_regenerate_api_key, admin_revoke_api_key
# After fetching api_key, before operating on it:
if not api_key:
return Template(...)
# Get the authenticated user's polar_user_id from session
stmt = select(User).where(User.is_active == True).limit(1)
result = await session.execute(stmt)
user = result.scalar_one_or_none()
if user and api_key.user_id != user.polar_user_id:
return Template(
template_name="admin/partials/sync_error.html",
context={"error": "You don't have permission to modify this API key."}
)Note: This is currently low-risk in self-hosted mode (single user) but becomes critical if DEPLOYMENT_MODE=saas is ever used. 🟡 Medium: Error Template ReuseLocation: The endpoints reuse Recommendation: Create a generic 🟡 Medium: XSS Risk in Error MessagesLocation: Exception messages are directly interpolated into templates without escaping: context={"error": f"Failed to regenerate key: {str(e)}"}If an exception contains user-controlled data (unlikely but possible), this could lead to XSS. Jinja2 auto-escapes by default, but it's best practice to sanitize error messages shown to users. Recommendation: Use generic error messages or explicitly escape exceptions. Bugs & Logic Errors🔴 High: Race Condition in Create API KeyLocation: The check for existing active keys and creation are not atomic: key_result = await session.execute(key_stmt)
existing_key = key_result.scalar_one_or_none()
if existing_key:
return Template(...)
# Race window here - another request could create a key
api_key, raw_key = await create_api_key_for_user(...)If a user clicks "Create API Key" twice rapidly, they could end up with two keys. Fix: Add a unique constraint in the database (one active key per user) OR use a database lock/transaction isolation level. 🟡 Medium: Inconsistent Key Limit LogicLocation: The create endpoint prevents creating a second key if one exists: if existing_key:
return Template(..., context={"error": "User already has an active API key..."})But the UI only shows the "Create New Key" button when
Fix: Update the query to check for key_stmt = select(APIKey).where(
APIKey.user_id == user.polar_user_id,
APIKey.is_active == True, # Already correct
)And update UI logic at line 306 to match. 🟢 Low: Copy Confirmation UX IssueLocation: The
Recommendation: Reset Code Style & Quality✅ Good: CSRF ProtectionThe JavaScript correctly includes CSRF tokens: headers: {
'X-CSRF-Token': getCsrfToken(),
}And the routes are properly excluded from CSRF on admin session routes (app.py:244). ✅ Good: Session vs API Key Auth SeparationThe admin routes correctly use session authentication ( ✅ Good: Test CoverageExisting tests in Recommendation: Add integration tests for the new admin endpoints to test the full flow including:
🟡 Code DuplicationLocation: The three endpoints share similar structure:
Recommendation: Extract common patterns into helper functions to reduce duplication and improve maintainability. Documentation✅ Good: README UpdatesThe README.md correctly documents the new authentication requirements and removes the misleading "Open Access" option. 🟡 Missing: Revoke Recovery InstructionsLocation: The revoke success message says "reconnect via OAuth to generate a new key" but this isn't accurate - users can click "Create API Key" button (if implemented correctly per bug above). Recommendation: Update message to: "To restore access, create a new API key from the dashboard." Testing RecommendationsBefore merging, please test:
Positive Aspects
Required Changes
Optional Improvements
Recommendation: Request changes for security and bug fixes before merging. |
Pull Request ReviewSummaryThis PR adds admin dashboard functionality for managing API keys (create, regenerate, revoke) using session authentication instead of API key authentication. This solves the chicken-and-egg problem where users needed an API key to regenerate their API key. Detailed Analysis1. Security Issues 🔴Critical: CSRF Protection Verification NeededLocation: src/polar_flow_server/admin/routes.py:46-219 The new endpoints use CSRF tokens in the JavaScript client:
Recommendation: Test that CSRF protection is working correctly for these endpoints. XSS Prevention - Good ImplementationLocation: src/polar_flow_server/templates/admin/dashboard.html:403-407 ✅ GOOD: Uses .textContent instead of .innerHTML, which prevents XSS Potential IDOR (Insecure Direct Object Reference)Location: src/polar_flow_server/admin/routes.py:64-73 For future SaaS mode: This could allow one user to regenerate/revoke another user's keys by guessing key IDs. Recommendation: Add authorization check after fetching the api_key to verify ownership or admin status. 2. Logic & Bug Issues 🟡Prevents Multiple API Keys Per UserLocation: src/polar_flow_server/admin/routes.py:183-195 The admin_create_api_key endpoint checks if a user already has an active key and rejects creation. This prevents users from having multiple API keys, which may be a legitimate use case (e.g., different keys for different applications). Recommendation: Either:
Error Handling May Expose Sensitive InformationLocation: src/polar_flow_server/admin/routes.py:94-99, 148-153, 214-219 Recommendation:
Minor: keyWasCopied State ManagementLocation: src/polar_flow_server/templates/admin/dashboard.html:541-548 ✅ GOOD: Warns users before closing without copying Recommendation: Reset keyWasCopied = false when opening modals, not just when closing. 3. Code Style & Consistency ✅Consistent with Codebase Patterns
Good Practices
Documentation
4. Improvements & Suggestions 💡Add Tests - HIGH PRIORITYNo tests were added for the new endpoints. Given that these handle security-critical operations (API key management), tests are essential. Recommendation: Add tests for:
Better UX for Key Prefix DisplayLocation: src/polar_flow_server/templates/admin/dashboard.html:322-367 The old prefix is shown in the modal when regenerating, which might confuse users since the prefix will change. Recommendation: Update modal text to clarify that the new key will have a different prefix. Add Audit Logging - MEDIUM PRIORITYAPI key operations (create, regenerate, revoke) are security-sensitive and should be logged for audit trails. Modal AccessibilityThe modals don't have ARIA attributes for accessibility. Recommendation: Add role="dialog", aria-modal="true", aria-labelledby attributes. Make Key Name EditableCurrently auto-generated. Consider allowing users to provide custom names like "Production Server" or "Local Dev". 5. Breaking Changes
|
Pull Request Review: API Key Management from Admin DashboardSummaryThis PR adds admin panel functionality for creating, regenerating, and revoking API keys without requiring API key authentication. This solves the chicken-and-egg problem where users needed an API key to manage their API keys. The implementation uses session-based admin authentication with CSRF protection and provides a clean UI with confirmation modals. Security Analysis✅ Strengths
|
- Reset keyWasCopied flag in confirmRegenerate() and confirmCreateKey() to prevent false copy warnings when generating multiple keys - Update revoke message to reference dashboard instead of OAuth - Add auth model comment explaining admin vs per-key authorization Stu Mason + AI <me@stumason.dev>
Pull Request Review - API Key ManagementSummaryThis PR adds admin-level API key management functionality (create, regenerate, revoke) via the admin dashboard using session-based authentication. This solves the chicken-and-egg problem where users needed an API key to manage their API keys. 1. Security Analysis 🔒✅ Strengths
|
Summary
Changes
POST /admin/api-keys/{key_id}/regenerate- regenerate a key from admin panelPOST /admin/api-keys/{key_id}/revoke- revoke a key from admin panelTest plan
Stu Mason + AI me@stumason.dev