CLI प्रमाणीकरण, सही तरीका
(abgeo.dev)- कई CLI डिफ़ॉल्ट रूप से localhost OAuth redirect का उपयोग करते हैं, जो लैपटॉप के लोकल ब्राउज़र में जल्दी पूरा हो जाता है, लेकिन SSH·कंटेनर·WSL जैसे डेवलपमेंट एनवायरमेंट में यही धारणा टूट जाती है और login flow रुक जाता है
- मौजूदा तरीका यह है कि CLI
127.0.0.1पर एक अस्थायी HTTP server खोलता है, ब्राउज़र को authentication URL पर भेजता है, फिर authentication provider authorization code को local callback पर वापस भेजता है - 2019 में standard बना RFC 8628 Device Authorization Grant token मांगने वाले CLI और user के authenticate करने वाले browser device को अलग कर देता है, जिससे port binding या local browser पर निर्भरता खत्म हो जाती है
- Device flow में
device_code,user_code,verification_uri,intervalमिलते हैं और/tokenको समय-समय पर poll किया जाता है, साथ हीauthorization_pending,slow_down,access_denied,expired_tokenजैसी standard states को handle किया जाता है - अगर नया CLI बना रहे हैं, तो device flow को default रखना चाहिए,
.well-known/openid-configurationसे endpoint discover करना चाहिए, और refresh token को~/.configके JSON file में नहीं बल्कि OS keychain में रखना चाहिए
localhost redirect किन बातों को मानकर चलता है
- आम CLI login इस धारणा पर काम करता है कि local HTTP server और system browser एक ही मशीन पर हैं
- CLI
127.0.0.1के किसी तय port पर HTTP server bind करता है - system browser में OAuth authorization endpoint खोलता है और
redirect_uri=http://127.0.0.1:<port>/callbackशामिल करता है - user login करता है तो authentication provider authorization code को loopback URL पर
302redirect करता है - CLI का छोटा HTTP server code पढ़ता है और token endpoint से token के बदले exchange करता है
- ज़्यादातर मामलों में PKCE भी जुड़ा होता है, और उसके बाद “you may close this tab” पेज दिखता है
- CLI
gcloud auth login,wrangler login, पुरानाvercel loginऔर कई vendor CLI यही तरीका इस्तेमाल करते हैं- Wrangler
8976port इस्तेमाल करता है - gcloud
8085इस्तेमाल करता है - Claude Code हर run पर अस्थायी port चुनता है
- Wrangler
- RFC 8252 browser मौजूद होने पर native app के लिए इस pattern की सिफारिश करता है, लेकिन host पर browser न हो तो क्या करना है, यह नहीं बताता
user localhost चरण को ठीक से क्यों नहीं देख पाता
- localhost callback बहुत कम समय के लिए आता है, इसलिए ज़्यादातर users उसे देख ही नहीं पाते
- CLI जो URL दिखाता है वह लंबा होता है, और उसमें redirect URI query string के अंदर शामिल होता है
- user authentication provider के असली domain पर login और approval देता है
- authentication provider browser को localhost callback पर भेजता है, CLI code पढ़ लेता है, फिर polished “signed in” पेज पर आगे बढ़ जाता है
- ऊपर से देखने पर यह “वेबसाइट पर login किया और CLI authenticate हो गया” जैसा लगता है, लेकिन वास्तव में इस flow को local HTTP server और browser का साथ मौजूद होना संभालता है
SSH·कंटेनर·WSL में यह कहाँ टूटता है
- पूरा flow इस धारणा पर निर्भर है कि जिस मशीन पर CLI चल रहा है और जिस मशीन पर browser चल रहा है, दोनों एक ही हैं
- SSH session में remote host पर browser नहीं होता, और
xdg-openfail हो सकता है या X forwarding में ऐसा remote browser खुल सकता है जो दिखे ही नहीं- callback port को लैपटॉप तक tunnel किया जा सकता है, लेकिन authentication provider में registered redirect URI को tunneled port की अनुमति देनी होगी
- कंटेनर में browser नहीं होता, और कई images में
xdg-openयाopenभी नहीं होते-pसे callback port expose किया जा सकता है, लेकिन पहले यह जानना होगा कि CLI कौन-सा port चुनेगा- Cloudflare CLI में इस समस्या से फँसे users की issue लगातार आती रही है
- WSL में browser Windows पर खुलता है, जबकि loopback server Linux में चलता है
- WSL2 का port forwarding अक्सर काम करता है, लेकिन हर बार नहीं
- shared box में उसी मशीन के दूसरे process
/proc/net/tcpसे listening port ढूँढ सकते हैं, या known port को पहले bind करने की race में आ सकते हैं- PKCE code exchange को सुरक्षित करता है, लेकिन redirect के authenticated session को नहीं
fallback खुद design समस्या दिखा देता है
- जो CLI loopback flow को default देते हैं, वे टूटने की स्थिति के लिए fallback भी साथ रखते हैं
- gcloud में
--no-launch-browserहै - Wrangler रुक जाता है, और accepted workaround यह है कि दूसरे terminal से localhost URL को सीधे curl किया जाए
- Anthropic का
claude“Paste code here if prompted” प्रिंट करके इंतज़ार करता है - ये fallback असल में manual device flow ही हैं, और इसलिए मौजूद हैं क्योंकि CLI जिन environments में वास्तव में इस्तेमाल होता है, वहाँ default flow काम नहीं करता
RFC 8628 Device Authorization Grant
- RFC 8628 2019 में “input-constrained devices” के लिए आया OAuth 2.0 Device Authorization Grant है
- इसमें TV, console, CLI शामिल हैं
- मुख्य विचार यह है कि token मांगने वाली device और user के authenticate करने वाली device को अलग किया जाए
- CLI authentication provider के
device_authorization_endpointपर POST करता है- उदाहरण request
client_id=my-cli&scope=openid+offline_accessभेजती है
- उदाहरण request
- authentication provider JSON में ये values लौटाता है
device_codeuser_codeverification_uriverification_uri_completeexpires_ininterval
- CLI URL और छोटा code दिखाता है, और संभव हो तो
verification_uri_completeके लिए QR भी दिखाता है - user अपनी पसंद की device पर URL खोलता है, login करता है, फिर requested scope और client name देखकर यह पुष्टि करता है कि वह CLI पर दिख रहे छोटे code से मेल खाता है, और फिर approval देता है
polling और standard state handling
- CLI हर
intervalसेकंड में token endpoint को poll करता है - grant type
urn:ietf:params:oauth:grant-type:device_codeहोता है - RFC 8628 section 3.5 ये states define करता है
authorization_pending: user approval का इंतज़ार जारी हैslow_down: authentication provider कह रहा है कि polling interval कम बार रखें, और spec के अनुसार interval कम-से-कम 5 सेकंड बढ़ाना चाहिएaccess_denied: user ने मना कर दियाexpired_token: बहुत देर इंतज़ार हुआ और token expire हो गया
- device flow में CLI कोई port bind नहीं करता और यह नहीं मानता कि execution host पर browser मौजूद होगा
- यही login तरीका laptop, container और human approval का इंतज़ार कर रही CI job — सभी में काम करता है
polling की लागत और endpoint discovery
- default polling interval 5 सेकंड है
- ज़्यादातर authentication 1 मिनट के भीतर पूरी हो जाती है, इसलिए सामान्य login में
/tokenपर लगभग 10 बार polling होती है और फिर रुक जाती है - server
slow_downके ज़रिए interval बढ़ा सकता है, और अच्छे client को इसका पालन करना चाहिए - हर pending login के लिए stateful endpoint पर WebSocket या SSE connection बनाए रखने की तुलना में
/tokenपर stateless polling ज़्यादा सरल और सस्ती है - अगर authentication provider OpenID Connect Discovery support करता है, तो CLI
.well-known/openid-configurationसेdevice_authorization_endpointऔरtoken_endpointले सकता है, जिससे URL hardcode करने की ज़रूरत नहीं रहती
device flow का phishing risk
- device flow में एक हमला यह है कि attacker असली authentication provider के
device_authorization_endpointको call करकेuser_codeऔरdevice_codeलेता है, फिर victim को code दर्ज करने के लिए उकसाता है - victim असली URL पर, असली code के साथ login कर सकता है और असली consent screen approve कर सकता है
- attacker अपने बनाए
device_codeके साथ/tokenको poll करता रहता है और access token हासिल कर लेता है - एक रूसी threat actor ने अगस्त 2024 के बाद M365 tenant को निशाना बनाकर यह campaign चलाया
- Microsoft Threat Intelligence इसे Storm-2372 के रूप में track करता है
- Volexity ने इसका attribution APT29/Midnight Blizzard को दिया है
- कई महाद्वीपों में government, defence और NGO tenant प्रभावित हुए
phishing से बचाव authentication provider की ज़िम्मेदारी है
- phishing defence CLI की नहीं बल्कि authentication provider की ज़िम्मेदारी होनी चाहिए
- ज़रूरी mitigations ये हैं
user_codeकी छोटी expiry time- verification page पर client name और request origin को साफ़-साफ़ दिखाना
- code entry attempts पर rate limiting
verification_uri_completeन दिखाना ताकि victim लिंक पर click करने के बजाय code खुद दर्ज करे- high-value tenant के लिए known network या device न होने पर device code flow रोकने वाली conditional access policy
- CLI का काम spec का पालन करना है, shortcuts बनाना नहीं
- device flow local attack surface को social attack surface में बदल देता है, लेकिन अधिक environments में काम करने वाला flow देना और authentication provider की mitigation का लाभ उठाना ज़्यादा उचित है
Go implementation example का मुख्य flow
- पूरी implementation Go में सिर्फ
net/httpके साथ लगभग 30 lines में आ जाती है - implementation flow इस प्रकार है
client_idऔरscopeके साथDeviceAuthorizationEndpointपरhttp.PostFormcall- response JSON से
DeviceCode,UserCode,VerificationURIComplete,Intervaldecode करना - user को
VerificationURICompleteऔरUserCodeप्रिंट करना TokenEndpointपरdevice_code,client_id, device grant type के साथ बार-बार POST करनाauthorization_pendingहो तो इंतज़ार जारी रखनाslow_downहो तो interval 5 सेकंड बढ़ाना- error न हो तो
access_tokenऔरrefresh_tokenलौटाना - अन्य error को failure मानना
- Keycloak realm में “OAuth 2.0 Device Authorization Grant” capability on कर दें, या grant support करने वाला OpenID-certified provider इस्तेमाल करें, तो device-flow login काम करेगा
नए CLI के default के रूप में क्या चुनना चाहिए
- default device flow होना चाहिए
.well-known/openid-configurationसे endpoint discover करने चाहिए, URL hardcode नहीं करने चाहिएintervalऔरslow_downका पालन अनिवार्य रूप से करना चाहिए- refresh token को
~/.configके नीचे JSON file में नहीं बल्कि OS keychain में रखना चाहिए - अगर तेज़ laptop login के लिए loopback path देना ही हो, तो उसे
--webflag के पीछे रखें, default न बनाएं
जो CLI आगे बढ़ चुके हैं और जो अभी बाकी हैं
- कुछ CLI पहले से device flow को default के रूप में इस्तेमाल कर रहे हैं
gh auth loginशुरू से device flow इस्तेमाल करता आया है, और open source में इसे सबसे साफ़ reference implementation माना जाता हैaws sso loginIAM Identity Center के साथ end-to-end device flow चलाता हैvercel loginने सितंबर 2025 में RFC 8628 पर migration किया, और email-based login व पुराने--oobflag को replace किया- Stripe CLI RFC 8628 खुद नहीं है, लेकिन बेहतरीन UX वाला pairing-code flow इस्तेमाल करता है
- कुछ tools अब भी loopback flow को default रखते हैं और उसके साथ paste-the-code fallback जोड़ते हैं
- Google
gcloud - Cloudflare
wrangler - Anthropic
claude
- Google
- अगर किसी CLI को laptop से बाहर जाते ही manual paste-the-code fallback चाहिए, तो बेहतर है कि उसी fallback को default flow बना दिया जाए
1 टिप्पणियां
Lobste.rs की राय
अभिव्यक्ति थोड़ी ढीली-ढाली है, लेकिन दिलचस्प है। device code/link को हर 1 मिनट में बदलने से phishing में उसके दुरुपयोग की संभावना भी कम हो सकती है
एक बार इस्तेमाल होने के बाद rotation रोक दी जाए और उस session को IP या browser से बाँध दिया जाए
Microsoft जैसे provider में, जहाँ उपयोगकर्ता को code खुद दर्ज करना पड़ता है, landing page निर्देश दिखाकर code को clipboard में copy भी कर सकता है, जिससे phishing का खतरा और बढ़ सकता है
अच्छा लेख है, और मैं इस बात से सहमत हूँ कि सबको RFC 8628 की ओर जाना चाहिए
remote development machine पर CLI OAuth प्रक्रिया बहुत ज़्यादा बार झेलने के बाद, मैंने
xdg-openको intercept करने और ports को अपने-आप forward करके खराब user experience को छिपाने वाला एक personal tool बनाया: https://github.com/phinze/bankshotदिलचस्प। मैंने हाल ही में संयोग से “पुराना” authentication तरीका RFC 8252 implement किया था, लेकिन “नए” तरीके RFC 8268 के बारे में नहीं जानता था
शायद ऐसा इसलिए क्योंकि मेरा मुख्य use case Google server authentication था। जिन documents को मैं RFC 8268 flow समझ रहा था, उनमें यह साफ़ लिखा है
Google की scope restriction वही जगह है जहाँ OIDC की जटिलता उभरकर सामने आती है। आदर्श रूप से Google को access token में सब कुछ ठूँसने के बजाय ID token लौटाना चाहिए, लेकिन यह Google की OAuth configuration की समस्या है, 8628 की अपनी विशेषता नहीं
OAuth की अंतहीन जटिलता यहीं से आती है। standard इस बात की रूपरेखा अच्छी तरह तय करता है कि authorization framework को कैसे बनाना और पहुँचाना है, लेकिन यह जानबूझकर चुप रहता है कि वह असल में क्या होना चाहिए। “ज़्यादातर” providers जिस common HTTP endpoints के सेट पर सहमत हैं, वहाँ तक पहुँचने के लिए भी OIDC के आविष्कार और कई साल लगे
एक और hack यह है कि server के xdg-open call को laptop तक forward किया जाए। मैंने personal infrastructure के लिए यह करने वाला एक छोटा tool बनाया है: https://github.com/zimbatm/subportal/
क्या दोनों approaches को जोड़ा नहीं जा सकता?
localhostURL पर redirect करकेhelloवापस भेजा जाए, और अगर client कोhelloन मिले तो CLI में URL दिखा दिया जाएसाथ ही, अगर server को भेजे गए
helloका जवाब न मिले, तो browser में code दिखाकर “पुष्टि करें कि क्या आप login की कोशिश कर रहे हैं” जैसा संदेश दिखाया जा सकता है। Google की तरह फ़ोन पर चुनने के लिए नंबर दिखाकर इसे और आसान भी बनाया जा सकता हैफ़ायदा यह है कि case 2 में भी लोग लिंक पर click तो आसानी से कर लेते हैं, लेकिन OTP/code share अपेक्षाकृत कम करते हैं, और हमलावर को attack के दौरान लगातार social engineering में शामिल रहना पड़ता है
जब local machine पर यह ठीक से काम करता है, तब किसी interaction की ज़रूरत नहीं होती, इसलिए default browser-based flow होना चाहिए