-
[Supabase][인증] signing key rotation 뒤 old JWT 유예와 JWKS 캐시를 어디까지 기다리고 언제 revoke하나기타개발지식/풀스택개발 2026. 8. 15. 09:16
IT 리서치 노트
[Supabase][인증] signing key rotation 뒤 old JWT 유예와 JWKS 캐시를 어디까지 기다리고 언제 revoke하나
Supabase signing key rotation을 해 본 팀이라면 rotate 버튼을 누른 뒤 old JWT를 어디까지 살려 두고 언제 revoke해야 하는지가 가장 애매할 때가 많다. 하지만 2026년 8월 15일 기준 Supabase 공식 문서를 다시 보면 JWKS endpoint는 edge와 client library 캐시를 타고, JWT guide는 standby key 생성이나 이전 key revoke 때 최소 20분 대기를 권장한다. 이 글은 signing key rotation 뒤 old JWT 유예와 JWKS 캐시를 어떤 시간축으로 읽어야 안전한지 정리한다.
1. 개요
결론부터 말하면 Supabase signing key rotation 뒤에는
standby key가 모든 verifier에 퍼질 시간,old JWT access token TTL,앱 쪽 JWKS 캐시 수명을 같은 시간축으로 적어야 한다. 자체 JWKS verifier가 있는 상태에서 rotate 직후 바로 revoke하면 valid token 거절과 old key 신뢰가 둘 다 섞일 수 있다.즉 첫 질문은 "rotate는 끝났나"가 아니라 "누가 아직 old JWT를 검증하고 있고, 누가 아직 새 public key를 못 봤나"다. getClaims와 Supabase client library 위주 경로인지, createRemoteJWKSet 같은 자체 verifier 경로인지에 따라 기다려야 할 근거가 달라진다.
2. 어디서 실제로 막히는가
실무에서 자주 꼬이는 패턴은 네 가지다. 첫째, standby key를 만든 직후 곧바로 rotate한다. 둘째, rotate 직후 old JWT가 몇 분 더 통과하자 revoke가 안 먹는다고 오해한다. 셋째, 반대로 너무 빨리 revoke해서 아직 valid한 old JWT를 앱 backend가 거절한다. 넷째, Supabase edge cache와 자체 backend cache를 한 숫자로만 적는다.
Supabase signing keys 문서는 JWKS endpoint가 edge에서 10분 캐시되고 client libraries도 메모리에 추가 10분 캐시할 수 있다고 설명한다. 같은 문서는 urgent revoke 상황에서 앱 backend 일부가 revoked key를 잠시 더 신뢰할 수 있다고 경고한다. JWT guide는 standby key 생성이나 이전 key revoke 때 최소 20분 대기를 권장하고, 자체 verifier 예시로 createRemoteJWKSet을 보여 준다.
이 문서들을 같이 읽으면 rotation은 단일 버튼 작업이 아니다. 새 key를 JWKS에 노출하고, verifier가 그 key를 보게 하고, old JWT TTL을 소진시키고, 그 뒤 revoke하는 일련의 시간축 작업이다. 특히 custom backend verifier가 있다면 Supabase 기본 캐시보다 더 긴 앱 캐시가 숨어 있을 수 있다.
- 증상: rotate 후에도 old JWT가 통과하거나, valid token이 갑자기 거절된다.
- 실패: standby 배포 시간과 token TTL을 같은 숫자로 적는다.
- 막힘: edge cache와 app cache를 분리 기록하지 않는다.
- 누락: 긴급 revoke와 정상 rotation runbook을 같은 순서로 둔다.
보이는 현상 먼저 볼 값 판단 기준 rotate 직후 일부 verifier만 실패한다 JWKS cache와 custom app cache 새 standby key를 아직 못 본 verifier가 있는지 본다 revoke 뒤 old JWT가 잠깐 더 통과한다 cache purge 여부 긴급 사고인지 정상 rotation인지 먼저 나눈다 valid token이 갑자기 거절된다 old JWT TTL과 revoke 시각 TTL 소진 전에 previous key를 내렸는지 본다 3. 실무에서 적용하는 순서
실무 순서는 다섯 단계가 가장 안전하다. 먼저 verifier inventory를 만든다. 다음으로 standby signing key를 만들고 최소 20분을 기다린다. 세 번째로 rotate를 실행한다. 네 번째로 old JWT access token TTL과 app cache window가 지나갈 때까지 기다린다. 마지막으로 previous key를 revoke한다.
- getClaims, client library, custom JWKS verifier, HS256 direct check를 inventory로 적는다.
- standby key 생성 뒤 최소 20분 대기한다.
- rotate 실행 시각을 기록한다.
- old JWT TTL과 app cache 소진 시각을 계산한다.
- 그 뒤에만 previous key revoke를 실행한다.
실행할 때는 JWKS URL을 조회하고, verifier 설정을 확인하고, rotation 시각을 메모 파일에 저장하고, auth 로그와 401 오류 응답을 비교하고, 필요하면 캐시 purge 명령을 실행하는 순서가 안전하다. mixed verifier 환경이라면 각 서비스의 배포 상태도 같이 확인해야 한다.
예를 들어 access token TTL이 60분이고, JWKS는 edge 10분 + client 10분 구조이며, 앱 backend가 createRemoteJWKSet 위에 추가 메모리 캐시를 5분 둔다면 earliest revoke 시각은 rotate 직후가 아니라 TTL과 cache window를 모두 지난 뒤로 잡아야 한다. 이때 직접 verifier가 없다면 대기 메모는 더 단순해질 수 있지만, mixed verifier 환경이라면 보수적으로 잡는 편이 낫다.
반대로 security incident처럼 previous key를 급히 끊어야 한다면 정상 rotation runbook을 그대로 쓰지 않는다. 앱 cache purge, 세션 무효화, 또는 Auth server 직접 검증 경로 같은 비상 절차를 같이 꺼내야 한다. Supabase 문서가 urgent revocation을 별도 문제로 적는 이유가 바로 여기 있다.
이 메모를 남기면 다음 실행에서 "왜 20분을 기다렸지"와 "왜 revoke를 1시간 뒤로 밀었지"를 따로 설명할 수 있다. rotation runbook은 숫자보다 시간축 메모가 중요하다.
4. 공식 문서와 예시 화면으로 확인하기
첫 공식 자료는 public key discovery와 caching 설명이다. signing key rotation 이후에 왜 바로 revoke하지 말아야 하는지 이해하려면 이 캐시 구조를 먼저 봐야 한다.
즉 rotation 문제는 키를 만들고 바꾸는 작업만이 아니라, 어떤 verifier가 언제 새 public key를 보게 되는지의 문제다. 특히 자체 backend verifier가 있으면 캐시 층을 따로 읽어야 한다.
두 번째 자료는 캐시 시간 그 자체를 보여 주는 구간이다. Supabase edge 10분과 client library 추가 10분이 같이 적혀 있어 '최소 20분' 판단의 근거가 된다.
이 규칙 때문에 standby key를 만들고 곧바로 rotate하거나 revoke하면 일부 verifier는 아직 새 key를 못 본 상태일 수 있다. 직접 만든 캐시는 이보다 더 길어질 수도 있다.
세 번째 자료는 urgent key revocation 경고다. 보안 사고에서는 revoke 후에도 앱 backend 일부가 이전 key를 잠깐 더 신뢰할 수 있다는 점을 여기서 분명히 적고 있다.
따라서 보안 사고 대응과 정상 rotation은 같은 순서가 아니다. 정상 rotation은 기다림이 필요하고, 긴급 revoke는 cache busting이나 서버 직접 검증 경로까지 준비해야 한다.
네 번째 자료는 JWT guide의 권장 대기 시간이다. standby signing key 생성과 previously used key revoke를 할 때 최소 20분을 기다리라는 문장이 직접 나온다.
이미 secret key rotation과 signing key rotation 분리 글, Verify JWT와 getClaims 분기 글을 읽었다면, 이번 문장은 그 다음 단계인 wait window와 revoke 시점의 기준선이다.
다섯 번째 자료는 jose verifier 예시다. 자체 verifier를 쓰는 팀이라면 getClaims 경로와 달리 createRemoteJWKSet 기반 캐시 정책을 직접 관리할 가능성이 크다는 점을 여기서 확인해야 한다.
이 코드를 쓰는 backend가 있다면 standby key를 만들었다고 자동 반영된다고 가정하면 안 된다. 앱 쪽 캐시 수명과 purge 방법을 rotation runbook에 같이 적어야 한다.
실무에서는 standby, rotate, wait, revoke를 타임라인 표로 다시 적는 편이 가장 빠르다. old JWT 유예와 JWKS 캐시를 같은 시간축에 놓아야 revoke 시점이 선명해진다.
이 표를 기준으로 보면 rotation 직후 일부 verifier가 old JWT를 계속 받아들이는 상황과, 반대로 너무 빨리 revoke해 valid token이 거절되는 상황을 같은 언어로 설명할 수 있다.
마지막 자료는 실제 운영 메모 예시다. key 생성 시각과 cache window, token TTL, revoke 시각을 한 줄 메모로 남기면 다음 incident 대응이 빨라진다.
이 메모만 있어도 '왜 아직 old JWT가 통과하지' 또는 '왜 valid token이 갑자기 거절되지' 같은 질문을 훨씬 빨리 좁힐 수 있다. rotation 로그는 시간축 메모가 핵심이다.
5. 주의사항과 리스크
첫 번째 리스크는 standby key를 만들자마자 rotate하는 것이다. custom verifier가 새 key를 아직 못 봤다면 일부 서비스만 실패할 수 있다. 두 번째 리스크는 rotate 직후 바로 revoke하는 것이다. old JWT TTL이 살아 있으면 valid token이 backend에서 거절될 수 있다. 세 번째 리스크는 긴급 revoke와 정상 rotation을 같은 runbook으로 처리하는 것이다.
운영 전에 확인할 때는 최소한
standby_created_at,wait_before_rotate,access_token_ttl,app_cache_window,revoke_at다섯 값을 같은 표에 두는 편이 좋다. 이 다섯 칸이 없으면 old JWT 유예와 cache delay가 계속 섞인다. 담당자는 verifier 설정, purge 명령, auth 로그, 실패 응답, 배포 파일 변경을 같이 남겨야 revoke 판단을 재검증할 수 있다.- standby key는 verifier에 먼저 퍼져야 한다.
- revoke 시각은 token TTL과 cache window 뒤로 잡는다.
- 긴급 사고는 cache purge runbook을 별도로 둔다.
6. 결론
Supabase signing key rotation 뒤 old JWT와 JWKS 캐시는 같은 문제다. standby key를 먼저 퍼뜨리고, rotate 뒤에는 token TTL과 cache window를 지나서 revoke하는 편이 가장 안전하다. 자체 verifier가 있는 팀일수록 이 시간축 메모를 더 엄격하게 남겨야 한다.
- standby key 생성 뒤 최소 20분 대기한다.
- rotate 뒤 old JWT TTL과 app cache를 함께 계산한다.
- previous key revoke는 가장 마지막 단계다.
정상 rotation 시간을 이미 이해했다면, 실제 사고에서는 긴급 revoke에서 cache purge와 session invalidation을 같이 움직이는 follow-up 글로 이어서 verifier inventory와 비상 절차를 따로 적어 두는 편이 안전하다.
7. 참고 링크
'기타개발지식 > 풀스택개발' 카테고리의 다른 글