-
Notifications
You must be signed in to change notification settings - Fork 17
Improve UX when stored credentials fail validation (login, whoami, MCP) #283
Description
Summary
When the profile already has an API key, hookdeck login only re-validates against GET /cli-auth/validate (no browser). A 401 currently surfaces as a raw API error plus a noisy ERROR log from PerformRequest. hookdeck whoami hits the same path. MCP tools map 401 to a short generic line without config path or clear recovery (hookdeck_login with reauth: true).
This issue tracks clearer user-facing messages, quieter logging for expected validate 401s, and consistent MCP recovery text—without changing the "existing key → verify first" behavior of hookdeck login (browser-always login can be a separate product decision).
Problem
pkg/login/client_login.go: IfProfile.APIKeyis set, login only callsValidateAPIKey(). On failure, users see low-level errors and log noise.pkg/cmd/whoami.go: Same validate call; same experience.- MCP (
pkg/gateway/mcp/errors.go): 401 → "Authentication failed. Check your API key." with no file path orreauthguidance for the general case. Project listing already has extra copy intool_projects_errors.go.hookdeck_logincan report "Already authenticated" while the on-disk key is stale until the first failing API call—recovery copy should be consistent wherever 401 appears.
Proposed approach
1. Shared detection helper
In pkg/hookdeck (near APIError / IsNotFoundError):
IsUnauthorizedError(err error) bool—errors.Asinto*APIError,StatusCode == 401.
2. Quieter logs for validate-only requests
- Add a
Clientflag parallel toSuppressRateLimitErrors, e.g.SuppressAuthFailureLogs. - Set it on the shallow copy built in
clientForCLIAuthValidate()(pkg/hookdeck/auth.go). - In
PerformRequest(pkg/hookdeck/client.go), whencheckAndPrintErrorfails with 401 and the flag is set, log at Debug instead of Error (401 only; avoid masking unexpected 403s on other endpoints).
3. CLI: structured failure message
Add a small formatter (e.g. under pkg/login or pkg/cmd) that takes *config.Config + error:
When IsUnauthorizedError(err):
- Explain the CLI used credentials from the config file (no secret values printed).
- Print config file path from
viper.ConfigFileUsed()when known; otherwise mention--hookdeck-config/ unknown path. - Mention active profile (aligned with
whoami's "Using profile …"). - Next steps: confirm key in dashboard;
hookdeck logoutthenhookdeck loginorhookdeck login -i; note that with a key on disk, plainloginonly re-verifies.
Wire after ValidateAPIKey() fails in:
pkg/login/client_login.gopkg/cmd/whoami.go(theGetAPIClient().ValidateAPIKey()path)
Optional follow-up: drop redundant Profile.ValidateAPIKey() in whoami if it's only an empty-key check.
4. MCP: recovery paragraph
- Extend
TranslateAPIErroror addTranslateAPIErrorWithRecovery(err, configPath string)inpkg/gateway/mcp/errors.go. - On 401, append guidance: credentials loaded from config (include path when non-empty); invalid/revoked; use
hookdeck_loginwithreauth: true(or logout / browser login outside MCP). - Thread
configPathfromServer.cfg/ConfigFileUsed(); centralize usage (e.g. viawrapWithTelemetryorserver.toolAPIError) so every tool doesn't duplicate strings. - Deduplicate with
listProjectsFailureMessageintool_projects_errors.govia a sharedmcpAuthRecoveryHint(configPath)(or similar). - Optionally tweak tool/help strings in
tool_help.go/tools.goso "invalid stored key" appears next to "narrow dashboard key" where relevant.
5. Optional later (separate decision)
hookdeck_login could validate the stored key and on 401 suggest reauth: true instead of "Already authenticated." That improves MCP but adds a network round-trip on every no-arg login—track separately if not in scope.
Tests
IsUnauthorizedError:APIError, wrapped errors, non-matching errors.- Formatter: substrings / table for path, profile,
logout,login. - MCP:
TranslateAPIError/ recovery with and withoutconfigPath; keeptool_projects_errors_test.goin sync if hints merge.
Files (reference)
| Area | Files |
|---|---|
| HTTP client | pkg/hookdeck/client.go, pkg/hookdeck/auth.go |
| CLI | New helper + pkg/login/client_login.go, pkg/cmd/whoami.go |
| MCP | pkg/gateway/mcp/errors.go, server.go, tool_projects_errors.go, tests |
README: optional one-liner under Login only if we want public docs to match.