From b1c2d05ae9aa409b4e927216e7918809759d9404 Mon Sep 17 00:00:00 2001 From: donghyeon-ka Date: Sat, 25 Jul 2026 16:37:07 +0900 Subject: [PATCH] test: isolate refresh token rotation contract --- docs/refresh-token-rotation.md | 16 ++++++++++++++++ .../verify-refresh-token-rotation-contract.sh | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 docs/refresh-token-rotation.md create mode 100755 scripts/verify-refresh-token-rotation-contract.sh diff --git a/docs/refresh-token-rotation.md b/docs/refresh-token-rotation.md new file mode 100644 index 0000000..de5e55e --- /dev/null +++ b/docs/refresh-token-rotation.md @@ -0,0 +1,16 @@ +# Refresh token rotation contract + +Realm 설정은 refresh token revoke를 활성화하고 재사용 허용 횟수를 0으로 둔다. +SPA는 새 token set을 받은 즉시 이전 refresh token을 폐기한다. + +실제 AP1 E2E는 다음을 구분한다. + +- RT1로 refresh하면 RT2가 새로 발급된다. +- 이미 소비한 RT1 재사용은 성공하면 안 된다. +- 재사용 탐지 후 RT2까지 무효화할지는 Keycloak realm 정책과 동시 요청 + 상황에 따라 관찰한다. +- refresh token revoke 이후 refresh는 실패한다. +- 이미 발급된 stateless access JWT는 `exp`까지 유효할 수 있다. + +`verify-refresh-token-rotation-contract.sh`는 realm과 E2E assertions의 계약을 +빠르게 확인한다. 실제 token 수명주기 재현은 `verify-pattern1.sh`가 수행한다. diff --git a/scripts/verify-refresh-token-rotation-contract.sh b/scripts/verify-refresh-token-rotation-contract.sh new file mode 100755 index 0000000..2ae6208 --- /dev/null +++ b/scripts/verify-refresh-token-rotation-contract.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -eu + +jq -e ' + .revokeRefreshToken == true + and .refreshTokenMaxReuse == 0 + and .accessTokenLifespan <= 300 +' keycloak/import/keycloak-patterns-realm.json >/dev/null + +rg -Fq 'assert.notEqual(rotated.refresh_token, secondTokenSet.refresh_token)' \ + e2e/pattern1.mjs +rg -Fq 'a consumed refresh token must not be accepted again' e2e/pattern1.mjs +rg -Fq 'refresh revoke is not an immediate deny-list' e2e/pattern1.mjs + +echo "Refresh rotation/reuse/revocation contract verified" +echo "Run ./scripts/verify-pattern1.sh for the destructive live-token E2E"