Summary#
OAuth 2.1 계열의 browser app 인증에서 BFF(Backend-for-Frontend) session architecture는 “브라우저에 OAuth access token·refresh token을 보관하지 않고, same-origin backend가 OAuth client 역할과 token 보관을 맡으며, 브라우저에는 애플리케이션 session cookie만 노출하는” 패턴이다. 이 구조는 SPA가 localStorage/sessionStorage/IndexedDB 등에 token을 저장하는 위험과 refresh token 탈취 위험을 줄이지만, session cookie 기반 구조가 되므로 CSRF, session fixation, cookie scope, SameSite, third-party-cookie 차단, OAuth state/PKCE/redirect URI 검증 실패를 별도로 다뤄야 한다.
핵심 설계는 다음과 같다: browser → BFF는 first-party session cookie로 인증하고, BFF → Authorization Server는 authorization code flow를 사용하며, BFF가 confidential client라 하더라도 PKCE를 적용해 authorization code interception·mix-up 계열 위험을 줄인다. BFF는 refresh token을 서버 측 vault/DB/HSM/KMS 경계 안에 보관하고, 브라우저에는 refresh token을 절대 전달하지 않는다. OAuth callback에서는 state를 단순 random 값이 아니라 browser session, redirect target, issuer/client configuration, PKCE verifier record와 결합해 검증해야 한다. OIDC를 함께 쓰는 경우 nonce는 ID Token replay·substitution 방어 목적으로 별도 검증한다.
Third-party-cookie failure mode는 특히 “silent refresh”와 “embedded login iframe”에서 중요하다. 브라우저가 third-party cookies를 차단하면 SPA가 hidden iframe으로 Authorization Server 세션을 재사용해 token을 조용히 갱신하는 방식은 실패하거나 불안정해진다. BFF 패턴은 애플리케이션 도메인의 first-party session cookie를 중심으로 동작하므로 이 실패 모드를 완화할 수 있지만, Authorization Server가 별도 사이트에 있고 front-channel redirect가 필요한 한, 로그인 UX·SSO UX·iframe 기반 세션 확인 기능은 브라우저 cookie 정책 변화의 영향을 받을 수 있다.
Key Points#
- BFF의 보안 경계
- 브라우저는 OAuth token holder가 아니라 애플리케이션 session holder로 취급한다.
- access token과 refresh token은 BFF 또는 BFF 뒤의 token service에만 저장한다.
- 브라우저 JavaScript가 access token·refresh token을 읽을 수 없게 하는 것이 핵심이다.
- BFF가 API 호출을 대신 수행하거나, 내부 API에 token을 붙여 proxy한다.
-
session cookie는
HttpOnly,Secure, 적절한SameSite, 제한된Path/Domain, 짧은 idle timeout/absolute timeout 정책을 가져야 한다. -
OAuth 2.1 방향성과 browser app
- OAuth 2.1 방향성은 implicit flow와 resource owner password credentials 같은 과거 패턴을 제거하고 authorization code flow + PKCE를 중심으로 정리한다.
- browser-based app guidance는 token을 browser storage에 보관하는 위험을 강조하며, BFF/token-mediating backend 같은 서버 보조 패턴을 더 안전한 선택지로 다룬다.
-
BFF가 confidential client라 해도 PKCE는 defense-in-depth로 유용하다. code가 front-channel을 통과하고 callback endpoint가 노출되는 이상, authorization code injection·interception·mix-up 방어를 PKCE와
state검증에 의존하는 구간이 남는다. -
PKCE 구현 계약
code_verifier는 충분히 랜덤해야 하며, authorization attempt별로 1회성으로 생성한다.- 가능한 경우
code_challenge_method=S256만 허용하고plaindowngrade를 피한다. - BFF는
code_verifier를 서버 측 transient store에 저장하고, browser에는 원문을 노출하지 않는다. code_verifierrecord는state, browser session id, redirect URI, issuer, client id, 생성 시각, 만료 시각과 함께 묶어 저장한다.-
callback 처리 후에는 verifier/state record를 즉시 폐기해 replay와 다중 탭 혼선을 줄인다.
-
Refresh-token confinement
- refresh token은 browser에 내려보내지 않는다.
- BFF 내부에서도 refresh token은 평문 로그, analytics, crash report, client-visible error에 절대 포함하지 않는다.
- 저장 시 envelope encryption, KMS/HSM, DB column-level encryption, token hash/fingerprint, access control, audit log를 고려한다.
- refresh token rotation 또는 sender-constrained refresh token을 사용하면 탈취·재사용 탐지에 도움이 된다.
- rotation reuse가 감지되면 정상 client retry와 attacker replay를 완벽히 구분할 수 없으므로, token family 폐기와 재인증 정책을 명확히 해야 한다.
-
BFF scale-out 환경에서는 refresh race를 막기 위해 per-session lock, token family 상태 전이, idempotency window, 짧은 grace policy를 신중히 설계해야 한다.
-
CSRF와
statebinding - BFF 구조는 OAuth token 탈취 위험을 줄이지만, cookie-based session으로 전환되는 만큼 CSRF 방어가 필수다.
- 애플리케이션 API에는 SameSite cookie만 믿지 말고 CSRF token, double-submit pattern, origin/referer 검증, Fetch Metadata header 검증 등을 threat model에 맞게 결합한다.
- OAuth authorization request의
state는 callback CSRF 방어의 핵심이다. state는 단순 random nonce가 아니라 다음 항목에 bind하는 것이 안전하다:- pre-login browser session 또는 login transaction id
code_verifierrecord- expected issuer / authorization server
- client id
- redirect URI
- post-login return URL
- 생성 시각과 짧은 만료 시간
-
return URL을
state안에 직접 넣거나 신뢰하면 open redirect로 이어질 수 있으므로 allowlist 또는 server-side handle 방식을 사용한다. -
OIDC
nonce와state의 분리 state는 주로 OAuth callback CSRF 및 authorization response binding에 사용된다.nonce는 OIDC ID Token replay/substitution 방어에 사용된다.- 둘을 같은 난수에서 파생할 수는 있어도 검증 목적과 검증 위치는 분리해야 한다.
-
ID Token을 사용하는 경우 issuer, audience, expiry, nonce, signature, key id/JWKS rotation 처리를 함께 검증한다.
-
Third-party-cookie failure modes
- hidden iframe silent refresh는 Authorization Server cookie가 third-party context로 취급될 때 실패할 수 있다.
- Safari ITP, Firefox ETP, Chrome의 third-party-cookie 제한/단계적 폐지 정책은 iframe 기반 SSO 확인, prompt=none, silent token renewal을 불안정하게 만든다.
- BFF는 애플리케이션 도메인의 first-party session cookie를 사용하므로 SPA token silent refresh보다 안정적일 수 있다.
- 그러나 사용자가 Authorization Server와 상호작용해야 하는 login redirect, federated logout, IdP session check iframe, cross-site SSO UX는 여전히 browser cookie policy의 영향을 받는다.
- SameSite 설정이 너무 엄격하면 OAuth redirect callback에서 session correlation cookie가 누락될 수 있고, 너무 느슨하면 CSRF 표면이 커진다.
-
일반적으로 OAuth login transaction correlation cookie는 redirect 흐름을 고려해
SameSite=Lax또는 별도 짧은 수명 cookie를 검토하고, cross-site iframe 의존은 줄이는 방향이 안전하다. -
Failure-mode checklist
- 브라우저 localStorage에 refresh token 저장.
- BFF가 access token을 JSON으로 브라우저에 반환.
state를 검증하지 않거나, session과 bind하지 않음.staterecord를 여러 로그인 시도에서 재사용.- callback의
code를 PKCE verifier와 정확히 매칭하지 않음. - redirect URI를 prefix/wildcard로 느슨하게 비교.
- issuer/client metadata mix-up을 검증하지 않음.
- refresh token rotation reuse detection이 token family 단위로 작동하지 않음.
- silent refresh iframe을 핵심 세션 유지 메커니즘으로 가정.
- SameSite 설정 변경 후 OAuth callback correlation이 깨짐.
- BFF API가 cookie 인증만 있고 CSRF 방어가 없음.
- logout이 BFF session, refresh token, upstream IdP session의 범위를 혼동함.
Cautions#
- 현재 실행 환경에는 사용자가 지시한
WebSearch/WebFetch도구가 제공되지 않아, 실제 공개 웹 검색 결과 선택 및 원문 fetch 검증을 수행할 수 없었다. 아래 내용은 공개 표준·BCP·브라우저 문서로 알려진 URL을 기반으로 한 capsule 초안이다. - OAuth 2.1은 OAuth 2.0 관련 RFC와 security BCP를 통합·정리하는 방향의 사양이므로, 구현 시점에는 사용하는 draft/RFC 버전과 authorization server의 실제 지원 범위를 확인해야 한다.
- BFF가 항상 SPA보다 “자동으로 안전하다”는 뜻은 아니다. token exposure 위험은 줄지만, cookie session, CSRF, server-side token vault, proxy authorization, logout propagation, operational compromise 위험이 새로 생긴다.
- PKCE는 authorization code interception 방어에 강하지만 XSS, compromised BFF, open redirect, malicious browser extension, IdP compromise, weak session cookie 설정을 해결하지 않는다.
- SameSite cookie 동작은 브라우저·버전·redirect 방식·top-level navigation 여부에 따라 차이가 있을 수 있다. OAuth callback correlation cookie 설계는 실제 대상 브라우저에서 테스트해야 한다.
- Third-party-cookie 차단은 silent refresh와 iframe 기반 SSO 확인을 불안정하게 만들지만, 모든 redirect 기반 로그인 자체가 차단된다는 의미는 아니다. top-level redirect 기반 authorization code flow는 일반적으로 iframe silent refresh보다 호환성이 높다.
- Refresh token rotation에서 reuse를 탐지해도 정상 클라이언트의 중복 요청·네트워크 재시도·공격자 replay를 완벽히 구분할 수 없다. 재인증, grace window, token family revoke 범위는 제품 보안 정책으로 명시해야 한다.
- 이 초안은 특정 vendor SDK의 behavior를 일반화하지 않는다. Auth0, Okta, Microsoft Entra, Cognito 등은 BFF·SPA·refresh token 정책에 서로 다른 제한과 확장을 둘 수 있다.
Sources#
- https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/
- https://datatracker.ietf.org/doc/draft-ietf-oauth-browser-based-apps/
- https://www.rfc-editor.org/rfc/rfc7636
- https://www.rfc-editor.org/rfc/rfc6749
- https://www.rfc-editor.org/rfc/rfc9700
- https://openid.net/specs/openid-connect-core-1_0.html
- https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/Third-party_cookies
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
Related#
- OAuth 2.1 Authorization Code + PKCE Failure Modes: Redirect URI Matching, State and Nonce Binding, Refresh Token Policy for Public Clients, and Provider Metadata Drift
- JWT Refresh Token Rotation Failure Modes: Reuse Detection, Concurrent Refresh Races, Revocation Propagation, and Multi-Device Session Boundaries
- Session Fixation Mitigation Architecture: Session ID Regeneration Timing, Federated Login Handoffs, Remember-Me Cookies, and CSRF Coupling Failure Modes
Sagwan Revalidation 2026-07-30T10:37:01Z#
- verdict:
ok - note: BFF·PKCE·토큰 격리·CSRF/3PC 위험 설명은 현재도 유효함