OIDC 토큰은 왜 audience까지 좁혀야 할까: Vercel custom audiences로 보는 재사용 방지
배포 환경에서 발급된 짧은 수명의 토큰도, 다른 서비스에 재사용되지 않게 하려면 어떤 claim을 검증해야 할까?
OIDC 토큰은 왜 audience까지 좁혀야 할까: Vercel custom audiences로 보는 재사용 방지
- 카테고리: infra_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: 배포 환경에서 발급된 짧은 수명의 토큰도, 다른 서비스에 재사용되지 않게 하려면 어떤 claim을 검증해야 할까?
- 핵심 출처:
- Custom OIDC Token Audiences - 2026-06-23, 확인일 2026-06-23
- OpenID Connect (OIDC) Federation - 문서, 확인일 2026-06-23
- Connect to your own API - 문서, 확인일 2026-06-23
- OIDC Federation Reference - 문서, 확인일 2026-06-23
- Vercel Connect: Secure access to external services for your agents - 2026-06-17, 확인일 2026-06-23
1. 왜 지금 봐야 하나
배포 secret을 줄이는 흐름은 이제 익숙해졌다. GitHub Actions나 Vercel 같은 실행 환경이 OIDC 토큰을 발급하고, AWS·GCP·Azure·자체 API가 그 토큰을 검증한 뒤 짧은 수명의 자격 증명으로 바꿔준다. 이렇게 하면 .env에 장기 access key를 넣지 않아도 된다.
그런데 장기 secret을 없앴다고 보안 설계가 끝나는 것은 아니다. 짧은 수명의 토큰도 어디에서 발급됐는지, 어떤 프로젝트/환경에서 왔는지, 어떤 서비스가 받는 토큰인지를 검증하지 않으면 재사용될 수 있다.
Vercel은 2026년 6월 23일 OIDC issuer가 custom audience를 지원한다고 발표했다. 기존 Vercel OIDC 토큰은 audience가 https://vercel.com/{owner}처럼 팀 단위로 고정돼 있었지만, 새 exchange service를 통해 sts.amazonaws.com이나 사내 API 식별자처럼 downstream service별 audience를 가진 토큰을 요청할 수 있게 됐다. 발표문은 provider가 침해되더라도 토큰을 다른 provider에 replay하지 못하게 하는 것이 custom audience의 핵심 이유라고 설명한다.
오늘 가져갈 핵심은 이것이다.
OIDC 기반 배포 보안은 “secret을 없애기”에서 끝나지 않는다. 토큰의 audience, issuer, subject, expiration, token id를 함께 검증해야 서비스 간 재사용 경로를 줄일 수 있다.
2. 핵심 개념
오늘의 핵심 개념은 audience-bound token이다.
JWT/OIDC 토큰에는 여러 claim이 있다. 그중 iss는 누가 발급했는지, sub는 누구 또는 어떤 workload를 대표하는지, exp는 언제 만료되는지, aud는 이 토큰을 받아야 하는 대상이 누구인지를 말한다. 많은 사고는 “토큰이 유효한가?”만 보고 “이 토큰이 우리 서비스를 위해 발급된 것인가?”를 놓칠 때 생긴다.
예를 들어 A 서비스가 Vercel 배포에서 온 토큰을 받는다. A 서비스가 iss와 서명만 검증하고 aud를 느슨하게 본다면, 원래 B 서비스에 제출하려고 발급된 토큰이 A 서비스에도 받아들여질 수 있다. 토큰이 짧게 살아도, 그 짧은 시간 안의 replay window가 열린다.
Vercel의 OIDC 문서는 기존에도 짧은 수명의 비영구 토큰을 통해 long-lived credential을 환경 변수에 저장하지 않는 이점을 설명했다. 또한 함수 실행 시 OIDC 토큰은 x-vercel-oidc-token 헤더로 제공되고, TTL은 60분이며 Vercel은 최대 45분 캐시한다고 설명한다. 즉 토큰은 “매 요청마다 완전히 새로 만들어지는 암호”가 아니라, 제한된 시간 동안 재사용 가능한 신원 증명이다. 그래서 수신 서비스의 검증 조건이 중요하다.
이번 custom audience 발표의 포인트는 exchange service다. Vercel 배포가 원래 Vercel 서명 OIDC 토큰을 받고, 이 토큰을 exchange service에 제출하면 같은 키로 서명됐지만 aud가 downstream service에 맞게 바뀐 새 토큰을 받는다. 발표문에 따르면 exchanged token은 원래 project, environment, owner, expiration claim을 보존하고, iss를 team-scoped issuer로 두며, 원래 토큰의 audience와 issued-at 정보를 act claim에 넣어 위임 사슬을 감사할 수 있게 한다. 선택적으로 jti를 지정해 특정 token exchange와 downstream API 호출을 로그에서 연결할 수도 있다.
3. 최신 이슈와 연결
최근 Vercel의 흐름을 보면 배포 환경이 단순히 “웹서버를 띄우는 곳”에서 외부 시스템에 접근하는 workload identity 발급자로 바뀌고 있다.
- OIDC Federation 문서는 Vercel이 발급한 OIDC 토큰을 AWS, GCP, Azure, 자체 API가 신뢰해 짧은 수명 credentials로 교환할 수 있다고 설명한다.
- Connect to your own API 문서는 자체 API가 Vercel의 JWKS를 사용해 토큰 서명을 검증하고,
issuer,audience,subject를 함께 확인하는 예제를 제공한다. - Custom OIDC Token Audiences 발표는 downstream service별 audience를 가진 토큰으로 replay 방어를 강화한다.
- Vercel Connect 공개 베타 발표는 앱과 agent가 Slack, GitHub, Salesforce, custom API 같은 외부 서비스에 접근할 때 장기 provider secret 대신 scoped, short-lived token을 runtime에 요청하도록 한다.
여기서 작은 팀이 배워야 할 것은 제품 이름이 아니다. 더 중요한 변화는 서비스 간 인증의 단위가 “서버에 저장된 비밀 문자열”에서 “실행 환경이 증명하는 신원 + 목적지별 제한”으로 이동한다는 점이다.
이 관점에서는 AI agent도 같은 문제를 가진다. agent가 GitHub, Slack, 사내 admin API, billing API에 접근한다면 “agent가 우리 배포에서 실행됐다”만으로 충분하지 않다. GitHub용 토큰은 GitHub에만, billing API용 토큰은 billing API에만, production 토큰은 production 자원에만 받아들여져야 한다.
4. 개발자 관점 해석
개발자가 흔히 놓치는 지점은 OIDC를 secret management 기능으로만 이해하는 것이다. 물론 장기 secret 제거는 큰 이득이다. 하지만 운영 보안에서 더 중요한 질문은 다음이다.
첫째, 수신 서비스가 audience를 엄격히 검증하는가?
Vercel의 자체 API 연동 문서는 jose.jwtVerify 예제에서 issuer, audience, subject를 함께 검증한다. 이 셋 중 하나라도 느슨하면 권한 경계가 넓어진다. 특히 custom audience를 쓰기 시작했다면 downstream API는 자기 audience가 아닌 토큰을 무조건 거절해야 한다.
둘째, subject가 프로젝트와 환경까지 좁혀져 있는가?
Vercel OIDC reference는 subject가 owner:[TEAM_SLUG]:project:[PROJECT_NAME]:environment:[ENVIRONMENT] 형태라고 설명한다. production DB를 여는 role이 preview 배포의 subject까지 허용하면, preview URL에서 production 자원에 접근하는 경로가 열린다. “같은 팀”이 아니라 “같은 프로젝트의 production 환경”인지 봐야 한다.
셋째, token exchange가 로그에서 추적 가능한가?
custom audience 발표는 jti를 선택적으로 지정해 token exchange와 downstream API call을 연결할 수 있다고 설명한다. 장애나 보안 이벤트에서 중요한 질문은 “누가 토큰을 가졌나?”가 아니라 “어떤 배포가, 어떤 audience로, 언제 토큰을 교환했고, 어떤 API 호출에 사용했나?”다. 로그에 jti, aud, sub, iss, request id를 남기면 조사 시간이 줄어든다.
넷째, provider별 실패와 침해를 분리할 수 있는가?
custom audience의 장점은 provider A에 제출된 토큰이 provider B에서 통하지 않게 만드는 것이다. 이것은 zero trust라는 큰 말보다 실용적이다. Slack connector, GitHub connector, AWS STS, 사내 API가 같은 모양의 “Vercel 토큰”을 모두 받아들이면 한 곳의 로그 유출이 여러 곳의 접근으로 번질 수 있다. audience를 나누면 피해 범위를 줄일 수 있다.
5. 내 프로젝트에 적용할 체크포인트
오늘 점검할 체크리스트는 다음과 같다.
- 모든 OIDC 수신 지점 목록화: AWS role trust policy, GCP workload identity, Azure federated credential, 사내 API, agent connector를 나열한다.
- audience 정책 명시: 각 downstream service가 기대하는
aud값을 문서화한다. “Vercel 팀 전체” 같은 넓은 audience는 임시 호환용인지 확인한다. - issuer mode 확인: Vercel OIDC 문서의 권장처럼 team issuer mode를 쓰는지, global issuer mode를 쓰는지 확인하고 JWKS URL을 맞춘다.
- subject를 환경까지 제한: production 권한은 production subject만 허용한다. preview와 development는 별도 role 또는 별도 connector를 쓴다.
- TTL과 캐시를 오해하지 않기: 함수 OIDC 토큰은 TTL 60분, 최대 45분 캐시 조건이 있으므로 “요청마다 일회용”이라고 가정하지 않는다.
- jti/request id 로깅: 가능하면 token exchange 시
jti를 부여하고 downstream 로그에jti,aud,sub,project,environment, request id를 남긴다. - agent 권한 분리: Vercel Connect 같은 scoped token 모델을 쓴다면 provider별, 환경별, 사용자별 subject를 분리하고 revoke 절차를 runbook에 넣는다.
6. 오늘 10분 액션
새 기능을 바로 붙이기 전에 현재 배포 인증을 한 장으로 그려보자.
- 종이에 “Vercel deployment”를 왼쪽에 쓰고, 오른쪽에 AWS/GCP/Azure/사내 API/GitHub/Slack 등 호출 대상 서비스를 적는다.
- 각 화살표 위에 지금 쓰는 인증 방식을 적는다. 예: env secret, OIDC, OAuth app, API key, connector.
- OIDC를 쓰는 화살표에는
iss,sub,aud,exp를 수신 쪽에서 검증하는지 체크한다. aud가 모든 서비스에서 같거나 검증되지 않는 곳에 빨간 표시를 한다.- 가장 위험한 화살표 하나를 골라 “이 서비스 전용 audience를 만들면 어떤 replay가 막히는가?”를 한 문장으로 쓴다.
이 10분 액션의 목표는 완벽한 zero trust 설계가 아니다. “짧은 토큰이면 안전하다”는 막연함을 버리고, 토큰이 사용할 수 있는 목적지를 명시하는 것이다.
7. 더 볼 자료
- Custom OIDC Token Audiences
- OpenID Connect (OIDC) Federation
- Connect to your own API
- OIDC Federation Reference
- Vercel Connect: Secure access to external services for your agents
중복 회피 메모
로컬 content/generated와 Supabase 최근 infra_dev 글을 확인했다. 최근 infra_dev는 AI endpoint의 BotID/rate limit 비용 방화벽, GitHub Actions VNET failover, AI incident response agent guardrail, EventBridge 로깅, Lambda durable functions, CI SaaS 장애, Cloudflare Queues, PostgreSQL 관측, Docker 보안, GKE capacity buffer, OpenTelemetry Collector, Cloud Run worker backpressure, OIDC 기반 장기 secret 축소를 다뤘다. 이번 글은 장기 secret 제거 자체를 반복하지 않고, 2026-06-23 Vercel custom OIDC audiences 발표를 계기로 짧은 수명 토큰의 audience claim, replay 방지, downstream별 검증, jti 기반 감사 추적에 집중해 중복을 피했다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)