Skip to main content
← 블로그

브라우저를 잠깐 빌리다 — 터미널 로그인의 뒷이야기

VauDium·

지난 글에서 한 문단으로 미뤄 둔 이야기. fecit:// 스킴이 막아선 자리를, gh와 gcloud가 쓰는 오래된 방식 loopback으로 우회해 토큰을 터미널로 데려온 과정.

브라우저를 잠깐 빌리다 — 터미널 로그인의 뒷이야기

지난 글에서 Fecit의 터미널 클라이언트, CLI를 소개했습니다. 거기서 로그인은 “브라우저로든 터미널로든 골라서 들어간다”고 한 문단으로 슬쩍 넘겼는데요. 사실 그 한 문단 안에 작은 모험이 있었습니다. 오늘은 그 이야기입니다.

쉬운 길과 막힌 길

아이디와 비밀번호로 들어가는 건 어렵지 않습니다. 입력받아 /api/auth/login에 던지고, 받은 토큰을 저장하면 끝입니다. 비밀번호는 화면에 별표로 가렸고요.

막힌 건 “브라우저로 로그인하고 싶다”는 한마디였습니다. 구글·애플 로그인을 터미널 안에서 처리할 수는 없으니 브라우저를 띄워야 하는데, 진짜 문제는 그다음이었습니다. 브라우저에서 로그인이 끝난 뒤, 그 결과를 어떻게 터미널로 돌려받느냐.

fecit:// 가 막아선 자리

확인해 보니 Fecit는 이미 브라우저 로그인 페이지를 운영하고 있었습니다. 데스크톱 앱이 쓰는 페이지였죠. 흐름은 이랬습니다. 브라우저에서 구글 로그인 → 토큰 발급 → fecit://auth/callback?access_token=... 으로 이동. 마지막의 fecit://는 운영체제가 데스크톱 앱에게 넘겨주라고 약속된 커스텀 주소입니다. 데스크톱 앱은 그 주소를 낚아채 토큰을 꺼냅니다.

CLI에게는 이게 닫힌 문이었습니다. fecit://는 이미 데스크톱 앱이 차지하고 있고, 맨몸의 실행 파일 하나가 운영체제에 “그 주소는 내가 받겠다”고 등록하는 건 번거롭고 충돌도 납니다. 토큰이 코앞까지 와서 엉뚱한 곳으로 빠지는 셈이었습니다.

브라우저를 잠깐 빌리는 법

답은 의외로 오래된 방식이었습니다. gh, gcloud, vercel 같은 도구들이 다 쓰는 그 방법, loopback입니다.

CLI가 자기 컴퓨터 안에 아주 잠깐 작은 웹 서버를 엽니다. http://127.0.0.1의 임의의 포트에요. 그리고 브라우저로 로그인 페이지를 열되, 한마디를 덧붙입니다. “끝나면 fecit://로 가지 말고, 방금 내가 연 이 주소로 토큰을 보내 줘.” 사용자가 브라우저에서 로그인을 마치면, 페이지는 토큰을 그 localhost 주소로 돌려보냅니다. 바깥으로 나간 적 없는, 내 컴퓨터 안에서만 오간 왕복입니다.

백엔드는 한 군데만

백엔드는 딱 한 곳만 손봤습니다. 로그인 페이지가 “어디로 돌려보낼지”를 주소창의 값에서 읽도록.

단, 아무 데로나 보내면 안 됩니다. 누군가 ?redirect=악성주소 가 박힌 링크를 흘려, 남이 로그인한 토큰을 자기 서버로 가로챌 수 있으니까요. 그래서 127.0.0.1localhost만 허용하도록 막았습니다. 그 검증 코드는 우리가 내려보내는 페이지 안에 있으니, 공격자가 건드릴 수 있는 건 주소창의 값뿐입니다. 거기에 더해, 매번 무작위 값(state)을 하나 끼워 보내고 돌아온 값과 맞춰, 지금 받은 게 내가 보낸 그 요청이 맞는지 확인합니다.

어느 길이든 같은 통로

여기까지 오니 그 로그인 페이지가 더 쓸모 있어졌습니다. 거기엔 이미 구글·애플 버튼이 나란히 있었고, 거기에 아이디·비밀번호 입력칸까지 더했습니다. 이제 fecit login을 치면 브라우저가 열리고, 구글이든 애플이든 아이디·비밀번호든 셋 다 그 화면에서 고릅니다. 어느 길로 들어오든 토큰은 같은 localhost 통로로 돌아옵니다. 터미널은 그동안 조용히 기다리다, 토큰이 도착하면 한 줄로 인사합니다.

남는 생각

처음엔 “브라우저 로그인을 하려면 백엔드를 크게 뜯어야 하나” 싶었습니다. 그런데 막상 풀고 보니, 이미 있던 로그인 페이지를 거의 그대로 빌려 쓰고, 바뀐 건 “어디로 돌려보낼지”를 읽는 HTML 몇 줄과, 잠깐 떴다 사라지는 localhost 서버 하나뿐이었습니다.

새로 짓기보다 있는 걸 빌려 쓰는 쪽이 대개 더 멀리 갑니다. 브라우저도, 로그인 페이지도, 잠깐 빌렸다 돌려준 셈입니다.