Files
document-haness/docs/keycloak/final/.techviz/bearer-jwt-validation-chain/spec.json
T

240 lines
6.2 KiB
JSON

{
"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 변환이 서로 다른 단계임을 한 흐름에서 구분한다."
}
}