Skip to content

CLI-1082 Harden authentication flows - #798

Draft
nquinquenel wants to merge 3 commits into
masterfrom
bug/nq/CLI-1082-auth-hardening
Draft

nquinquenel wants to merge 3 commits into
masterfrom
bug/nq/CLI-1082-auth-hardening

Conversation

@nquinquenel

@nquinquenel nquinquenel commented Sep 7, 2026

Copy link
Copy Markdown
Member

Summary by Gitar

  • Authentication hardening:
    • Validate browser authentication tokens via checkTokenStatus during callback handling and token generation
    • Reject unauthorized browser tokens with a 401 status and support fallback to manual token input
    • Update recordConnectionFromAuth to correctly set the envOnly marker on existing matching connections

This will update automatically on new commits.

@netlify

netlify Bot commented Sep 7, 2026

Copy link
Copy Markdown

Deploy Preview for sonarqube-cli canceled.

Name Link
🔨 Latest commit e72ccbe
🔍 Latest deploy log https://app.netlify.com/projects/sonarqube-cli/deploys/6a9f2ffb55790b0008d4aa38

@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Sep 7, 2026

Copy link
Copy Markdown

CLI-1082

Comment thread src/core/auth/auth-connection-recorder.ts Outdated
Comment thread src/core/auth/token.ts
Comment thread src/core/auth/token.ts Outdated
Comment thread src/core/auth/auth-connection-recorder.ts Outdated
Comment thread tests/integration/specs/auth/auth.test.ts
@gitar-bot

gitar-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 5 resolved / 5 findings

Hardens authentication flows by validating browser authentication tokens via checkTokenStatus during callback handling and token generation, rejecting unauthorized tokens with a 401 status to support fallback to manual input. Addresses envOnly marker stamping on login connections, callback token rejection leaving CI login hanging, unreachable server misreported as unvalidatable token, env-var auth silent failures when keychain is unreachable, and CI login test trust prompt handling.

✅ 5 resolved
Bug: envOnly marker stamped on login connection disables logout

📄 src/core/auth/auth-connection-recorder.ts:65-68
After sonar auth login the active connection is fully enriched (userUuid + sqsInstallationId), so any later command run with SONARQUBE_CLI_TOKEN/SONARQUBE_CLI_SERVER pointing at the same server now takes the early-return branch and permanently persists envOnly: true on that keychain-backed connection (before this PR the branch returned without mutating). A subsequent sonar auth logout (env vars unset) hits active.envOnly in logout.ts:43, prints "You are already logged out." and never revokes the server token, never calls deleteToken, and leaves isAuthenticated: true — so the keychain token stays usable and the user believes they are logged out. Only mark envOnly when there is no keychain token behind the connection.

Edge Case: Rejected callback token leaves CI login hanging forever

📄 src/core/auth/token.ts:268-275 📄 src/core/auth/token.ts:286-299
The callback now only calls resolveToken when validation returns valid, so a browser-delivered token that is invalid — or valid but whose validation call returns unreachable because of a transient network/proxy error — leaves tokenPromise unresolved. In the CI === 'true' branch (token.ts:290) there is no timeout, abort signal or race, and no interactive paste fallback, so the CLI blocks indefinitely with no diagnostic instead of failing; previously the POST always resolved the promise. Fail fast in the non-interactive branch (and log the rejection) rather than waiting forever.

Edge Case: Unreachable server reported as an unvalidatable token

📄 src/core/auth/token.ts:269 📄 src/core/auth/token.ts:301-308
checkTokenStatus returns unreachable for any network/HTTP failure (token.ts:66-73), and both new call sites treat anything other than valid as a bad token: the callback returns 401 and the final check throws The provided token could not be validated by the SonarQube server. So a manually pasted, perfectly good token fails login on a transient outage, with a message blaming the token and no remediationHint, while preflight-summary.ts distinguishes the two statuses. Branch on unreachable and say the server could not be reached.

Bug: Env-var auth now dies silently when the keychain is unreachable

📄 src/core/auth/auth-connection-recorder.ts:60-64
recordConnectionFromAuth now calls getToken() on the env-var path, and getToken propagates a CommandFailedError whenever the backend fails (wrapBunSecrets, keychain.ts:47) — which is exactly what happens in headless containers/CI where Bun.secrets has no libsecret/D-Bus and no SONARQUBE_CLI_KEYCHAIN_FILE is set. The only caller passing envOnly: true (recordEnvAuthConnectionOnce, auth-resolver.ts:90) swallows that rejection into a logger.debug, so with SONARQUBE_CLI_TOKEN + SONARQUBE_CLI_SERVER on such a machine the connection is no longer recorded at all: state.auth.isAuthenticated stays false, no connection row, no telemetry identity — the very behaviour tests/integration/specs/auth/env-auth-state-sync.test.ts was written to guarantee (integration tests always set the file backend, so they never exercise this). Keychain-free env-var auth is the documented fallback for a broken keychain (KEYCHAIN_UNAVAILABLE_HINT), so the lookup must not be able to break it: catch the error and treat it as "cannot prove this is env-only".

Bug: New CI login test never answers the trust prompt, so it can't pass

📄 tests/integration/specs/auth/auth.test.ts:135-148
auth login --server <fake on-premise url> hits confirmServerTrustconfirmPrompt('Connect to: …?') before it ever reaches the browser flow, and confirmPrompt has no non-TTY/CI shortcut (unlike pressEnterKeyPrompt). harness.run() pipes stdin and never writes to it, so the prompt either cancels (Login cancelled on stderr → the toContain('The token delivered by the browser could not be validated.') assertion fails) or blocks until the harness timeout; the invalid browserToken is never delivered. Every other on-premise login test in this file goes through the confirmTrust helper for this reason — use it here too.

Implementation Status ✅ 3 of 3 objectives covered
CLI-1082 - 3 of 3 objectives covered

This PR covers the hardening of browser auth callbacks, preserving the auth source marker for environment credentials, and adding regression test coverage for both flows.

✅ 3 covered here
  • ✅ Harden browser authentication callback acceptance
  • ✅ Preserve the authentication source marker when environment credentials reuse an existing connection
  • ✅ Add regression coverage for both authentication flows
Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

sonarqubecloud Bot commented Sep 7, 2026

Copy link
Copy Markdown

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