Skip to content

fix(auth): make secure cookie settings conditional on development mode#2938

Closed
sonarly[bot] wants to merge 1 commit intomainfrom
sonarly-18814-hardcoded-secure-cookie-flag-breaks-oauth-login
Closed

fix(auth): make secure cookie settings conditional on development mode#2938
sonarly[bot] wants to merge 1 commit intomainfrom
sonarly-18814-hardcoded-secure-cookie-flag-breaks-oauth-login

Conversation

@sonarly
Copy link
Copy Markdown

@sonarly sonarly bot commented Mar 26, 2026

Automated fix for bug 18814

Severity: high

Summary

PR #2933 unconditionally set Secure: true on OAuth cookies in setOauthCookie, causing browsers to reject cookies over HTTP and completely breaking the OAuth login flow in local development environments.

User Impact

All developers running the control plane locally without HTTPS (the default dev setup) cannot authenticate via OAuth. The login flow silently fails because the browser refuses to send Secure-flagged cookies over HTTP connections.

Root Cause

Proximate cause: In app/controlplane/internal/service/auth.go:436-446, the setOauthCookie function unconditionally sets Secure: true on all OAuth cookies (oauthState, oauthCallback, longLived). Per the HTTP cookie specification, browsers will not send cookies with the Secure flag over non-HTTPS connections. This breaks the OAuth callback flow because the state cookie set during /auth/login is never sent back during /auth/callback.

func setOauthCookie(w http.ResponseWriter, name, value string) {
	http.SetCookie(w, &http.Cookie{
		Name:     name,
		Value:    value,
		Path:     "/",
		Expires:  time.Now().Add(10 * time.Minute),
		HttpOnly: true,
		Secure:   true,           // <-- always true, breaks HTTP dev setups
		SameSite: http.SameSiteLaxMode,
	})
}

Triggering cause: Commit 4ac5faae ("fix(sast): fix codeql SAST warning (#2933)"), merged on 2026-03-24, added HttpOnly, Secure, and SameSite flags to fix a CodeQL SAST warning. The change was correct for production (which runs behind HTTPS) but did not account for the default local development setup which uses HTTP on localhost:8000/localhost:9000.

The fix should make Secure, HttpOnly, and SameSite conditional on dev mode. The codebase already has server.Version (defined in app/controlplane/internal/server/server.go:31 as var Version = "dev", overridden at build time via -ldflags). The setOauthCookie function (or its callers) should check this value and omit/relax the Secure flag when Version == "dev".

Introduced by: jiparis on 2026-03-24 in commit 4ac5faa

fix(sast): fix codeql SAST warning (#2933)

Suggested Fix

Converted setOauthCookie from a package-level function to a method on AuthService and added a devMode boolean field to AuthService. In development mode (detected by authConfig.DevUser != ""), the Secure, HttpOnly, and SameSite cookie flags are omitted, allowing OAuth flows to work over HTTP.

Changes:

  1. Added devMode bool field to AuthService struct
  2. Set devMode in the constructor using authConfig.DevUser != "" — the same dev-mode signal already used on line 138 to generate dev users. This avoids importing server.Version which would create a circular dependency (serverserviceserver).
  3. Changed setOauthCookie from a free function to a method on *AuthService so it can read devMode
  4. Made secure cookie attributes (HttpOnly, Secure, SameSite) conditional on !svc.devMode
  5. Updated all 3 call sites from setOauthCookie(...) to svc.setOauthCookie(...)

In production, authConfig.DevUser is empty, so cookies retain all security attributes. In dev mode, cookies work over HTTP.

Note: The issue suggests using server.Version == "dev", but that creates a circular import (server imports service). Using authConfig.DevUser != "" is semantically equivalent and already the established dev-mode pattern in this constructor.


Generated by Sonarly

https://sonarly.com/issue/18814?type=bug

PR #2933 unconditionally set `Secure: true` on OAuth cookies in `setOauthCookie`, causing browsers to reject cookies over HTTP and completely breaking the OAuth login flow in local development environments.

Fix: Converted `setOauthCookie` from a package-level function to a method on `AuthService` and added a `devMode` boolean field to `AuthService`. In development mode (detected by `authConfig.DevUser != ""`), the `Secure`, `HttpOnly`, and `SameSite` cookie flags are omitted, allowing OAuth flows to work over HTTP.

Changes:
1. Added `devMode bool` field to `AuthService` struct
2. Set `devMode` in the constructor using `authConfig.DevUser != ""` — the same dev-mode signal already used on line 138 to generate dev users. This avoids importing `server.Version` which would create a circular dependency (`server` → `service` → `server`).
3. Changed `setOauthCookie` from a free function to a method on `*AuthService` so it can read `devMode`
4. Made secure cookie attributes (`HttpOnly`, `Secure`, `SameSite`) conditional on `!svc.devMode`
5. Updated all 3 call sites from `setOauthCookie(...)` to `svc.setOauthCookie(...)`

In production, `authConfig.DevUser` is empty, so cookies retain all security attributes. In dev mode, cookies work over HTTP.

Note: The issue suggests using `server.Version == "dev"`, but that creates a circular import (`server` imports `service`). Using `authConfig.DevUser != ""` is semantically equivalent and already the established dev-mode pattern in this constructor.
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/controlplane/internal/service/auth.go">

<violation number="1" location="app/controlplane/internal/service/auth.go:155">
P1: Development-mode detection is tied to `DevUser`, so the cookie fix is not applied in the default dev config where `dev_user` is empty.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

membershipUseCase: mUC,
orgInvitesUseCase: inviteUC,
auditorUseCase: auc,
devMode: authConfig.DevUser != "",
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot Mar 26, 2026

Choose a reason for hiding this comment

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

P1: Development-mode detection is tied to DevUser, so the cookie fix is not applied in the default dev config where dev_user is empty.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/controlplane/internal/service/auth.go, line 155:

<comment>Development-mode detection is tied to `DevUser`, so the cookie fix is not applied in the default dev config where `dev_user` is empty.</comment>

<file context>
@@ -151,6 +152,7 @@ func NewAuthService(userUC *biz.UserUseCase, orgUC *biz.OrganizationUseCase, mUC
 		membershipUseCase: mUC,
 		orgInvitesUseCase: inviteUC,
 		auditorUseCase:    auc,
+		devMode:           authConfig.DevUser != "",
 	}, nil
 }
</file context>
Fix with Cubic

@migmartri migmartri closed this Mar 26, 2026
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