Missing Authentication in Chi
How Missing Authentication Manifests in Chi
Missing authentication in Chi-based APIs creates multiple attack vectors that exploit the framework's design patterns. The most common manifestation occurs in Chi's route handler chain, where developers assume middleware will always be present but fail to enforce authentication at the handler level.
Consider a typical Chi router setup:
router := chi.NewRouter()
router.Use(middleware.Logger)
router.Use(middleware.Recoverer)
router.Use(authMiddleware) // Authentication middleware
router.Get("/api/users", listUsersHandler) // Protected endpoint
router.Post("/api/users", createUserHandler) // Protected endpoint
The vulnerability emerges when developers create sub-routers without explicitly inheriting middleware:
adminRouter := chi.NewRouter()
adminRouter.Get("/stats", adminStatsHandler) // No authMiddleware applied!
router.Mount("/admin", adminRouter) // Sub-router mounts without auth
This pattern allows unauthenticated access to /admin/stats because the sub-router doesn't automatically inherit parent middleware. Attackers can exploit this by discovering admin endpoints through directory traversal or brute force.
Another Chi-specific manifestation involves context-based authentication state. Developers often store authentication results in the request context but fail to validate it in every handler:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "user_id", token)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func someHandler(w http.ResponseWriter, r *http.Request) {
// BUG: No context validation
userID := r.Context().Value("user_id")
if userID == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
// Process request...
}
The context-based approach fails when handlers are called directly or when middleware is bypassed through router mounting.
Chi's pattern matching also creates authentication gaps. Wildcard routes like /* or /api/* can inadvertently expose sensitive endpoints if not properly secured:
router.Get("/api/*", catchAllHandler) // May expose admin endpoints
Attackers exploit these gaps by guessing endpoint patterns or using tools that automatically discover API surface areas.
Chi-Specific Detection
Detecting missing authentication in Chi applications requires both static analysis and runtime scanning. The most effective approach combines code review with automated security scanning.
Static analysis should focus on Chi's router configuration patterns. Look for these red flags in your codebase:
// Red flag: Sub-routers without inherited middleware
adminRouter := chi.NewRouter()
adminRouter.Get("/sensitive", sensitiveHandler)
router.Mount("/admin", adminRouter) // No auth middleware
// Red flag: Direct handler assignments without middleware
router.Get("/api/data", directHandler) // No auth check
// Red flag: Context values without validation
func handler(w http.ResponseWriter, r *http.Request) {
if r.Context().Value("user_id") == nil {
// Missing auth check!
}
}
Runtime detection with middleBrick specifically identifies Chi authentication gaps by analyzing the actual HTTP request flow. The scanner tests endpoints without authentication headers and observes responses:
middleBrick Authentication Detection Workflow:
- Scans all discovered endpoints without authentication headers
- Analyzes HTTP status codes and response patterns
- Identifies endpoints that should be protected but respond to unauthenticated requests
- Cross-references discovered endpoints with OpenAPI specifications if available
- Tests for common authentication bypass patterns specific to Go/HTTP frameworks >
The scanner's Chi-specific detection includes testing for:
// What middleBrick tests:
GET /admin/stats HTTP/1.1
Host: example.com
// Should return 401/403 but returns 200 - authentication missing!
GET /api/users HTTP/1.1
Host: example.com
// Should require auth but accessible anonymously
middleBrick also analyzes Chi's context-based authentication patterns by examining how authentication state is propagated through the request chain. The scanner looks for handlers that access context values without proper validation.
For comprehensive coverage, integrate middleBrick into your CI/CD pipeline using the GitHub Action:
name: API Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run middleBrick Scan
run: |
npx middlebrick scan https://your-api.com --output json
continue-on-error: true
- name: Fail on High Risk
run: |
# Parse middleBrick JSON output
# Fail if any critical/high severity authentication issues found
Chi-Specific Remediation
Remediating missing authentication in Chi requires a defense-in-depth approach that combines proper middleware usage, context validation, and endpoint protection patterns.
1. Enforce Authentication at Router Level
The most reliable pattern is to create a protected router that guarantees authentication for all endpoints:
func NewProtectedRouter() *chi.Mux {
router := chi.NewRouter()
router.Use(authMiddleware)
// All routes here are automatically protected
router.Get("/api/users", listUsersHandler)
router.Post("/api/users", createUserHandler)
router.Get("/admin/stats", adminStatsHandler)
return router
}
func main() {
r := chi.NewRouter()
r.Mount("/", NewProtectedRouter())
http.ListenAndServe(":8080", r)
}
This pattern ensures no endpoint can be added without going through the authentication middleware.
2. Context Validation Wrapper
Create a handler wrapper that validates authentication context in every handler:
func RequireAuth(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Validate authentication context
authContext := r.Context().Value("auth_context")
if authContext == nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
// Usage:
router.Get("/api/data", RequireAuth(dataHandler))
3. Sub-Router Authentication Pattern
When using sub-routers, always apply authentication explicitly:
func NewAdminRouter() http.Handler {
router := chi.NewRouter()
router.Use(authMiddleware) // CRITICAL: Apply auth to sub-router
// All admin endpoints automatically protected
router.Get("/stats", adminStatsHandler)
router.Post("/config", updateConfigHandler)
return router
}
func main() {
r := chi.NewRouter()
r.Mount("/admin", NewAdminRouter())
http.ListenAndServe(":8080", r)
}
4. Authentication Failure Detection
Add logging and monitoring to detect authentication bypass attempts:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
log.Printf("auth attempt: missing token from %s", r.RemoteAddr)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
// Validate token...
if !valid {
log.Printf("auth attempt: invalid token from %s", r.RemoteAddr)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
5. Automated Testing
Implement automated tests that verify authentication requirements:
func TestAuthentication(t *testing.T) {
ts := httptest.NewServer(NewProtectedRouter())
defer ts.Close()
// Test unauthenticated access should fail
resp, err := http.Get(ts.URL + "/api/users")
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != http.StatusUnauthorized {
t.Errorf("expected 401, got %d", resp.StatusCode)
}
// Test authenticated access should succeed
req, _ := http.NewRequest("GET", ts.URL + "/api/users", nil)
req.Header.Set("Authorization", "valid-token")
resp, _ = http.DefaultClient.Do(req)
if resp.StatusCode != http.StatusOK {
t.Errorf("expected 200, got %d", resp.StatusCode)
}
}
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |