Skip to content

fix(auth): allow custom environments via BW_API_URL; harden token parsing#17

Open
kshahbw wants to merge 2 commits into
mainfrom
fix/auth-environment-guardrails
Open

fix(auth): allow custom environments via BW_API_URL; harden token parsing#17
kshahbw wants to merge 2 commits into
mainfrom
fix/auth-environment-guardrails

Conversation

@kshahbw

@kshahbw kshahbw commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Three related auth-path hardenings, all grounded in the intent of the env-validation work in ddb2632 / 11a4f95 (kill silent fall-through to production, and turn cryptic failures into actionable ones):

  1. resolveEnvironment — restore the explicit-route escape hatch. After that change, any environment outside prod/test/uat was rejected outright — including environments intentionally routed through an explicit BW_API_URL override, which regressed that workflow. This permits a non-built-in environment only when BW_API_URL is set. An explicit route is the opposite of a silent fall-through, so the original guarantee holds: an unrecognized value with no override still fails loudly and never silently resolves to prod.

  2. oauth.go — legible error for a non-JSON token response. A 2xx whose body isn't a JSON object (an HTML proxy interstitial, or a misrouted host returning XML) previously died with a cryptic invalid character '<' looking for beginning of value parse error. It now returns "token endpoint returned a non-JSON response — you may be behind a proxy or pointed at the wrong host; check your environment and BW_API_URL."

  3. ValidateAPIOverride — reject a schemeless BW_API_URL up front. A BW_API_URL missing its scheme (e.g. stage.api.bandwidth.com instead of https://stage.api.bandwidth.com) reached net/http as the opaque unsupported protocol scheme "". It's now caught at both auth entry points (authenticate() and auth login) with a message that names the fix. Unset stays valid.

Also included (flag for review)

messagingProdOnlyWarning now fires for any non-prod environment, not just test/uat. Slightly beyond the fixes above, but it's the minimum needed to keep #1 from regressing a safety property: a custom-routed environment still hits the production-only messaging host, so without this a custom-env user would send real, billable messages with no warning — exactly the hazard the original hardening closed. Happy to drop it if you'd rather handle separately.

Why this came up

Two users hit auth failures that all trace back to the BW_API_URL override path:

Testing

  • resolveEnvironment: unit tests for fail-loud (no override) and opt-in (with BW_API_URL); verified in a real binary — unknown env fails loudly without an override, routes the token request to the custom host with one.
  • ValidateAPIOverride: unit tests for unset/valid/schemeless; verified in a real binary that a schemeless value yields the actionable message and a scheme'd value routes to the host.
  • messagingProdOnlyWarning: unit test asserts any non-prod env warns.
  • oauth.go: unit test asserts a 2xx HTML body yields the friendly error, not a parse error.
  • go build ./..., full go test ./..., gofmt, and go vet all clean.

🤖 Generated with Claude Code

…sing

resolveEnvironment rejected any environment outside prod/test/uat, which
also blocked an environment routed through an explicit BW_API_URL override —
regressing that workflow. Permit a non-built-in environment when BW_API_URL
is set: an explicit route is not a silent fall-through to prod, so it keeps
the guarantee that an unrecognized value never silently resolves to
production (the reason validation was added in ddb2632 / 11a4f95).

Because a custom-routed environment still hits the production-only messaging
host, widen messagingProdOnlyWarning to fire for any non-prod environment,
so those users are still warned that sends are real and billable.

Harden the OAuth token exchange: a 2xx response whose body is not a JSON
object (an HTML proxy interstitial, or a misrouted host returning XML) now
produces a clear 'non-JSON response — check your environment and BW_API_URL'
error instead of a cryptic 'invalid character <' JSON parse failure.
@kshahbw kshahbw requested review from a team as code owners July 9, 2026 15:55
@bwappsec

bwappsec commented Jul 9, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

A BW_API_URL missing its scheme (e.g. "stage.api.bandwidth.com") reached
net/http as the opaque error 'unsupported protocol scheme ""'.
ValidateAPIOverride now catches a schemeless or hostless override at both
auth entry points — authenticate() and auth login — with an actionable
message that names the fix. An unset BW_API_URL stays valid.
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.

2 participants