115 lines
8.8 KiB
Markdown
115 lines
8.8 KiB
Markdown
---
|
|
id: 7ff40767-a00b-4db2-98f6-0cdfce8c8936
|
|
kind: QUESTION
|
|
slug: edge-authorization-scope
|
|
title: Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가
|
|
topic: oauth-oidc-auth-boundary
|
|
topicName: OAuth/OIDC 인증 경계
|
|
project: KeyCloak Patterns
|
|
status: 게시 중
|
|
version: 36
|
|
questionStatus: OPEN
|
|
studio: "https://hyeonworks.com/studio/documents/7ff40767-a00b-4db2-98f6-0cdfce8c8936/edit"
|
|
public: "https://hyeonworks.com/questions/edge-authorization-scope"
|
|
sourceRevision: keycloak-patterns-lab@2026-08
|
|
source:
|
|
- final/document.md#검토한-선택지와-막힌-지점-ap4
|
|
- final/document.md#얻은-것-잃은-것-적용하지-않을-때-ap4
|
|
---
|
|
|
|
# Forward-Auth 구조에서 Application Authorization을 어디까지 Edge에 둘 것인가
|
|
|
|
지금 엣지는 인증된 사용자의 `user`와 `email`만 헤더로 넘기고, 업스트림 애플리케이션은 역할(role)을 보고 인가를 판단하지 않는다.
|
|
|
|
## 관계
|
|
|
|
- **Forward-Auth에서 Client가 보낸 Identity Header를 신뢰하면 안 되는 이유**
|
|
엣지가 user와 email만 넘긴다는 사실을 여기서 가져왔다.
|
|
- **Forward-Auth에서 Identity Header를 신뢰하기 위한 조건**
|
|
넘길 헤더를 허용 목록(allowlist)으로 두는 기준과 검증 조건이 이 기록에 있다.
|
|
- **BFF 인증 구조 설계 기준**
|
|
네 번째 선택지로 되돌아갈 때 따를 기준이 이 기록이다.
|
|
|
|
## 사실
|
|
|
|
- 지금 엣지 응답은 user와 email만 넘긴다. 역할과 그룹, 테넌트, 인증 방식, 토큰 만료는 넘기지 않는다.
|
|
- 업스트림의 신원 응답 엔드포인트는 역할을 확인하지 않고 누가 왔는지만 돌려준다.
|
|
- 내부 토큰(internal token) 검증은 컨트롤러 한 곳에서만 하고, Spring Security 설정은 그 경로를 permitAll로 열어 둔다. 검증이 그 컨트롤러 안에만 있으니 같은 내부 경로 아래에 엔드포인트를 새로 추가해도 검증이 따라붙지 않는다. 필터나 인터셉터, Spring Security의 인증 처리 단계처럼 모든 요청이 지나는 공통 경계로 이 검사를 옮겨야 한다.
|
|
- Nginx는 클라이언트가 보낸 같은 이름의 헤더를 합치지 않고 덮어쓴다. 헤더를 늘리면 늘어난 헤더도 똑같이 덮어쓰게 해야 한다.
|
|
- 업스트림은 JWT를 입력으로 받지 않아서 헤더로 넘어온 값이 맞는지 확인할 방법이 없다.
|
|
|
|
## 가정
|
|
|
|
- 헤더 종류가 늘어나면 그만큼 정해야 할 계약도 늘어난다.
|
|
- 역할이 바뀌는 시각과 요청이 들어오는 시각이 달라서, 그 사이에 들어온 요청은 바뀌기 전 값을 볼 수도 있다.
|
|
|
|
## 미지수
|
|
|
|
- 역할 기반 인가가 필요한 요구가 들어왔을 때 어떻게 처리할지. 엣지가 사용자의 역할까지 확인해 헤더로 넘길지, 애플리케이션이 역할과 권한을 직접 조회해 인가를 판단할지.
|
|
- 역할이 여러 개일 때 어떤 구분자와 이스케이프 규칙으로 보낼지. 값 안에 그 구분자가 들어오면 어떻게 되는지.
|
|
- 헤더 크기 상한을 넘으면 어떻게 되는지. 프록시가 잘라 내는지, 요청 자체가 거부되는지.
|
|
현재 fixture는 `/api/edge`와 `/`를 모두 `/edge/me`로 바꿔서 큰 헤더가 실린 요청을 통과시켜 본 적이 없다.
|
|
- 역할이 바뀌었을 때 프록시 세션과 다운스트림 인가에 언제 반영되는지. 권한을 바꾸고 몇 분 뒤에 반영되는지.
|
|
- 업스트림이 헤더가 있는지만 볼지, 값과 내부 서비스 식별값(service identity)까지 함께 볼지.
|
|
|
|
## 제약
|
|
|
|
- 넘길 헤더는 허용 목록으로 정해야 하고, 클라이언트가 보낸 같은 이름의 헤더는 언제나 덮어써야 한다.
|
|
- 내부 토큰 검사가 컨트롤러 한 곳에만 있다. 헤더를 늘리기 전에 이 검사를 공통 경계로 옮겨야 한다.
|
|
|
|
## 선택지
|
|
|
|
### 1. 인증만 엣지에 둔다
|
|
|
|
엣지가 넘기는 헤더를 user와 email 정도로 묶어 두면 엣지와 업스트림 사이의 계약을 작게 유지할 수 있다. 역할이나 권한을 헤더에 계속 더하지 않으니 헤더가 커지는 문제도 줄일 수 있다.
|
|
|
|
대신 인가는 업스트림 애플리케이션이 직접 판단한다. 넘겨받은 사용자 식별 정보로 자기 저장소에서 역할이나 권한을 조회하고, 그 요청을 허용할지 정해야 한다.
|
|
|
|
인가를 서비스가 직접 판단하다 보니 권한 조회와 인가 코드를 서비스마다 따로 만들어야 한다.
|
|
|
|
### 2. 역할 전달까지 엣지에 둔다
|
|
|
|
엣지가 공통 역할을 확인해 업스트림에 넘기면, 서비스마다 사용자 권한을 따로 조회하는 일을 줄일 수 있다.
|
|
|
|
대신 역할을 헤더로 넘기는 계약을 먼저 정해야 한다. 한 사용자가 역할을 여럿 가질 때 어떤 형식으로 직렬화할지, 헤더에 허용할 최대 크기를 얼마로 둘지, 역할을 바꾼 뒤 언제부터 새 값이 요청에 실리는지를 적어 두어야 한다.
|
|
|
|
업스트림은 넘겨받은 역할이 원래 인증 시스템의 값과 같은지 확인할 수 있어야 한다. 확인하지 못하면 엣지가 넘긴 값을 그대로 믿게 되는데, 엣지가 역할을 잘못 계산하거나 오래된 값을 넘기면 업스트림의 인가 판단도 그대로 틀어질 수 있다.
|
|
|
|
이 선택지를 고르면 엣지가 역할을 만드는 과정과 헤더가 지나는 경로까지 신뢰 경계 안으로 들어온다. 역할을 언제 갱신하고 전달 오류를 어떻게 잡을지도 같이 설계해야 한다.
|
|
|
|
### 3. 테넌트와 인가 판단까지 엣지에 둔다
|
|
|
|
테넌트는 어느 조직의 데이터까지 볼 수 있는지를 정하는 값이다. 그래서 잘못된 테넌트 값 하나가 넘어가면 다른 조직의 데이터에 접근하는 문제로 바로 이어질 수 있다.
|
|
|
|
테넌트를 엣지 헤더로 넘기려면 업스트림이 그 사용자가 실제로 그 테넌트에 속하는지 다시 확인할 방법이 있어야 한다. 지금 구성에는 다시 확인할 수단이 없어서 테넌트까지 엣지가 맡는 구조로 넓히기에는 위험이 크다.
|
|
|
|
테넌트나 역할로 인가를 판단하는 일까지 엣지로 옮기면 엣지가 애플리케이션의 도메인 규칙을 알아야 한다. 어떤 사용자가 어느 조직의 어떤 기능을 쓸 수 있는지 같은 정책이 바뀔 때마다 엣지 코드도 함께 고쳐 배포해야 한다.
|
|
|
|
그래서 엣지는 인증된 사용자 정보를 넘기는 쪽에 가깝게 두고, 테넌트 소속 여부나 도메인에 묶인 인가 규칙은 업스트림 애플리케이션이 검증하는 구조를 먼저 검토한다.
|
|
|
|
### 4. 헤더 계약 대신 BFF가 인가와 API 호출을 맡는다
|
|
|
|
역할이나 테넌트 같은 값을 엣지 헤더에 계속 더하는 대신, BFF(Backend For Frontend)가 필요한 정보를 직접 조회해 인가를 판단하고 API까지 부르는 구조도 고를 수 있다. BFF는 화면에 필요한 API를 브라우저 대신 불러 조합하는 서버다.
|
|
|
|
이러면 엣지는 애플리케이션의 역할과 테넌트, 권한 정책을 알 필요가 없다. BFF가 사용자와 권한을 조회해 인가를 판단하고, 화면에 필요한 여러 Resource Server의 API를 불러 결과를 합칠 수 있다.
|
|
|
|
대신 BFF를 넣으면 서버가 다시 인증 상태를 들고 있어야 한다. 브라우저와 BFF 사이의 애플리케이션 세션을 보호해야 한다. 쿠키 기반 세션을 쓴다면 쿠키가 요청마다 자동으로 붙으니, 값을 바꾸는 요청에는 별도 anti-CSRF token을 요구해 cross-site forged request를 구분하는 CSRF(Cross-Site Request Forgery) 검증도 있어야 한다. BFF를 여러 대로 늘려 인증 상태를 유지하려면 세션과 authorized client를 어떻게 공유할지 정하고, 공유 저장소의 장애와 만료 처리까지 운영해야 한다.
|
|
|
|
이 구조를 골랐다가 다시 엣지 쪽으로 되돌린다면 BFF가 맡던 사용자별 인가를 업스트림이나 별도 정책 서비스로 다시 옮겨야 한다.
|
|
|
|
## 다음 검증
|
|
|
|
업스트림이 실제로 요구하는 사용자 속성(claim)부터 적는다.
|
|
|
|
1. 넘기려는 속성이 계속 늘어나는가.
|
|
2. 역할이나 테넌트를 바꾸면 곧바로 반영돼야 하는가.
|
|
3. 정책이 애플리케이션 도메인을 알아야 하는가.
|
|
4. 헤더 값이 인가 판단의 근거가 되는가.
|
|
5. 서비스마다 정책 차이가 커지는가.
|
|
|
|
2번부터 5번 가운데 하나라도 그렇다면 헤더를 늘리는 대신 BFF 구조를 검토한다.
|
|
|
|
역할을 헤더에 담는 구성을 먼저 만들고, 값을 여러 개 넣고 크기 상한까지 올려 무엇이 먼저 깨지는지 확인한다. 역할을 바꾼 뒤 몇 번째 요청부터 새 값이 실리는지도 센다.
|
|
|
|
어느 쪽으로 옮길지는 새로 일을 맡는 쪽이 상태와 검증을 감당할 수 있는지를 보고 정한다.
|