CLI-authenticatie goed krijgen: de complete gids voor alle 4 methoden
De 4 CLI-authentificatiemethoden die ertoe doen, hoe GitHub, AWS en AI-tools ze implementeren en de beveiligingsfouten die je wilt vermijden.
De 4 CLI-authentificatiemethoden die ertoe doen, hoe GitHub, AWS en AI-tools ze implementeren en de beveiligingsfouten die je wilt vermijden.
Elke ontwikkelaars-CLI wordt geleverd met login als eerste commando. En ze lossen allemaal authenticatie anders op.
GitHub toont je een code en opent je browser om deze te verifiëren. AWS opent een browser voor PKCE-gebaseerde SSO. Stripe laat je een koppelingscode in het dashboard bevestigen. De nieuwere AI-tools (Claude Code, OpenAI Codex CLI, Cursor) kozen elk hun eigen benadering.
Als je een CLI bouwt, is authenticatie één van de eerste dingen waar je over na moet denken. Kies je de verkeerde methode, dan hoor je het snel genoeg: gefrustreerde gebruikers, beveiligingsaudits, of allebei. En met de recente golf aan AI-coding-agents die CLI-tools programmatisch aanroepen, zijn de risico's groter: je authenticeert niet alleen meer een mens. Je geeft misschien inloggegevens aan een autonoom proces.
Hier zijn de vier relevante authenticatiemethoden, hoe de grootste tools ze toepassen, en de fouten die je wilt vermijden.
Voordat we de diepte ingaan, hier een snelle vergelijking:
| Methode | Best voor | Beveiliging | Browser nodig? |
|---|---|---|---|
| OAuth Device Code Flow | Headless omgevingen, SSH | Hoog | Nee (op hetzelfde apparaat) |
| Browser-based OAuth (localhost redirect) | Lokale ontwikkeling | Hoogst | Ja |
| API Keys / PATs | Automatisering, CI/CD, snel prototypen | Matig | Nee |
| Client Credentials | Machine-to-machine, services | Hoog | Nee |
Elke optie heeft zijn eigen voor- en nadelen. Hier is wat je moet weten over elk.
Dit is die waarbij je CLI je een code toont zoals ABCD-1234 plus een URL, en je vraagt die URL op elk apparaat te openen en de code in te voeren.
Wie gebruikt het: GitHub CLI (standaard), Azure CLI (via --use-device-code), Vercel CLI (sinds kort als standaard), OpenAI Codex CLI (als bètakeuze)
cli login uitclient_id en gewenste scopesdevice_code (interne ID), een user_code (de korte code die je invoert) en een verification_uri (waarheen je moet gaan)Het grote voordeel: het werkt overal. SSH-sessie naar een remote server? Werkt. Draait in een Docker-container? Werkt. Cloud IDE zonder lokale browser? Werkt. De browser hoeft niet op dezelfde machine te draaien als de CLI.
Het ondersteunt ook alle enterprise-authenticatievormen (SAML, OIDC, MFA), want alles gebeurt in de browser en niet in de terminal. Je CLI ziet nooit je wachtwoord.
Device code flow heeft een phishingprobleem. Een aanvaller kan een device code aanvragen, een legitieme gebruikerscode krijgen en je misleiden deze in te voeren, waardoor hij feitelijk de sessie van de aanvaller autoriseert. Dit is geen theorie. Security-onderzoekers hebben deze aanval tegen AWS SSO device code auth beschreven.
Dit is zo'n groot risico dat AWS hun standaard heeft gewijzigd. Vanaf AWS CLI v2.22.0 is de standaard voor aws sso login nu PKCE-gebaseerde authorization code flow. Device code is nog steeds beschikbaar via --use-device-code, maar het is niet meer de standaard.
Microsofts eigen tenant is gestart met blokkeren van device code flow via conditional access policies, wat aangeeft dat zij dit als een risicovolle authenticatiemethode beschouwen.
We zien dus een interessante splitsing: Vercel adopteerde device code flow als standaard in september 2025, terwijl AWS er juist vanaf stapt. De trend: device code flow is ideaal als je echt geen browser kunt openen, maar kan dat lokaal wél, dan is PKCE veiliger.
Aan de aanbiederskant groeit de vraag duidelijk. Logto bracht onlangs OAuth 2.0 Device Authorization Grant ondersteuning uit voor native apps in v1.38.0 (open source) en Logto Cloud. Zo kun je nu device flow als authorisatiemethode voor iedere native applicatie inschakelen. Dat is belangrijk als je een CLI bouwt. RFC 8628 correct implementeren (code-verval, rate limiting, pollinglogica, sign-in UX op de verificatiepagina) kost meer werk dan de meeste teams denken, en het aan je provider overlaten betekent alleen dat jij de juiste HTTP-calls hoeft te doen.
Enkele punten uit RFC 8628:
expires_in waarde voor device codes wordt door de server bepaald. De RFC noemt 1800 seconden (30 minuten) als voorbeeld, maar dat is geen vaste eis.interval, dan moet de client standaard 5 seconden aanhouden.slow_down error, tel dan 5 seconden bij je interval op.Dit is de meest gebruikte methode voor CLIs die lokaal draaien. Je voert login uit, je browser opent, je authenticeert en de browser redirect terug naar een tijdelijke lokale server die de CLI opzet. Moderne varianten voegen PKCE (spreek uit: "pixie") toe, waardoor de flow veel moeilijker te misbruiken is.
Wie gebruikt het: Claude Code, gcloud CLI, Terraform CLI, AWS CLI v2.22+ (voor SSO, met PKCE als standaard)
cli login uithttp://127.0.0.1:8742)http://127.0.0.1:8742/callback?code=XXXX&state=YYYYDe gebruikerservaring is soepel. Geen codes overtypen, geen URL's overnemen. Gewoon een tab opent en weer sluit.
Dit werkt alleen als de CLI een browser kan openen én aan localhost kan binden. Niet bruikbaar voor:
Daarom bieden de meeste tools die standaard browser OAuth gebruiken ook een fallback, meestal device code flow of API keys.
Val 1: Binden aan 0.0.0.0 i.p.v. 127.0.0.1
Dit is de meest gemaakte fout, en erg ernstig. Luistert je callback-server op alle interfaces, kan iedereen op het netwerk de code onderscheppen.
Ik heb dit in production-CLIs gezien. Veel HTTP-serverbibliotheken gebruiken standaard 0.0.0.0, dus je maakt deze fout snel.
Val 2: Ontbrekende state-parametervalidatie
De state-parameter beschermt tegen CSRF. Zonder dit kan een aanvaller je CLI misleiden een code van een kwaadwillende sessie te accepteren.
Val 3: PKCE niet gebruiken
Gebruik je geen PKCE (Proof Key for Code Exchange), kan een onderschepte code opnieuw worden gebruikt.
In een standaard authorization code flow kan een aanvaller de code onderscheppen (via het netwerk of de redirect-URL) en die zelf voor tokens inwisselen. PKCE voorkomt dat door bewijs te eisen dat degene die de code inwisselt, dezelfde client is als degene die de authorisatie aanvroeg.
PKCE voegt dit toe aan de flow:
code_verifier (een lange, willekeurige string)code_challengecode_verifier meeDe aanvaller heeft de code_verifier niet, dus die kan de code niet inwisselen.
Daarom heeft AWS CLI v2.22+ PKCE de standaard gemaakt voor SSO, en stappen ze af van device code flow. Kan de CLI een browser op dezelfde machine openen, dan is browser OAuth met PKCE gewoon beter dan device code flow: zelfde UX, sterkere beveiliging, geen phishingrisico. Device code flow is nog steeds geschikt als een browser op de machine niet mogelijk is (SSH, containers, remote development), maar voor lokaal gebruik is het niet meer de beste keuze.
De simpelste aanpak. Je maakt een API-key aan in het dashboard, plakt hem in je CLI-configuratie of environment variable, en klaar.
Wie gebruikt het: Stripe CLI (als login-optie), npm, pip, de meeste AI-codingtools als fallback (Claude Code via ANTHROPIC_API_KEY, OpenAI-tools via OPENAI_API_KEY, Aider)
sk_live_, ghp_, npm_)~/.config/stripe/config.toml, ~/.aws/credentials) of een environment variableDe CLI leest die bij het opstarten uit en stuurt hem mee in API-requests, meestal als Bearer token in de Authorization-header.
Voor automatisering zijn API-keys ongeëvenaard. Ze werken in CI/CD, containers, scripts, cronjobs. Alles wat een environment variable kan lezen. Geen browser nodig, geen interactieve prompts, geen tokenrefresh.
Voor AI-agent-workflows zijn API-keys de makkelijkste manier. Als Claude Code of Cursor een API moet aanroepen, is een env variable met een API-key de snelste optie.
Slim omgaan met API-keys? Wissel ze runtime om voor tokens met beperkte geldigheid.
AWS was hierop een voorloper met STS (Security Token Service). Je langlevende credentials zijn er alleen om tijdelijke credentials aan te vragen die binnen een uur verlopen. Tools als aws-vault automatiseren dit volledig.
Zelfs als je met API-keys begint, kun je dit patroon toevoegen. Dat beperkt de schade van een gelekte key van "tot iemand het merkt" tot "één uur".
Deze OAuth 2.0-flow is bedoeld voor machine-to-machine authenticatie: services die zonder menselijke interactie communiceren.
Gebruikt in: CI/CD pipelines, achtergrondservices, geautomatiseerde tools
De service stuurt zijn client_id en client_secret direct naar de authenticatieserver en krijgt een tijdelijke access token terug. Geen browser, geen interactie, geen redirect.
Gebruik client credentials wanneer:
Gebruik het niet voor menselijke authenticatie. Het ondersteunt geen MFA, SSO of interactieve verificatie.
Hier is een bijgewerkt overzicht obv documentatie en code. Veel artikelen zitten ernaast omdat tools hun standaardinstellingen regelmatig wijzigen.
| CLI-tool | Standaard authenticatie | Fallback-opties | Tokenopslag |
|---|---|---|---|
GitHub CLI (gh) | Device code flow via browser | PAT (--with-token), env (GH_TOKEN) | OS keychain (fallback: tekstbestand) |
| AWS CLI v2 | PKCE auth code flow (SSO) | Device code (--use-device-code), credential-bestanden | ~/.aws/sso/cache/ |
Azure CLI (az) | WAM op Windows; browserauth flow op Linux/macOS | Device code (--use-device-code) | ~/.azure/msal_token_cache.* |
| Vercel CLI | Device code flow (nieuw standaard, sep 2025) | API-token (--token, env variable) | ~/.local/share/com.vercel.cli/auth.json |
| Stripe CLI | Browser-based pairing flow | API-key (--interactive, --api-key, of env) | ~/.config/stripe/config.toml |
| gcloud CLI | Browser OAuth | --no-browser handmatig | ~/.config/gcloud/ |
| Claude Code | Browser OAuth | API-key (env var, apiKeyHelper) | OS keychain / ~/.claude/.credentials.json |
| OpenAI Codex CLI | Browser OAuth | Device code (beta), API-key | ~/.codex/auth.json / OS keyring |
| Terraform CLI | Browser OAuth | Token plakken | ~/.terraform.d/credentials.tfrc.json |
De trend is duidelijk: browser-gebaseerde OAuth is de standaard voor lokale ontwikkeling, device code flow als fallback voor headless, en API-keys voor automatisering. PKCE wordt veel gebruikt als veiligste optie waar een browser beschikbaar is.
Authenticatie juist regelen heeft geen zin als je tokens verkeerd opslaat.
Elk groot besturingssysteem heeft een ingebouwde versleutelde credential store:
Deze bieden OS-encryptie, toegangscontrole en eventueel hardware-integratie. Je CLI hoeft zelf geen kryptografie toe te voegen.
Is een keychain niet beschikbaar (containers, minimalistische Linux installs), gebruik dan versleutelde configfiles met restrictieve permissies:
Platte tekstbestanden. Dat zou duidelijk moeten zijn, maar veel tools doen dit nog. Een plaintext tokenbestand is toegankelijk voor ieder proces onder je gebruiker, elke backuptool en wie even toegang krijgt tot je machine.
Environment variables voor langdurige opslag. Env vars zijn zichtbaar in processen, worden soms gelogd in crash reports, en doorgegeven aan child-processen. Voor CI/CD (waar het platform de secret beheert) kan het, maar voor lokaal is het riskant.
Browser localStorage. Heeft je CLI een webcomponent, gebruik dan geen localStorage voor tokens. Eén XSS-lek en alles ligt op straat.
Maak deze kortlevend. Eén uur is gangbaar. Als een access token vervalt, moet de CLI hem stilletjes vernieuwen. De gebruiker hoeft daarvoor normaal niet opnieuw in te loggen.
Refresh tokens zijn de langdurige aanmeldgegevens waarmee je nieuwe access tokens kunt krijgen zonder opnieuw te authenticeren. Ze zijn gewilde doelwitten voor aanvallers, omdat ze dagen tot maanden geldig blijven.
Moderne systemen wisselen refresh tokens bij elk gebruik:
Dit beperkt de schade van een gestolen refresh token. Probeert een aanvaller een refresh token te hergebruiken die de legitieme CLI al gebruikte, raakt de hele tokenfamilie ongeldig. Zowel de token van de aanvaller als die van de gebruiker werken dan niet meer — je moet opnieuw inloggen, maar de aanvaller blijft buiten.
Al eerder genoemd, maar het blijft belangrijk: bind altijd aan 127.0.0.1, nooit aan 0.0.0.0.
Dit gebeurt vaker dan mensen toegeven. Een debuglog, een error-handler die headers dumpt, een verbose-modus die alles print.
Docker images zijn geen geheime kluis. Elke laag is uitleesbaar.
Verloopt een token halverwege een operatie, crasht dan niet met een 401-error. Probeer ze te verversen, en vraag pas opnieuw in te loggen als ook de refresh token verlopen is.
Vraag niet om admin:* scope als je alleen repo:read nodig hebt. Dit geldt voor zowel OAuth scopes als API key-permissies.
Gebruik je CLI door een AI-agent, dan is dit nog belangrijker. Je wilt meestal niet dat een AI-assistent rechten krijgt om een repo te verwijderen, alleen maar omdat hij code mag lezen.
Wat 2026 anders maakt dan 2023: CLI's zijn niet alleen meer voor mensen die commando's typen. AI-coding-agents zoals Claude Code, Codex en Cursor's agent-modus roepen CLI-tools programmatisch aan. Dit geeft nieuwe authenticatie-uitdagingen:
Gedelegeerde machtigingen. Als Claude Code gh pr create uitvoert namens jou, gebruikt hij jouw GitHub-credentials. Maar hoort een AI-agent dezelfde rechten te hebben als jij? Volgens het principle of least privilege niet, maar de meeste tools bieden geen manier om agent-toegang te beperken.
Credential-exposure. Staat je API-key in een env variable, dan kan ieder proces hem lezen — ook het subprocess van de AI-agent. Tools als Claude Code lossen dit deels op met apiKeyHelper-scripts die tijdelijk geldige tokens genereren, maar universeel is dat nog niet.
Headless authenticatie voor agents. Een AI-agent in een sandbox-omgeving kan geen browser openen. Device code flow werkt (de gebruiker keurt goed op een ander apparaat), maar API-keys zijn de gewoonlijke oplossing omdat ze geen interactie vragen.
Audittrails. Doet een AI-agent API-calls met jouw credentials, dan lijkt het auditlog te tonen dat jij die acties uitvoerde. Er is nog geen standaard om "de mens deed dit" te onderscheiden van "de agent deed dit namens de mens".
Dit ontwikkelt zich snel. Beste wat je nu kunt doen:
Authenticatiemethode kiezen? Hier de korte versie:
"Mijn gebruikers zijn ontwikkelaars op hun lokale machine" → Browsergebaseerde OAuth met PKCE (beste beveiliging + soepelste UX)
"Mijn CLI moet werken in SSH-sessies en containers" → Device code flow als fallback, browser OAuth als primaire optie
"Dit draait in CI/CD zonder mens erbij" → Client credentials flow of gescope API-keys
"Ik wil de snelste implementatie" → API-keys (maar voeg tokenrotatie later toe)
"Enterprise-klanten willen SSO en MFA" → Elke OAuth-flow (device code of browser), want die ondersteunt alle enterprise-authenticatie
"AI-agents gaan deze CLI gebruiken" → Ondersteun API-keys (makkelijk voor agents) + browser OAuth (voor menselijke gebruikers), met beperkte rechten en kortlevende tokens
Tegen de meeste aanvallen wel, maar er is een bekende phishing-kwetsbaarheid. Een aanvaller kan een device code genereren en gebruikers misleiden die goed te keuren. Daarom maakte AWS PKCE standaard voor SSO-login. Voor headless omgevingen waar PKCE niet kan, blijft device code flow de beste keus — wees alleen alert op phishing.
Voor CI/CD: ja, want het platform slaat ze versleuteld op en injecteert ze bij runtime. Voor lokaal: niet doen. Gebruik OS keychain. Env variables zijn zichtbaar in processen, kunnen per ongeluk gelogd/gelekt worden naar child-processen.
Functioneel weinig. Beide zijn langlevende credentials voor API-aanroepen. Het verschil is vooral organisatorisch: API-keys zijn vaak per project/app gescope, personal access tokens zijn gelinkt aan een gebruikersaccount. Sommige diensten gebruiken de termen door elkaar.
Access tokens: elk uur of minder (gaat automatisch via refreshflow). Refresh tokens: roteren bij elk gebruik (de auth-server zou dit moeten doen). API-keys: minstens elke 90 dagen, of direct bij vermoeden van lek. In de praktijk vervangen de meeste teams hun API-keys pas na een incident — dat is te laat.
Drie opties, in volgorde van voorkeur:
docker run -e API_KEY=${API_KEY}) voor CI/CDdocker run -v ~/.config/tool:/root/.config/tool:ro) voor lokaalNooit credentials in het image bakken. Nooit.
MCP is de opkomende standaard voor AI-agents die connectie maken met externe tools en diensten. Het introduceert een extra auth-laag: de agent heeft credentials nodig voor de MCP-server, die op zijn beurt weer credentials nodig heeft voor achterliggende APIs. Dit wordt nog gestandaardiseerd. Voor nu gebruiken de meeste MCP-implementaties API-keys of OAuth-tokens die via de MCP-configuratie meegestuurd worden. Verwacht snelle evolutie hierin.
CLI-authenticatie verandert snel. Wat twee jaar geleden best practice was (device code flow als standaard, platte tekst-bestanden voor credentials) is nu al achterhaald. Voeg je vandaag authenticatie toe aan een CLI, begin dan met browser OAuth + PKCE voor mensen, API-keys voor automatisering, en bedenk dat straks AI-agents je belangrijkste gebruikers kunnen zijn.