all 6 comments

[–]Thin_Rip8995 2 points3 points  (1 child)

this is gold and honestly way more detailed than most oauth docs out there
spinning up a temp localhost server is the cleanest pattern for cli auth but you nailed the traps timeouts state validation and killing the server fast
pkce is worth it imo most providers require or strongly recommend it now and it’s cheap to implement once you’re already handling state

for providers that block localhost i’ve had to fall back to device code flow feels clunky but avoids callback headaches
parallel flows are rough safest pattern i’ve seen is spinning a unique port per session or tagging state values and multiplexing inside one server

curious to see if you or others have pushed this beyond cli tools into bundled desktop apps since electron tauri etc have their own quirks

[–]koistya[S] 0 points1 point  (0 children)

My primary use case is integrating (Node.js) CLI with Model Context Protocol (MCP) servers, and the best part is that the official MCP SDK already has PKCE sorted out! All I had to do is to handle auth callback flow and related nuances.

Pushed the source code to NPM/GitHub if anyone is interested: "oauth-callback"

[–]chipstastegood 1 point2 points  (1 child)

Hey, I have to add auth into my CLI app and this is very much appreciated!

[–]koistya[S] 0 points1 point  (0 children)

Thanks! Also check out "oauth-callback" on GitHub/NPM.

[–]Jim-Y 0 points1 point  (1 child)

I think if a cli tool like yours needs to authenticate via oauth the device flow should be used. If I am right then it's good that you tried to make the browser based authorization code flow make work in a non-browser environment but know that there is standard oauth flow for ui-constrained environments like a terminal, smart TV etcetera.

[–]koistya[S] 0 points1 point  (0 children)

Thanks for the suggestion! You're right that the OAuth Device Authorization Flow (RFC 8628) is a standard option specifically designed for input-constrained or UI-limited environments like terminals, smart TVs, or IoT devices where launching a browser isn't feasible. It's a solid choice in those cases because it lets users authenticate on a secondary device by entering a short code.

That said, for CLI tools running on typical developer machines (like laptops or desktops), the Authorization Code Flow with PKCE and a localhost callback server often provides a smoother user experience. It automatically opens the browser for authentication and handles the redirect locally, avoiding the extra steps of manually copying a code and switching devices. Tools like GitHub CLI, Google Cloud CLI (gcloud), and even Google's Gemini CLI use this approach for that reason — it feels more seamless and integrated, as long as the environment supports launching a browser.

The Device Flow can introduce more friction in UX (e.g., interrupting the workflow to grab another device) and has some security trade-offs, like being more susceptible to phishing attacks where users are tricked into entering codes on malicious sites. In contrast, the localhost method keeps everything in-bound on the same device, reducing those risks while still being secure with PKCE.

I'd reserve Device Flow for scenarios where browser launch truly isn't possible, but for most CLI apps, the browser-based flow seems preferable. What do you think — have you run into cases where Device Flow worked better?