Skip to content

Make CORS origins configurable instead of hardcoded#282

Open
prempalhade3-code wants to merge 5 commits intoAOSSIE-Org:mainfrom
prempalhade3-code:cors-configurable
Open

Make CORS origins configurable instead of hardcoded#282
prempalhade3-code wants to merge 5 commits intoAOSSIE-Org:mainfrom
prempalhade3-code:cors-configurable

Conversation

@prempalhade3-code
Copy link

@prempalhade3-code prempalhade3-code commented Jan 29, 2026

This PR removes the hardcoded frontend origin and makes CORS origins
configurable via backend configuration.

Existing local development behavior is preserved by falling back to the
previous default when no configuration is provided.

Summary by CodeRabbit

  • New Features

    • Configurable CORS with automatic localhost fallback for development
  • Bug Fixes

    • Stricter configuration validation with clearer startup errors
    • Improved server startup logging and Redis initialization handling
  • Chores

    • Streamlined route and server initialization
    • Updated repository ignore rules (DS_Store/.zip added, .env ignore removed)

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 29, 2026

📝 Walkthrough

Walkthrough

The pull request updates backend startup and configuration: adds config validation and CORS AllowedOrigins, changes config load error handling, conditionally initializes Redis, simplifies router setup by removing various route registrations and WebSocket signaling endpoints, adjusts .gitignore, and removes two no-op loops in tests.

Changes

Cohort / File(s) Summary
Configuration
backend/config/config.go
Added CORS.AllowedOrigins field and validateConfig(); LoadConfig now validates required fields (server.port, database.uri, jwt.secret, Gemini.apiKey, googleOAuth.clientID) and rejects invalid CORS entries.
Server startup & routing
backend/cmd/server/main.go
Replaced panic-on-config with log.Fatalf; conditional Redis initialization using cfg.Redis.Addr and debate.InitRedis; dynamic CORS origins from config with http://localhost:5173 default; removed numerous route registrations, WebSocket signaling endpoints, and related log statements; retained room-watcher/goroutine startup.
Version control
.gitignore
Removed *.env from ignores and added *.env.DS_Store and *.zip entries.
Tests / small cleanup
backend/test_server.go
Removed two empty for-range loops over the matchmaking pool (no-op removal).
Manifest
go.mod
Modifications reflected (lines changed), indicating dependency adjustments alongside server changes.

Sequence Diagram(s)

sequenceDiagram
    participant DevClient as Client
    participant Server as Backend Server
    participant Mongo as MongoDB
    participant Redis as Redis (optional)
    participant Debate as debate package

    DevClient->>Server: HTTP request / ws connect
    Server->>Server: LoadConfig -> validateConfig
    alt config invalid
        Server-->>DevClient: Fail startup (log.Fatalf)
    else config valid
        Server->>Mongo: Connect to DB
        Mongo-->>Server: DB OK
        alt cfg.Redis.Addr set
            Server->>Redis: Init connection (debate.InitRedis)
            Redis-->>Server: OK / warn on failure
            Server->>Debate: Enable Redis-backed features
        else no Redis
            Server-->>Server: Log Redis unavailable
        end
        Server->>Server: Configure CORS origins
        Server->>Server: Register simplified routes and start room watcher
        Server-->>DevClient: Serve responses / websockets
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I hopped through configs, tidy and spry,
Removed the noise, let Redis reply,
CORS now listens where origins play,
Routes trimmed neat to greet the day,
A rabbit's cheer for startup sway! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Make CORS origins configurable instead of hardcoded' accurately describes the main change: converting hardcoded CORS origins to configurable settings via backend configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.gitignore:
- Around line 3-4: The .gitignore entry '*.env.DS_Store' only matches files
literally ending with '.env.DS_Store'; replace it with a proper macOS ignore
like '.DS_Store' or '**/.DS_Store' so typical .DS_Store files are ignored (edit
the .gitignore line containing '*.env.DS_Store' to '.DS_Store' or
'**/.DS_Store').

In `@backend/config/config.go`:
- Around line 100-118: Extend validateConfig to validate CORS origins: for
cfg.CORS.AllowedOrigins iterate each origin (trim whitespace) and return an
error if any origin is empty, equals "*" while cfg.CORS.AllowCredentials is
true, or does not start with "http://" or "https://"; ensure you reference the
cfg.CORS.AllowedOrigins slice and cfg.CORS.AllowCredentials flag in the checks
so invalid configurations are rejected.

Comment on lines +3 to +4
*.env.DS_Store
*.zip
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential typo in the .DS_Store ignore pattern.

*.env.DS_Store only matches filenames ending with .env.DS_Store. If the goal is to ignore macOS .DS_Store files, consider using .DS_Store (optionally with **/.DS_Store).

🔧 Proposed fix
-*.env.DS_Store
+.DS_Store
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
*.env.DS_Store
*.zip
.DS_Store
*.zip
🤖 Prompt for AI Agents
In @.gitignore around lines 3 - 4, The .gitignore entry '*.env.DS_Store' only
matches files literally ending with '.env.DS_Store'; replace it with a proper
macOS ignore like '.DS_Store' or '**/.DS_Store' so typical .DS_Store files are
ignored (edit the .gitignore line containing '*.env.DS_Store' to '.DS_Store' or
'**/.DS_Store').

Comment on lines 100 to 118
func validateConfig(cfg *Config) error {

if cfg.Server.Port == 0 {
return fmt.Errorf("server.port is required")
}
if cfg.Database.URI == "" {
return fmt.Errorf("database.uri is required")
}
if cfg.JWT.Secret == "" {
return fmt.Errorf("jwt.secret is required")
}
if cfg.Gemini.ApiKey == "" {
return fmt.Errorf("gemini.apiKey is required")
}
if cfg.GoogleOAuth.ClientID == "" {
return fmt.Errorf("googleOAuth.clientID is required")
}

return nil
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "config.go" -o -name "main.go" -o -name "router.go" | head -20

Repository: AOSSIE-Org/DebateAI

Length of output: 182


🏁 Script executed:

git ls-files | grep -E "(config|router)" | grep "\.go$"

Repository: AOSSIE-Org/DebateAI

Length of output: 87


🏁 Script executed:

cat -n backend/config/config.go

Repository: AOSSIE-Org/DebateAI

Length of output: 3525


🏁 Script executed:

find . -type f -name "*.go" | xargs grep -l "gin-contrib/cors\|AllowCredentials" | head -10

Repository: AOSSIE-Org/DebateAI

Length of output: 91


🏁 Script executed:

cat -n backend/cmd/server/main.go

Repository: AOSSIE-Org/DebateAI

Length of output: 5875


🏁 Script executed:

grep -r "AllowCredentials" backend/ --include="*.go" -B 2 -A 2

Repository: AOSSIE-Org/DebateAI

Length of output: 415


🌐 Web query:

CORS specification wildcard origin AllowCredentials true invalid

💡 Result:

Per the CORS/FETCH rules, you cannot combine:

  • Access-Control-Allow-Origin: * (wildcard) and
  • Access-Control-Allow-Credentials: true (allow cookies/HTTP auth/client certs)

If you do, browsers will treat the response as invalid for credentialed CORS and block access (you’ll typically see an error like “Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’”). [1], [2]

What to do instead

If you need credentials (cookies/auth):

  • Return a single, explicit origin (often by echoing the request’s Origin if it’s in your allowlist), e.g. Access-Control-Allow-Origin: https://app.example
  • Keep Access-Control-Allow-Credentials: true
  • Add Vary: Origin when you dynamically reflect origins to avoid cache issues. [2], [3]

If you want to allow any site (*):

  • Do not send Access-Control-Allow-Credentials: true, and ensure the client does not use credentials: "include" / withCredentials=true. [1], [2]

Sources:
[1] MDN: “Credential is not supported if the CORS header ‘Access-Control-Allow-Origin’ is ‘*’” https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors/CORSNotSupportingCredentials
[2] MDN: Access-Control-Allow-Origin (wildcard + credentials errors) https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
[3] MDN: handling multiple origins + Vary: Origin guidance https://developer.mozilla.org/docs/Web/HTTP/Guides/CORS/Errors/CORSMissingAllowOrigin


🌐 Web query:

gin-contrib/cors AllowCredentials true wildcard "*" behavior compliance

💡 Result:

In CORS, you cannot use Access-Control-Allow-Origin: * together with Access-Control-Allow-Credentials: true. For credentialed requests (cookies / HTTP auth / client certs), the server must return an explicit origin (and typically Vary: Origin); if it returns *, browsers will block access to the response and Set-Cookie won’t work. (developer.mozilla.org)

What gin-contrib/cors does / expects

gin-contrib/cors documents this as a restriction:

  • AllowAllOrigins (effectively “*”) means credentials cannot be used / “allowing all origins disables cookies.” (github.com)
  • AllowCredentials is intended only when you use precise origins (not all origins / wildcard). (github.com)

Compliance-safe configuration

To be compliant while allowing credentials:

  • Do not use AllowAllOrigins = true or AllowOrigins = []string{"*"}.
  • Instead, whitelist explicit origins (or implement AllowOriginFunc) and keep AllowCredentials = true. (github.com)

Citations:


Add CORS origin validation to prevent invalid configurations.

The router is configured with AllowCredentials: true (line 88, backend/cmd/server/main.go), but the config validator does not check cors.allowedOrigins. Per the CORS specification, combining a wildcard origin ("*") with credential support is invalid and will cause browsers to reject credentialed requests. Add validation to reject:

  • Wildcard "*" when AllowCredentials is true
  • Empty or whitespace-only origins
  • Origins without a scheme (http:// or https://)
Proposed validation additions
 import (
 	"fmt"
 	"os"
+	"strings"

 	"gopkg.in/yaml.v3"
 )
 func validateConfig(cfg *Config) error {
 	if cfg.Server.Port == 0 {
 		return fmt.Errorf("server.port is required")
 	}
 	if cfg.Database.URI == "" {
 		return fmt.Errorf("database.uri is required")
 	}
 	if cfg.JWT.Secret == "" {
 		return fmt.Errorf("jwt.secret is required")
 	}
 	if cfg.Gemini.ApiKey == "" {
 		return fmt.Errorf("gemini.apiKey is required")
 	}
 	if cfg.GoogleOAuth.ClientID == "" {
 		return fmt.Errorf("googleOAuth.clientID is required")
 	}
+	for i, origin := range cfg.CORS.AllowedOrigins {
+		if strings.TrimSpace(origin) == "" {
+			return fmt.Errorf("cors.allowedOrigins[%d] is empty", i)
+		}
+		if origin == "*" {
+			return fmt.Errorf("cors.allowedOrigins cannot include '*' when allowCredentials is true")
+		}
+		if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
+			return fmt.Errorf("cors.allowedOrigins[%d] must include scheme", i)
+		}
+	}
 
 	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func validateConfig(cfg *Config) error {
if cfg.Server.Port == 0 {
return fmt.Errorf("server.port is required")
}
if cfg.Database.URI == "" {
return fmt.Errorf("database.uri is required")
}
if cfg.JWT.Secret == "" {
return fmt.Errorf("jwt.secret is required")
}
if cfg.Gemini.ApiKey == "" {
return fmt.Errorf("gemini.apiKey is required")
}
if cfg.GoogleOAuth.ClientID == "" {
return fmt.Errorf("googleOAuth.clientID is required")
}
return nil
func validateConfig(cfg *Config) error {
if cfg.Server.Port == 0 {
return fmt.Errorf("server.port is required")
}
if cfg.Database.URI == "" {
return fmt.Errorf("database.uri is required")
}
if cfg.JWT.Secret == "" {
return fmt.Errorf("jwt.secret is required")
}
if cfg.Gemini.ApiKey == "" {
return fmt.Errorf("gemini.apiKey is required")
}
if cfg.GoogleOAuth.ClientID == "" {
return fmt.Errorf("googleOAuth.clientID is required")
}
for i, origin := range cfg.CORS.AllowedOrigins {
if strings.TrimSpace(origin) == "" {
return fmt.Errorf("cors.allowedOrigins[%d] is empty", i)
}
if origin == "*" {
return fmt.Errorf("cors.allowedOrigins cannot include '*' when allowCredentials is true")
}
if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
return fmt.Errorf("cors.allowedOrigins[%d] must include scheme", i)
}
}
return nil
}
🤖 Prompt for AI Agents
In `@backend/config/config.go` around lines 100 - 118, Extend validateConfig to
validate CORS origins: for cfg.CORS.AllowedOrigins iterate each origin (trim
whitespace) and return an error if any origin is empty, equals "*" while
cfg.CORS.AllowCredentials is true, or does not start with "http://" or
"https://"; ensure you reference the cfg.CORS.AllowedOrigins slice and
cfg.CORS.AllowCredentials flag in the checks so invalid configurations are
rejected.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@backend/config/config.go`:
- Around line 118-127: The loop over cfg.CORS.AllowedOrigins currently trims
origin for the empty-value check but uses the untrimmed origin for the wildcard
and scheme checks; update the code to store the trimmed value (e.g.,
trimmedOrigin := strings.TrimSpace(origin)) and use trimmedOrigin for all
subsequent checks, and change the wildcard error text from "cors.allowedOrigins
cannot contain '*' when credentials are enabled" to remove the conditional
wording (e.g., "cors.allowedOrigins cannot contain '*'") since credentials are
always enabled.

Comment on lines +118 to +127
for _, origin := range cfg.CORS.AllowedOrigins {
if strings.TrimSpace(origin) == "" {
return fmt.Errorf("cors.allowedOrigins cannot contain empty values")
}
if origin == "*" {
return fmt.Errorf("cors.allowedOrigins cannot contain '*' when credentials are enabled")
}
if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
return fmt.Errorf("cors.allowedOrigins must include scheme")
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for CORS-related configuration and AllowCredentials
rg -n "AllowCredentials|cors\\.Config|AllowedOrigins|CORSConfig|CORS" backend --type go -A 3 -B 3

Repository: AOSSIE-Org/DebateAI

Length of output: 1933


Remove conditional language from wildcard validation error; align trimmed origin usage across all checks.
Credentials are hardcoded to AllowCredentials: true in the CORS middleware (backend/cmd/server/main.go:88), making the error message "when credentials are enabled" misleading—the condition is always true at runtime. Additionally, use the trimmed origin consistently for the scheme check to avoid false positives on whitespace-padded values.

🛠️ Suggested fix
	for _, origin := range cfg.CORS.AllowedOrigins {
+		trimmed := strings.TrimSpace(origin)
-		if strings.TrimSpace(origin) == "" {
+		if trimmed == "" {
 			return fmt.Errorf("cors.allowedOrigins cannot contain empty values")
 		}
-		if origin == "*" {
-			return fmt.Errorf("cors.allowedOrigins cannot contain '*' when credentials are enabled")
+		if trimmed == "*" {
+			return fmt.Errorf("cors.allowedOrigins cannot contain '*'")
 		}
-		if !strings.HasPrefix(origin, "http://") && !strings.HasPrefix(origin, "https://") {
+		if !strings.HasPrefix(trimmed, "http://") && !strings.HasPrefix(trimmed, "https://") {
 			return fmt.Errorf("cors.allowedOrigins must include scheme")
 		}
 	}
🤖 Prompt for AI Agents
In `@backend/config/config.go` around lines 118 - 127, The loop over
cfg.CORS.AllowedOrigins currently trims origin for the empty-value check but
uses the untrimmed origin for the wildcard and scheme checks; update the code to
store the trimmed value (e.g., trimmedOrigin := strings.TrimSpace(origin)) and
use trimmedOrigin for all subsequent checks, and change the wildcard error text
from "cors.allowedOrigins cannot contain '*' when credentials are enabled" to
remove the conditional wording (e.g., "cors.allowedOrigins cannot contain '*'")
since credentials are always enabled.

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.

1 participant