GitHub OAuth 토큰 회전 업데이트: OAuth 앱 보안 설계를 바꿔야 하는 이유
GitHub가 OAuth 앱과 GitHub App 플랫폼에 보안 관련 변경을 추가했습니다. 핵심은 세 가지입니다. OAuth 앱의 expiring access token과 refresh token 지원, OAuth 앱당 최대 10개 redirect URI 등록, 그리고 GitHub App과 OAuth 앱의 redirect URI wildcard 매칭 제어입니다.
이 업데이트는 단순한 설정 화면 변경이 아닙니다. GitHub 로그인을 붙인 SaaS, 개발자 도구, CI 대시보드, 코드 분석 서비스라면 인증 토큰 수명과 callback URL 관리 방식이 운영 리스크와 바로 연결됩니다. 특히 AI 개발 도구처럼 GitHub 저장소 권한을 오래 들고 있는 서비스는 이번 변경을 보안 부채 정리 기회로 봐야 합니다.
출처: GitHub Changelog, 2026-08-14.
무엇이 바뀌었나
GitHub 발표 기준으로 OAuth 앱은 이제 사용자 인증 흐름에서 short-lived access token을 요청할 수 있습니다. 앱이 이 방식을 선택하면 access token은 8시간 동안 유효하고, refresh token은 6개월 동안 유효합니다. access token이 만료되면 refresh token으로 새 토큰 쌍을 받는 구조입니다.
도입 방식은 두 가지입니다. 첫째, 인증 요청에 offline_access scope를 포함해서 short-lived token 패턴을 테스트하고 점진적으로 적용합니다. 둘째, 앱 등록 설정에서 항상 short-lived token을 쓰도록 강제합니다. 후자는 구버전 클라이언트까지 한 번에 밀어붙이는 선택이라 배포 준비가 안 되어 있으면 장애로 이어질 수 있습니다.
Redirect URI 쪽도 바뀌었습니다. OAuth 앱 하나에 최대 10개 callback URI를 등록할 수 있습니다. 기존에는 개발, 스테이징, 프로덕션, 고객별 도메인을 처리하려고 앱을 여러 개 만들거나, redirect 처리 서버를 따로 두는 경우가 많았습니다. 이제는 환경별 callback URL을 앱 하나에서 관리할 수 있습니다.
Wildcard 매칭은 더 조심해야 합니다. wildcard는 멀티테넌트 subdomain 구조에서는 편하지만, redirect 대상 라우트를 강하게 통제하지 못하면 authorization code를 엉뚱한 경로로 보낼 여지가 생깁니다. GitHub도 사용자 콘텐츠를 호스팅하는 사이트에서는 abuse 가능성을 검토하라고 명시했습니다.
왜 AI 개발 도구에 더 중요해졌나
요즘 GitHub OAuth는 단순 로그인에만 쓰이지 않습니다. AI 코드 리뷰 도구, PR 요약 봇, 저장소 검색 에이전트, 이슈 자동 분류기, 배포 보조 도구가 모두 GitHub 권한을 요구합니다. 한 번 권한을 받은 뒤 장기간 access token을 보관하는 구조도 흔합니다.
문제는 AI 기능이 붙으면서 토큰 사용면이 넓어졌다는 점입니다. 예전에는 서버 API 몇 개가 토큰을 썼다면, 지금은 에이전트 작업 큐, 백그라운드 분석 워커, 임시 코드 실행 환경, 사용자별 MCP 서버까지 토큰 접근 경로가 늘어납니다. long-lived token 하나가 노출되면 피해 범위가 커집니다.
8시간 access token은 이런 구조를 줄이는 데 도움이 됩니다. 토큰이 유출되어도 시간 창이 짧고, refresh token을 별도 저장소와 회전 정책으로 관리할 수 있습니다. 대신 구현 난이도는 올라갑니다. refresh 실패 처리, 동시 요청 중복 갱신, revoked token 감지, 재동의 UX를 제대로 설계해야 합니다.
즉 이번 GitHub OAuth 업데이트는 “설정 켜기”가 아니라 “권한 수명 주기를 제품 코드에 반영하기”에 가깝습니다.
실제 마이그레이션에서 먼저 봐야 할 지점
첫 번째는 현재 토큰 저장 위치입니다. 데이터베이스에 access token을 평문으로 저장하고 있다면 short-lived token을 켜기 전에 암호화와 접근 제어를 먼저 정리해야 합니다. refresh token은 access token보다 오래 살기 때문에 더 민감합니다. KMS, envelope encryption, row-level 접근 제한, 감사 로그가 필요합니다.
두 번째는 refresh race condition입니다. 여러 worker가 같은 사용자 토큰으로 동시에 GitHub API를 호출하다가 access token 만료를 만나면, 모두가 refresh를 시도할 수 있습니다. 이때 마지막으로 저장된 refresh token만 유효해지는 구조라면 일부 요청이 실패합니다. 사용자별 refresh lock이나 compare-and-swap 저장 패턴을 넣어야 합니다.
세 번째는 scope 재검토입니다. refresh token을 도입하면 토큰 관리가 더 진지한 보안 자산이 됩니다. 이참에 repo 전체 권한을 정말 써야 하는지, GitHub App 권한으로 쪼갤 수 있는지 확인해야 합니다. AI 코드 분석 서비스는 읽기 권한만 필요한 경우가 많고, PR 코멘트 작성도 제한된 permission으로 처리할 수 있습니다.
네 번째는 callback URI inventory입니다. 새로 최대 10개 URI를 등록할 수 있다고 해서 모든 preview URL을 넣으면 안 됩니다. Vercel preview domain, 고객별 임시 도메인, 내부 tunnel URL이 섞이면 운영자가 어떤 redirect가 안전한지 판단하기 어려워집니다.
Wildcard redirect는 편하지만 기본값이 되면 위험하다
Wildcard matching은 멀티테넌트 SaaS에서 유혹적입니다. 예를 들어 https://*.example.com/github/callback 같은 패턴을 허용하면 고객별 subdomain을 매번 등록하지 않아도 됩니다. 하지만 OAuth redirect는 “편의”보다 “정확한 도착지 검증”이 우선입니다.
위험한 구조는 세 가지입니다. 첫째, 고객이 subdomain 콘텐츠나 route를 직접 제어할 수 있는 경우입니다. 둘째, callback path 아래에서 open redirect가 가능한 경우입니다. 셋째, preview deployment나 deleted tenant domain이 재점유될 수 있는 경우입니다.
안전하게 쓰려면 wildcard를 켜기 전에 tenant registry와 redirect 검증을 분리해야 합니다. GitHub가 보내는 code를 받는 endpoint는 고정된 인증 서버에 두고, tenant별 화면 이동은 내부 state 값 검증 후 처리하는 편이 낫습니다. state에는 CSRF 방지뿐 아니라 tenant id, nonce, 만료 시간, redirect 목적지를 넣고 서버에서 서명 검증해야 합니다.
그리고 기존에 redirect URI가 하나뿐인 앱은 legacy behavior로 wildcard matching이 켜져 있을 수 있다는 GitHub의 안내가 중요합니다. “우리는 wildcard를 켠 적이 없다”가 안전을 보장하지 않습니다. 앱 설정을 직접 열어 확인해야 합니다.
운영팀이 정해야 할 모니터링 지표
토큰 회전을 적용하면 장애가 조용히 발생할 수 있습니다. 사용자는 로그인되어 있는데 GitHub API만 실패하거나, 백그라운드 작업이 특정 사용자에서만 멈춥니다. 그래서 인증 성공률보다 token refresh 지표를 따로 봐야 합니다.
최소 지표는 다음과 같습니다. refresh 요청 수, refresh 성공률, invalid_grant 비율, 사용자 재인증 유도 수, GitHub API 401/403 발생률, worker별 refresh lock 대기 시간입니다. 배포 직후에는 사용자군별로 나눠 보는 것이 좋습니다. 오래된 데스크톱 앱, CLI, 브라우저 확장, 서버 연동 고객은 실패 양상이 다릅니다.
로그에는 토큰 값을 남기면 안 됩니다. 대신 token id hash, app id, user id, scope set hash, 만료 예정 시간, refresh 결과 코드만 남깁니다. 보안 사고 조사와 개인정보 최소화를 같이 만족시키려면 처음부터 로그 스키마를 정해야 합니다.
개발팀 적용 체크리스트
- GitHub OAuth 앱 설정에서 expiring token, multiple redirect URI, wildcard matching 상태를 확인한다.
- access token과 refresh token 저장소를 분리하고, refresh token은 KMS 기반 암호화를 적용한다.
offline_accessscope를 일부 사용자나 내부 dogfood 환경에서 먼저 테스트한다.- refresh race condition을 막기 위해 사용자별 lock 또는 CAS 업데이트를 구현한다.
- GitHub API 401/403, refresh 실패율, 재인증 전환율을 대시보드에 추가한다.
- 등록된 redirect URI 10개를 환경별로 정리하고, 불필요한 callback URL을 삭제한다.
- wildcard redirect는 기본 비활성으로 두고, 켜야 한다면 tenant registry와
state서명 검증을 함께 설계한다. - long-lived token을 전제로 만든 백그라운드 job이 있는지 찾아서 만료/재시도 로직을 넣는다.
- AI 에이전트가 GitHub 토큰을 사용하는 경로를 문서화하고, 도구 호출 로그에서 권한 사용 흔적을 추적한다.
- 새 GitHub App이나 OAuth 앱은 short-lived token 기본값을 기준으로 SDK 호환성을 검증한다.