CLI 인증 제대로 하기: 모든 4가지 방법 완전 가이드
중요한 4가지 CLI 인증 방식, GitHub, AWS, AI 도구들이 이를 어떻게 구현하는지, 그리고 반드시 피해야 할 보안 실수까지 모두 담았습니다.
모든 개발자용 CLI는 첫 번째 명령어로 login을 제공합니다. 그리고 CLI마다 인증을 해결하는 방식이 제각각입니다.
GitHub는 코드를 보여주고 브라우저를 열어서 인증을 유도합니다. AWS는 PKCE 기반의 SSO를 위해 브라우저를 엽니다. Stripe는 대시보드에서 페어링 코드를 입력하게 하죠. 최근의 AI 도구들(Claude Code, OpenAI Codex CLI, Cursor)도 각자의 방식을 택했습니다.
CLI를 만든다면, 인증(auth)은 처음에 해결해야 할 것 중 하나입니다. 잘못된 방식을 고르면 바로 알게 됩니다: 사용자들의 불만, 보안 감사, 혹은 둘 다. 그리고 최근 AI 코딩 에이전트들이 CLI 도구를 프로그래밍적으로 호출하는 흐름이 생기면서, 위험성은 더 커졌습니다: 이제 단순히 사람만 인증하지 않습니다. 자격증명을 자율 프로세스에 넘길 수도 있기 때문입니다.
중요한 4가지 인증 방식, 대형 도구들이 이를 어떻게 구현하는지, 그리고 반드시 피해야 할 실수를 정리했습니다.
네 가지 방식 한눈에 보기
자세히 들어가기 전에, 빠른 비교입니다:
| 방식 | 추천 상황 | 보안성 | 브라우저 필요? |
|---|---|---|---|
| OAuth Device Code Flow | 헤드리스 환경, SSH | 높음 | 아니오 (동일 기기에서는 필요 없음) |
| 브라우저 기반 OAuth (localhost 리디렉트) | 로컬 개발 | 매우 높음 | 예 |
| API 키 / PAT | 자동화, CI/CD, 빠른 프로토타입 | 중간 | 아니오 |
| 클라이언트 자격증명 | 기계 간, 서비스간 | 높음 | 아니오 |
각 방식마다 트레이드오프가 있습니다. 하나씩 알아보겠습니다.
1. OAuth 디바이스 코드 플로우 (RFC 8628)
이 방식은 CLI가 ABCD-1234 같은 코드와 URL을 보여주고, 아무 기기나 열어서 코드를 입력하라고 안내하는 패턴입니다.
사용 사례: GitHub CLI (기본), Azure CLI (--use-device-code 옵션), Vercel CLI (최근 기본값 전환), OpenAI Codex CLI (베타 옵션)
동작 방식
cli login을 실행합니다.- CLI가 인증 서버에 device code를 요청합니다. 이때
client_id와 scope를 보냅니다. - 서버는 세 가지 정보를 반환합니다:
device_code(내부 식별자),user_code(사용자가 입력할 짧은 코드),verification_uri(접속할 URL) - CLI가 코드와 URL을 출력하고, 5초마다 인증 서버에 폴링을 시작합니다.
- 아무 기기(휴대폰, 노트북, 다른 PC)에서 해당 URL에 접속, 코드를 입력, 원하는 방식(비밀번호, SSO, 패스키, MFA 등)으로 인증합니다.
- 승인이 완료되면, 다음 폴링에 access token과 refresh token을 반환합니다.
- CLI가 토큰을 저장하고 인증이 완료됩니다.
개발자들이 좋아하는 이유
가장 큰 장점: 어디서든 동작합니다. 원격 서버 SSH 세션? OK. Docker 컨테이너 안? OK. 로컬 브라우저 없는 클라우드 IDE? OK. 브라우저가 CLI와 같은 기기일 필요가 없습니다.
또한 모든 엔터프라이즈 인증(SAML, OIDC, MFA)을 지원합니다. 인증은 터미널이 아니라 브라우저에서 이루어지기 때문이죠. CLI는 절대 비밀번호를 직접 보지 않습니다.
대부분이 놓치는 보안 함정
디바이스 코드 플로우에는 피싱 문제가 있습니다. 공격자가 디바이스 코드 요청을 생성해 유효한 user code를 얻어낸 후, 사용자를 속여 해당 코드를 입력하게 한다면 공격자의 세션에 권한을 부여하게 됩니다. 이 는 이론이 아닙니다. 보안 연구자들은 AWS SSO 디바이스 코드 인증 방식에 대한 공격 사례도 보고했습니다.
이 때문에 AWS는 기본값을 변경했습니다. AWS CLI v2.22.0부터 aws sso login의 기본 인증 방식이 디바이스 코드 플로우에서 PKCE 기반 권한 코드 플로우로 바뀌었습니다. 디바이스 코드는 --use-device-code 옵션을 통해 여전히 쓸 수 있지만, 더 이상 기본 경로가 아닙니다.
한편, 마이크로소프트도 테넌트 차원에서 디바이스 코드 플로우 차단을 도입하며, 이 방식을 고위험으로 분류하고 있습니다.
이렇게 갈라진 모습입니다: Vercel은 2025년 9월 디바이스 코드 플로우를 기본으로 채택했고, AWS는 제거했습니다. 결국 브라우저를 여는 게 불가능한 환경에서는 디바이스 코드 플로우가 유용하지만, 가능하다면 PKCE가 더 안전하다는 결론입니다.
인증 서비스 쪽 수요도 늘고 있습니다. Logto는 v1.38.0(오픈소스)과 Logto Cloud에서 OAuth 2.0 디바이스 인증 지원을 출시했습니다. 이제 네이티브 앱의 인증 방식으로 디바이스 플로우를 활성화할 수 있습니다. CLI를 만든다면 의미 있는 변화입니다. RFC 8628을 올바르게 구현(코드 만료, 폴링 제한, UX 등)하는 건 대부분 팀의 예상보다 어렵고, 인증 서비스 쪽에서 이를 지원하면 HTTP 콜만 구현하면 됩니다.
RFC의 기술적 디테일
- device code의
expires_in값은 인증 서버가 정합니다. RFC 예시는 1800초(30분)이지만, 고정값은 아닙니다. - 서버가 폴링
interval을 명시하지 않으면, 클라이언트는 5초를 기본값으로 써야 합니다. slow_down에러가 오면, 인터벌을 5초 늘려야 합니다.- device code는 반드시 1회용이어야 하며, 신속하게 만료되어야 합니다.
- 모든 토큰 교환은 HTTPS로만 이루어져야 합니다.
2. 브라우저 기반 OAuth (localhost 리디렉트)
로컬 기기에서 뛰는 CLI 대다수의 표준 방식입니다. login을 실행하면 브라우저가 열리고, 인증 후 브라우저가 CLI가 띄운 로컬 서버로 리디렉트됩니다. 최신 구현체들은 PKCE(픽시, Proof Key for Code Exchange)를 추가해서 보안성을 더욱 높였습니다.
사용 사례: Claude Code, gcloud CLI, Terraform CLI, AWS CLI v2.22+ (SSO, PKCE 기본)
동작 방식
cli login실행- CLI가 임시 HTTP 서버를 랜덤 로컬 포트(예:
http://127.0.0.1:8742)에 띄움 - 인증 제공자의 권한 요청 endpoint로 브라우저를 열며, redirect URI로 localhost 주소를 전달
- 브라우저에서 SSO, 비밀번호, 패스키 등으로 인증
- 인증 제공자가 브라우저를
http://127.0.0.1:8742/callback?code=XXXX&state=YYYY로 리디렉트 - 로컬 서버가 authorization code를 캡처, 백엔드 HTTPS 요청으로 토큰 교환
- 브라우저에 “성공! 이 탭을 닫아도 좋습니다” 안내
- CLI가 토큰 저장 후 로컬 서버 종료
사용자 경험이 매우 매끄럽습니다. 코드를 복사할 필요 없음. URL도 직접 입력할 필요 없음. 그냥 브라우저 탭이 열렸다가 닫힙니다.
동작하지 않는 케이스
CLI가 로컬 브라우저를 열거나 localhost에 바인딩할 수 없는 환경에서는 사용할 수 없습니다:
- 원격 서버 SSH 세션
- Docker 컨테이너(포트 포워딩 없으면 불가)
- CI/CD 파이프라인
- 헤드리스 서버
- 일부 보안 제한 기업 환경
그래서 대부분 브라우저 OAuth 중심 도구는 백업 인증 방식을 제공합니다. 주로 device code flow나 API 키입니다.

