출연 · 서하늘(21) / 아이디 / 액세스 / 리프레시
소재 · codex login 이 발급하는 토큰 3종
읽는 데 3분 · 사전지식 0 · 인터넷 없어도 열림
새벽 3시 14분. 교양 「디지털 사회의 이해」 과제 마감까지 다섯 시간.
서하늘주제가… “당신이 매일 쓰는 도구 하나를 골라, 그 안에서 실제로 무슨 일이 일어나는지 설명하시오”???
서하늘저 codex login 한 번 치고 “Successfully logged in” 뜬 거 본 게 전부인데요.
…망했다
02 · 그 1초 사이에
“로그인 성공!” 이 한 줄 뒤에서
브라우저가 잠깐 열렸다 닫히는 그 1초 사이에, 하늘이 노트북 안 방 하나에 세 명이 이사를 왔다.
우당탕탕
서하늘…누구세요?
방 주소는 진짜로 있다. 맥·리눅스 기준 ~/.codex/auth.json. 로그인하면 이 파일 하나에 토큰 세 개가 나란히 저장된다.
03 · 첫 번째 질문
근데 왜 셋이야? 한 명이 다 하면 안 돼?
리프레시만능 카드 한 장을 상상해 봐. 내가 누군지도 적혀 있고, 문도 다 열리고, 유효기간도 없어. 편하지?
서하늘완전 좋은데요?
리프레시그 카드가 요청 보낼 때마다 인터넷을 건너간다는 게 문제야. 하루에도 수백 번. 딱 한 번만 흘리면 끝이고, 만료가 없으니 영원히 남의 거야.
서하늘그럼 유효기간을 짧게 하면요?
리프레시한 시간마다 다시 로그인. 안전하긴 한데 아무도 안 써.
그래서 → 쪼갰다
자주 내미는 카드는 짧게, 깊이 숨겨두는 카드는 길게. 이 한 문장이 방에 셋이 사는 이유의 전부다.
이렇게 쪼개는 방식을 OAuth 라고 부른다. 구글 로그인·GitHub 연동 같은 “○○으로 로그인” 버튼이 전부 같은 규약이다.
04 · 세입자 소개
아이디 id_token
“너 누구야?”에만 답하는 애
⏱ 1시간
아이디안녕하세요! 이름, 이메일, 어떤 계정으로 로그인하셨는지… 아 잠깐만요 프로필 유효기간 끝났다 새로 받고 올게요
서하늘방금 자기소개 시작하지 않았어요?
아이디는 문을 못 연다. 하는 일이 신원 확인 하나뿐이라 그렇다.
액세스 access_token
“들어가도 돼?”에 답하고 실제로 뛰는 애
⏱ 약 10일
액세스저는 요청 있을 때마다 서버까지 뛰어갑니다. 제 카드엔 “누구냐”가 아니라 “뭘 할 수 있냐”가 적혀 있어요. 다녀오겠습니다
다다다다
리프레시 refresh_token
“표 새로 줘” — 장롱 밖으로 안 나오는 실세
⏱ 해지할 때까지
리프레시나는 안 나가. 앞의 둘이 만료되면 내가 도장 찍어서 새로 태어나게 하는 게 일이야.
서하늘그래서 제가 몇 달째 재로그인을 안 해도 됐던 거예요?
리프레시응. 전부 나 때문이야.
수명이 현실과 거꾸로다. 진짜 여권은 10년, 탑승권은 하루다. 여기선 신분증(1시간)이 제일 짧다 — 얼마나 오래 유효하냐가 아니라 얼마나 자주 내미느냐가 수명을 정하기 때문.
05 · 결정적 한 줄
같은 사람 카드인데 왜 서로 못 바꿔 쓸까
서하늘둘 다 제 건데 그냥 바꿔 내면 안 돼요?
아이디학생증으로 편의점에서 술 못 사잖아요. 주민등록증으로는 도서관 책 못 빌리고요.
서하늘…같은 나인데.
아이디같은 나여도 내미는 창구가 다르니까요.
토큰 안에 aud(audience, 수신자)라는 줄이 있다. “이 카드는 어느 창구에 내미는 것인가”를 못박아 둔 값. 아이디의 aud는 CLI 앱, 액세스의 aud는 API 서버다. 그래서 아이디가 새어나가도 그것만으론 서버를 부를 수 없다 — 피해 범위를 미리 잘라둔 설계.
항목
아이디
액세스
내미는 곳
CLI 앱
API 서버
적힌 것
이름·이메일
권한·구독등급
수명
1시간
약 10일
06 · 반전 1
“암호화된 거 아니었어요?”
서하늘토큰이 eyJhbGciOi… 이렇게 외계어잖아요. 남이 봐도 못 읽는 거죠?
아이디아뇨. 그거 잠긴 게 아니라 접혀 있는 거예요.
…네?
JWT는 잠긴 상자가 아니라 봉인된 봉투다. 서명은 위조를 막을 뿐 열람을 막지 않는다. 점(.) 두 개로 나뉜 가운데 조각만 되펴면 이메일·이름·조직명·구독등급이 그대로 나온다. 도구도 필요 없다.
서하늘제 이메일이랑 이름이 그냥 다 보이는데요?!
아이디한 글자라도 고치면 도장이 깨져서 서버가 바로 거부해요. 근데 읽는 건 누구나 돼요.
그래서 온라인 JWT 디코더 사이트에 진짜 토큰을 붙여넣으면 안 된다. 비공개인 줄 알고 올렸는데 전체공개였던 것과 똑같은 사고가 난다.
07 · 한 달 만에 켰는데
왜 다시 로그인하라고 안 할까?
1
codex 실행 — 요청 보내기 직전에 액세스의 유효기간을 확인한다
2
아직 살아 있으면 그대로 사용 → 끝
3
만료됐으면 리프레시가 장롱에서 계약서를 꺼내 카운터에 제출
4
새 카드 두 장이 나온다 → 원래 하려던 요청이 아무 일 없었다는 듯 이어짐
✕
거절되면 그때서야 “codex login 을 다시 하세요”
서하늘오래 안 쓰다가 켜면 첫 명령만 유난히 느렸던 거… 그것 때문이에요?
리프레시맞아. 그 사이에 내가 일한 거야.
백그라운드 타이머가 도는 게 아니라 필요할 때만 갱신한다. 비밀번호도, 브라우저도, 사용자 개입도 없다. 갱신이 실제로 일어났는지는 auth.json 의 last_refresh 값으로 확인할 수 있다.
08 · 위기
“이 파일 그냥 복사하면 안 돼요?”
서하늘학교 컴퓨터에서도 쓰고 싶은데, auth.json 카톡으로 저한테 보내면 되지 않나요?
…………
리프레시하늘아. 그건 집 열쇠, 신분증, 도장을 한 봉투에 넣어 단톡방에 올리는 거야.
서하늘죄송합니다
세 장 중 제일 위험한 건 리프레시다. 재발급 요청에는 비밀번호가 필요 없다 — 뒤집으면 그 문자열만 손에 넣으면 누구든 똑같이 보낼 수 있다는 뜻이다. 남이 계속 새 카드를 뽑아 쓸 수 있다.
09 · 반전 2 — 회전
그런데 사실, 훔쳐가도 곧 들킨다
리프레시내 계약서는 쓸 때마다 새것으로 바뀌고 옛것은 버려져.
서하늘귀찮게 왜요?
리프레시도둑이 나보다 먼저 쓰면, 내 계약서는 이미 무효가 돼 있거든. 그럼 내 쪽에서 실패가 나.
!
서버: “같은 번호가 두 번 쓰였다”
✕
도난으로 간주 → 로그인 전체를 끊어버린다
들켰다
이게 아까 그 질문의 진짜 대답이다.auth.json 을 두 대에 복사해 쓰면 두 컴퓨터가 서로를 로그아웃시키며 싸운다. 서버 입장에선 도난과 구분이 안 돼 세션이 통째로 끊길 수 있다. 머신마다 따로 로그인하는 게 맞다.
10 · 집 규칙 3개
1
파일 권한은 600 — 나만 읽기
2
git 에 커밋하지 않기 · 도커 이미지에 굽지 않기
3
슬랙·메신저에 붙여넣지 않기 — 캡처도 포함
액세스참고로 저 하나 잃어버리면 남이 10일간 대신 씁니다. 리프레시 잃어버리면 기간이 없고요.
11 · 그래도 쫓겨나는 날
리프레시가 죽으면 그때는 사람이 다시 로그인해야 한다. 이유는 다섯 가지쯤.
원인
무슨 일이 일어난 건가
codex logout
기록 삭제 — 즉시 무효 (단, 이미 나간 액세스는 만료까지 살아 있음)
비번 변경
기존 세션을 전부 무효화하는 게 보통
회전 충돌
같은 번호 두 번 사용 → 도난 간주
장기 미사용
서버 정책상 만료
구독 만료
토큰은 멀쩡한데 권한만 빠짐 ⚠️
서하늘마지막 거 뭔가 억울한데요.
리프레시제일 자주 부딪히는 게 그거야. 로그인은 멀쩡한데 요청만 거부되는 상황.
이때는 토큰 문제가 아니라 결제 문제다. 엉뚱한 데서 원인을 찾다 시간을 날리기 딱 좋은 지점.
쪽지시험 — 셋 중 하나만 남에게 보이면 안 된다면?
리프레시(refresh_token). 나머지 둘은 각각 1시간·10일이면 알아서 죽지만, 리프레시는 그 하나로 나머지 둘을 무한히 다시 뽑아낼 수 있다. 아이디가 새면? 창구(aud)가 달라서 그것만으론 서버를 부르지 못한다.
12 · 아침 8시
서하늘과제 제목: 「방 하나에 세 명이 사는 이유 — 내가 매일 누르는 로그인 버튼의 구조」