refactor: 문서 개선 중

This commit is contained in:
donghyeon-ka
2026-09-21 14:30:55 +09:00
parent c93cdea150
commit 805a18f486
1497 changed files with 525837 additions and 59152 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,239 @@
{
"version": "1.1",
"id": "bearer-jwt-validation-chain",
"title": "Bearer JWT가 검증과 역할 변환을 지나 principal이 된다",
"question": "Resource Server가 받은 Bearer JWT는 어떤 검증과 변환 단계를 지나 authenticated principal이 되는가?",
"type": "data-flow",
"direction": "TB",
"audience": [
"Spring Security Resource Server의 JWT 검증 경계를 확인하는 개발자"
],
"summary": "Bearer JWT가 JWK 서명, issuer·시간, audience 검증을 거친 뒤 realm role 변환을 통해 authenticated principal과 ROLE_* authorities가 된다.",
"alt": "Bearer JWT 입력이 JwtDecoder, issuer·시간 검증, audience 검증, role converter를 거쳐 authenticated principal이 되는 검증 사슬.",
"long_description": "왼쪽의 raw Bearer JWT가 NimbusJwtDecoder에서 JWK 서명을 확인한 뒤 issuer와 timestamp validator, 프로젝트의 AudienceValidator를 통과해 validated Jwt가 된다. 이어서 KeycloakRealmRoleConverter가 realm_access.roles를 ROLE_* authority로 바꾸고 authenticated principal이 만들어진다.",
"source_context": {
"document": "document.md",
"document_sha256": "ea10df24b892e2c57123a37a4b4f0d821e4f394353e6746f50df6a48342353e9",
"anchor": {
"kind": "heading",
"value": "AP1 완주: callback code가 브라우저 Bearer 요청이 되기까지",
"line": 227
}
},
"composition": {
"profile": "component-flow",
"diagram_only": true,
"reference_ids": [
"payment-event-flow"
],
"rationale": "검증 순서가 일곱 단계라 문서 폭에서 가로로 늘리지 않고 위에서 아래로 읽는 component-flow로 표현한다.",
"focus_node": "audience-validator"
},
"groups": [],
"nodes": [
{
"id": "bearer-input",
"label": "Bearer JWT",
"kind": "data",
"role": "source",
"shape": "box",
"description": "Resource Server가 Authorization header에서 받은 raw Bearer JWT.",
"evidence": [
{
"start_line": 354,
"end_line": 359
}
],
"assumption": false
},
{
"id": "jwt-decoder",
"label": "NimbusJwtDecoder",
"kind": "service",
"role": "service",
"description": "JWK를 이용해 JWT 서명을 검증하는 decoder.",
"details": [
"JWK signature"
],
"evidence": [
{
"start_line": 359,
"end_line": 360
}
],
"assumption": false
},
{
"id": "issuer-time",
"label": "Issuer · Time validators",
"kind": "service",
"role": "service",
"description": "Expected issuer와 timestamp 조건을 확인하는 default validators.",
"evidence": [
{
"start_line": 361,
"end_line": 361
}
],
"assumption": false
},
{
"id": "audience-validator",
"label": "AudienceValidator",
"kind": "service",
"role": "service",
"emphasis": "primary",
"description": "keycloak-pattern-api audience 포함 여부를 확인하는 project validator.",
"details": [
"keycloak-pattern-api"
],
"evidence": [
{
"start_line": 362,
"end_line": 370
}
],
"assumption": false
},
{
"id": "validated-jwt",
"label": "Validated Jwt",
"kind": "data",
"role": "service",
"description": "서명, issuer·시간, audience 검증을 통과한 Jwt.",
"evidence": [
{
"start_line": 363,
"end_line": 363
}
],
"assumption": false
},
{
"id": "role-converter",
"label": "Realm role converter",
"kind": "service",
"role": "service",
"description": "realm_access.roles 문자열에 ROLE_ prefix를 붙여 authority로 변환한다.",
"details": [
"KeycloakRealmRoleConverter"
],
"evidence": [
{
"start_line": 364,
"end_line": 370
}
],
"assumption": false
},
{
"id": "principal",
"label": "Authenticated principal",
"kind": "actor",
"role": "sink",
"shape": "actor",
"description": "검증된 JWT와 ROLE_* authorities를 가진 인증 결과.",
"details": [
"ROLE_* authorities"
],
"evidence": [
{
"start_line": 365,
"end_line": 365
}
],
"assumption": false
}
],
"edges": [
{
"id": "e1",
"from": "bearer-input",
"to": "jwt-decoder",
"label": "decode",
"kind": "data",
"evidence": [
{
"start_line": 354,
"end_line": 360
}
],
"assumption": false
},
{
"id": "e2",
"from": "jwt-decoder",
"to": "issuer-time",
"label": "signature ok",
"kind": "data",
"evidence": [
{
"start_line": 360,
"end_line": 361
}
],
"assumption": false
},
{
"id": "e3",
"from": "issuer-time",
"to": "audience-validator",
"label": "claims",
"kind": "data",
"evidence": [
{
"start_line": 361,
"end_line": 362
}
],
"assumption": false
},
{
"id": "e4",
"from": "audience-validator",
"to": "validated-jwt",
"label": "valid audience",
"kind": "data",
"emphasis": "primary",
"evidence": [
{
"start_line": 362,
"end_line": 363
}
],
"assumption": false
},
{
"id": "e5",
"from": "validated-jwt",
"to": "role-converter",
"label": "realm roles",
"kind": "data",
"evidence": [
{
"start_line": 363,
"end_line": 364
}
],
"assumption": false
},
{
"id": "e6",
"from": "role-converter",
"to": "principal",
"label": "authorities",
"kind": "data",
"evidence": [
{
"start_line": 364,
"end_line": 365
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "서명 검증과 API 대상 audience 검증, role 변환이 서로 다른 단계임을 한 흐름에서 구분한다."
}
}