Files
Charon/test-results/qa-auth-certificate-test-report.md
GitHub Actions 7624f6fad8 Add QA testing reports for certificate page authentication fixes
- Created detailed QA testing report documenting the authentication issues with certificate endpoints, including test results and root cause analysis.
- Added final QA report confirming successful resolution of the authentication issue, with all tests passing and security verifications completed.
- Included test output logs before and after the fix to illustrate the changes in endpoint behavior.
- Documented the necessary code changes made to the route registration in `routes.go` to ensure proper application of authentication middleware.
2025-12-06 19:34:51 +00:00

10 KiB
Raw Blame History

QA Testing Report: Authentication Fixes for Certificates Page

Date: December 6, 2025 Tester: QA Testing Agent Testing Environment:

  • Backend: Docker container (charon-debug) at localhost:8080
  • Frontend: Production build served by backend
  • Testing Tool: curl with cookie file
  • Browser: Manual verification in Chrome/Chromium with DevTools

Executive Summary

Status: CRITICAL BUG FOUND

Fixes Under Test:

  1. Backend Fix: Removed incorrect user context checks in certificate_handler.go (List, Upload, Delete methods) - ALREADY APPLIED
  2. Frontend Fix: Added withCredentials: true to axios client in client.ts - ALREADY APPLIED

Critical Issue Discovered:

🚨 Certificate routes are NOT protected by authentication middleware!

The certificate endpoints (/api/v1/certificates) are registered OUTSIDE the protected group's closing brace in routes.go, meaning they bypass the AuthMiddleware entirely. This causes all requests to these endpoints to return 401 Unauthorized, even with valid authentication cookies.


Phase 1: Certificate Page Authentication Tests

Status: PASS

Steps:

  1. Register test user via API
  2. Login with test credentials
  3. Inspect cookie file
  4. Verify cookie attributes

Expected Results:

  • User logs in successfully
  • auth_token cookie is present
  • Cookie has HttpOnly, Secure (if HTTPS), SameSite=Strict flags
  • Cookie expiration is 24 hours

Actual Results:

  • Login successful (HTTP 200)
  • auth_token cookie created
  • Cookie details: #HttpOnly_localhost FALSE / FALSE 1765079377 auth_token eyJhbGc...
  • ⚠️ HttpOnly flag confirmed in cookie file
  • Secure and SameSite flags need manual verification in browser DevTools (curl doesn't show these)

Test 1.2: Certificate List (GET /api/v1/certificates)

Status: FAIL

Steps:

  1. Send GET request to /api/v1/certificates with auth cookie
  2. Verify request includes Cookie header
  3. Check response status and body

Expected Results:

  • Page loads without error
  • GET request includes Cookie: auth_token=...
  • Response status: 200 OK (not 401)
  • Certificates are displayed as JSON array

Actual Results:

  • Request DOES include Cookie: auth_token=... (verified with -v flag)
  • Response status: 401 Unauthorized
  • Response body: {"error":"unauthorized"}
  • Certificates are NOT returned

Root Cause Analysis: Using verbose curl, confirmed that the cookie IS being transmitted:

> Cookie: auth_token=eyJhbGci...
< HTTP/1.1 401 Unauthorized
{"error":"unauthorized"}

The cookie is valid (works for /api/v1/auth/me, /api/v1/proxy-hosts, etc.), but /api/v1/certificates specifically returns 401.

Investigation revealed that certificate routes in routes.go are registered OUTSIDE the protected group's closing brace (line 301), so they never receive the AuthMiddleware.


Test 1.3: Certificate Upload (POST /api/v1/certificates)

Status: PENDING

Expected Results:

  • Upload request includes auth cookie
  • Response status: 201 Created
  • Certificate appears in list after upload

Actual Results: Pending test execution...


Test 1.4: Certificate Delete (DELETE /api/v1/certificates/:id)

Status: PENDING

Expected Results:

  • Delete request includes auth cookie
  • Response status: 200 OK
  • Certificate is removed from list
  • Test error case: delete certificate in use (409 Conflict)

Actual Results: Pending test execution...


Test 1.5: Unauthorized Access

Status: PENDING

Expected Results:

  • Direct access to /certificates redirects to login
  • API calls without auth return 401

Actual Results: Pending test execution...


Phase 2: Regression Testing Other Endpoints

Test 2.1: Proxy Hosts Page

Status: PENDING

Test 2.2: Backups Page

Status: PENDING

Test 2.3: Settings Page

Status: PENDING

Test 2.4: User Management

Status: PENDING

Test 2.5: Other Protected Routes

Status: PENDING


Phase 3: Edge Cases and Error Handling

Test 3.1: Token Expiration

Status: PENDING

Test 3.2: Concurrent Requests

Status: PENDING

Test 3.3: Network Errors

Status: PENDING

Test 3.4: Browser Compatibility

Status: PENDING


Phase 4: Development vs Production Testing

Test 4.1: Development Mode

Status: PENDING

Test 4.2: Production Build

Status: PENDING


Phase 5: Security Verification

Status: PENDING

Test 5.2: XSS Protection

Status: PENDING

Test 5.3: CSRF Protection

Status: PENDING


🔍 Root Cause Analysis

The Bug

Certificate routes (GET /POST /DELETE /api/v1/certificates) are returning 401 Unauthorized even with valid authentication cookies.

Investigation Path

  1. Verified frontend fix: withCredentials: true is present in client.ts
  2. Verified backend handler: No user context checks in certificate_handler.go
  3. Tested cookie transmission: Cookies ARE being sent in requests
  4. Tested token validity: Same token works for other endpoints (/auth/me, /proxy-hosts, /backups)
  5. Checked middleware order: Cerberus → Auth → Handler (correct)
  6. Examined route registration: FOUND THE BUG

The Problem

In routes.go, lines 134-301 define the protected group:

protected := api.Group("/")
protected.Use(authMiddleware)
{
    // Many protected routes...
    // ...
} // Line 301 - CLOSING BRACE

BUT the certificate routes are registered AFTER this closing brace:

// Line 305-310: Access Lists (also affected!)
protected.GET("/access-lists/templates", ...)
protected.GET("/access-lists", ...)
// ...

// Line 318-320: Certificates (BUG!)
protected.GET("/certificates", certHandler.List)
protected.POST("/certificates", certHandler.Upload)
protected.DELETE("/certificates/:id", certHandler.Delete)

While these use the protected variable, they're added AFTER the Use(authMiddleware) block closes, so they don't actually get the middleware applied.

Why Other Endpoints Work

  • /api/v1/proxy-hosts: Uses RegisterRoutes(api) which applies its own auth checks
  • /api/v1/backups: Registered INSIDE the protected block (line 142-146)
  • /api/v1/settings: Registered INSIDE the protected block (line 155-162)
  • /api/v1/auth/me: Registered INSIDE the protected block (line 138)

The Fix

Move certificate routes (and access-lists routes) INSIDE the protected block, before line 301.


📊 Test Results Summary

Automated Test Results

Total Tests: 13
✅ Passed: 7
❌ Failed: 2
⚠️  Warnings: 1
⏭️  Skipped: 1

Failing Tests

  1. Certificate List (GET) - 401 Unauthorized (should be 200 OK)
  2. Certificate Upload (POST) - 401 Unauthorized (should be 201 Created)

Passing Tests

  1. Login successful
  2. auth_token cookie created
  3. Cookie transmitted in requests
  4. Unauthorized access properly rejected (without cookie)
  5. Proxy Hosts endpoint works
  6. Backups endpoint works
  7. Settings endpoint works

Warnings

  1. ⚠️ Users endpoint returns 403 Forbidden (expected for non-admin user)

🎯 Overall Assessment

Status: FAIL

The authentication fixes that were supposedly implemented are actually correct:

  • Frontend withCredentials: true is in place
  • Backend handler has no blocking user context checks
  • Cookies are being transmitted correctly

However, a separate architectural bug in route registration prevents the certificate endpoints from receiving authentication middleware, causing them to always return 401 Unauthorized regardless of authentication status.


🔧 Required Fix

File: backend/internal/api/routes/routes.go

Change: Move lines 305-320 (Access Lists and Certificate routes) INSIDE the protected block before line 301.

Before:

protected := api.Group("/")
protected.Use(authMiddleware)
{
    // ... many routes ...
} // Line 301

// Access Lists
protected.GET("/access-lists/templates", ...)
// ...

// Certificate routes
protected.GET("/certificates", certHandler.List)
protected.POST("/certificates", certHandler.Upload)
protected.DELETE("/certificates/:id", certHandler.Delete)

After:

protected := api.Group("/")
protected.Use(authMiddleware)
{
    // ... many routes ...

    // Access Lists
    protected.GET("/access-lists/templates", ...)
    // ...

    // Certificate routes
    protected.GET("/certificates", certHandler.List)
    protected.POST("/certificates", certHandler.Upload)
    protected.DELETE("/certificates/:id", certHandler.Delete)
} // Closing brace AFTER all protected routes

📋 Re-Test Plan

After implementing the fix:

  1. Rebuild Docker container
  2. Re-run automated test script
  3. Verify Certificate List returns 200 OK
  4. Verify Certificate Upload returns 201 Created
  5. Verify Certificate Delete returns 200 OK
  6. Manually test in browser UI

Test Execution Log

Test Script: /projects/Charon/scripts/qa-test-auth-certificates.sh Test Output: /projects/Charon/test-results/qa-auth-test-results.log Execution Time: December 6, 2025 22:49:36 - 22:49:52 (16 seconds)

Key Log Entries

[PASS] Login successful (HTTP 200)
[PASS] auth_token cookie created
[PASS] Request includes auth_token cookie
[FAIL] Authentication failed - 401 Unauthorized (Cookie not being sent or not valid)
[FAIL] Upload authentication failed - 401 Unauthorized (Cookie not being sent)
[PASS] Unauthorized access properly rejected (HTTP 401)
[PASS] Proxy hosts list successful (HTTP 200)
[PASS] Backups list successful (HTTP 200)
[PASS] Settings list successful (HTTP 200)

Container Log Evidence

[GIN] 2025/12/05 - 22:49:37 | 401 |     356.941µs |      172.18.0.1 | GET "/api/v1/certificates"
[GIN] 2025/12/05 - 22:49:37 | 401 |     387.132µs |      172.18.0.1 | POST "/api/v1/certificates"