Skip to content

spotify-pp-cli: auth login fails with "Invalid client secret" on the documented CLIENT_ID-only flow — PKCE is not implemented #1287

Description

@vinnyp

Summary

spotify-pp-cli auth login fails at the token-exchange step with HTTP 400: invalid_request, Invalid client secret when a user follows the documented PKCE flow (set only SPOTIFY_CLIENT_ID, no secret). The README and SKILL.md both state PKCE is the default in that configuration, but PKCE is not implemented in the code — so a CLIENT_ID-only setup can never complete login. It's a hard onboarding blocker for any new user who follows the docs.

What the docs promise

  • README.md (~L126): "OAuth flows are auto-detected: PKCE is the default when only SPOTIFY_CLIENT_ID is set, and Authorization Code with secret is used when SPOTIFY_SECRET is also present…"
  • SKILL.md Auth Setup, Step 3 (~L359): "…only needed if you want to use the Authorization Code flow with a secret. If you skip it, the CLI uses PKCE, which is simpler and recommended for desktop use."

Reproduction

  1. Create a Spotify app, register redirect URI http://127.0.0.1:8085/callback.
  2. export SPOTIFY_CLIENT_ID=<id>do not set any secret (the documented PKCE path).
  3. spotify-pp-cli auth login
  4. Browser consent succeeds and returns an authorization code; the CLI then fails:
Error: exchanging code for token: HTTP 400: map[error:invalid_request error_description:Invalid client secret]

Root cause

PKCE is never initiated and never used. In internal/cli/auth.go:

  • Authorize request (~L140-149) sets only client_id, redirect_uri, response_type=code, state, scope. There is no code_challenge / code_challenge_method, so the flow is not PKCE.
  • Token exchange (~L200-208) sends grant_type=authorization_code, code, redirect_uri, client_id, and adds client_secret only if non-empty. There is no code_verifier.

A grep over the repo confirms code_challenge / code_verifier / pkce appear nowhere in the source.

Result: with no secret, the token request is a bare authorization_code grant with neither client authentication nor a PKCE verifier, which Spotify's token endpoint rejects as Invalid client secret. The flow only works if a client secret is supplied (SPOTIFY_SECRET / SPOTIFY_CLIENT_SECRET), i.e. plain Authorization Code — the opposite of what the docs say is the default.

Expected

Either of:

  • (A) Implement PKCE — generate a code_verifier, send code_challenge + code_challenge_method=S256 on the authorize request, and code_verifier on the token exchange when no secret is configured. This honors the documented "CLIENT_ID-only" path and is the recommended public-client flow for a desktop CLI.
  • (B) Fix the docs — if PKCE is out of scope, make the client secret required in README.md + SKILL.md and remove the "PKCE is the default / secret optional" guidance, so users set SPOTIFY_SECRET from the start. (Lower-effort stopgap.)

(A) is preferable — Spotify's loopback/native-app guidance pushes PKCE, and it avoids shipping a long-lived secret on every user's machine.

Workaround (for anyone hitting this now)

Set the client secret and re-run login:

export SPOTIFY_CLIENT_SECRET=<secret>   # or SPOTIFY_SECRET
spotify-pp-cli auth login

Environment

  • CLI: spotify-pp-cli (library/media-and-entertainment/spotify), version 2026.6.1
  • Auth verified working once a secret is supplied (live me get-current-users-profile returns a real profile).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions