Skip to content

필사 모드: 리프레시 토큰 로테이션과 세션 관리 — 탈취에 강한 토큰 수명주기 설계

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

인증 시스템에서 가장 어려운 질문은 "어떻게 로그인시킬까"가 아니라 "**로그인 상태를 얼마나, 어떻게 유지할까**"입니다. 토큰 수명을 길게 잡으면 사용자 경험은 좋아지지만 탈취 피해가 커지고, 짧게 잡으면 안전해지지만 재로그인 지옥이 펼쳐집니다. 이 긴장을 푸는 표준 도구가 refresh token이고, 그 안전장치가 rotation과 reuse detection입니다.

2026년의 맥락에서 이 주제는 더 중요해졌습니다. OAuth 2.1 draft는 public client의 refresh token에 rotation 또는 sender-constraining을 의무화했고, RFC 9700(OAuth Security BCP)은 그 구체적 구현 요건을 정의합니다. 한편 passkeys가 기본 인증 수단이 되면서 "비밀번호는 안전해졌는데 세션/토큰이 약한 고리"가 되는 역전 현상이 일어나고 있습니다. 공격자는 이제 비밀번호 대신 세션 쿠키와 refresh token을 노립니다. 인포스틸러 멀웨어가 훔치는 것도 바로 이것들입니다.

이 글에서는 토큰 수명 설계 원칙부터 rotation 메커니즘의 내부 동작, IdP/앱/SSO 세션의 3계층 모델, Keycloak의 세션 설정 상세, 그리고 토큰 탈취 사고 발생 시 대응 절차까지를 다룹니다.

토큰 수명 설계 원칙

두 토큰의 역할 분담

┌──────────────────────────────────────────────────────────┐

│ Access Token (AT) │

│ - 용도: API 호출 인가 │

│ - 수명: 5~15분 (짧게!) │

│ - 검증: stateless (서명 검증만, IdP 조회 없음) │

│ - 탈취 시: 수명만큼만 피해. 차단 불가가 전제 │

├──────────────────────────────────────────────────────────┤

│ Refresh Token (RT) │

│ - 용도: 새 AT 발급 (IdP의 token 엔드포인트에서만 사용) │

│ - 수명: idle 수 시간~수 주, max 수 주~수 개월 │

│ - 검증: stateful (IdP가 세션/패밀리 상태를 확인) │

│ - 탈취 시: rotation + reuse detection으로 감지/차단 │

└──────────────────────────────────────────────────────────┘

설계 원칙은 다음 네 가지로 요약됩니다.

1. **AT는 "차단할 수 없다"고 전제하고 수명으로 피해를 제한합니다.** AT가 5분짜리라면 탈취돼도 피해 창은 최대 5분입니다.

2. **RT는 "탈취된다"고 전제하고 감지 메커니즘을 답니다.** rotation + reuse detection이 그 감지기입니다.

3. **수명은 위험도에 비례시킵니다.** 금융 서비스의 RT와 사내 위키의 RT가 같은 수명일 이유가 없습니다.

4. **idle과 max를 분리합니다.** "안 쓰면 이만큼 후 만료(idle)"와 "아무리 써도 이 시점엔 만료(max)"는 다른 통제입니다.

수명 권장 시작값

| 서비스 유형 | AT | RT idle | RT max | 비고 |

| --- | --- | --- | --- | --- |

| 금융/결제 | 5분 | 30분 | 8시간 | 재인증 빈도 높음 |

| 일반 B2C 웹/앱 | 10~15분 | 14일 | 90일 | rotation 필수 |

| 사내 업무 시스템 | 10분 | 8시간 | 24시간 | 근무일 단위 |

| 백그라운드 동기화 (offline) | 10분 | 30일 | 180일 | offline 토큰, 별도 감사 |

이 값은 정답이 아니라 출발점입니다. 핵심은 "각 값이 왜 그 값인지"를 설명할 수 있어야 한다는 것입니다.

Rotation + Reuse Detection 메커니즘

기본 동작

rotation은 RT를 사용할 때마다 새 RT를 발급하고 직전 RT를 무효화하는 것입니다. RT가 일회용 티켓이 되는 셈입니다.

시각 클라이언트 IdP

t0 RT1로 갱신 요청 → AT2 + RT2 발급, RT1을 "사용됨"으로 마킹

t1 RT2로 갱신 요청 → AT3 + RT3 발급, RT2를 "사용됨"으로 마킹

t2 RT3로 갱신 요청 → AT4 + RT4 발급, ...

토큰 패밀리와 재사용 감지

같은 최초 인증에서 파생된 RT들의 계보를 **토큰 패밀리(token family)** 라고 부릅니다. 재사용 감지는 이 패밀리 단위로 동작합니다.

패밀리 F1: RT1 ──> RT2 ──> RT3 (현재 유효)

탈취 시나리오 A: 공격자가 먼저 사용

1. 공격자가 RT2를 탈취해 갱신 → RT3' 획득 (공격자가 최신)

2. 정상 사용자가 RT2로 갱신 시도

3. IdP: "RT2는 이미 사용됨" → 재사용 감지!

4. 패밀리 F1 전체 무효화 (RT3'도 죽음)

5. 양쪽 모두 로그아웃 → 정상 사용자는 재로그인, 공격자는 차단

탈취 시나리오 B: 정상 사용자가 먼저 사용

1. 공격자가 RT2를 탈취 (아직 미사용)

2. 정상 사용자가 RT2로 갱신 → RT3 발급

3. 공격자가 RT2로 갱신 시도 → 재사용 감지! → 패밀리 무효화

어느 쪽이 먼저든, "두 번 쓰인 RT"가 감지되는 순간

패밀리 전체가 죽는다는 것이 핵심입니다.

이 메커니즘의 아름다움은 **공격자와 정상 사용자를 구분할 필요가 없다**는 점입니다. 누가 도둑인지 몰라도, 충돌이 감지되면 전부 무효화하고 재인증을 요구하면 됩니다. 정상 사용자는 약간의 불편(재로그인)을 겪지만, 공격자는 영구히 차단됩니다.

네트워크 오류와 grace period

현실에서는 정상 클라이언트도 RT를 "두 번" 보낼 수 있습니다. 갱신 요청 후 응답을 못 받고 재시도하는 경우입니다. 이를 위해 짧은 grace period(전송 중복 허용 창, 보통 수 초~수십 초)를 두는 구현이 많습니다. Keycloak은 `revokeRefreshToken` 활성화 시 `refreshTokenMaxReuse`(기본 0)로 허용 재사용 횟수를 제어합니다. 0이 가장 안전하며, 클라이언트의 재시도 로직을 멱등하게 만드는 것이 정도(正道)입니다.

Keycloak: rotation + 재사용 0회 허용 (가장 엄격)

kcadm.sh update realms/myrealm \

-s revokeRefreshToken=true \

-s refreshTokenMaxReuse=0

세션의 3계층 모델 — IdP 세션, 앱 세션, SSO 세션

토큰만 보면 세션 관리의 절반밖에 보지 못한 것입니다. 실제 시스템에는 세 종류의 "로그인 상태"가 공존합니다.

┌───────────────────────────────────────────────────────────────┐

│ 3계층 세션 모델 │

│ │

│ [브라우저] │

│ ├── 앱 세션 A (app-a.example.com의 세션 쿠키) │

│ ├── 앱 세션 B (app-b.example.com의 세션 쿠키) │

│ └── IdP 세션 (idp.example.com의 SSO 쿠키) │

│ │ │

│ ▼ │

│ [IdP 서버] │

│ └── SSO 세션 (서버 측 상태: 어떤 사용자가, 어떤 클라이언트들에, │

│ 언제 인증했는지의 원장) │

│ ├── Client Session A (app-a에 대한 토큰 발급 기록) │

│ └── Client Session B (app-b에 대한 토큰 발급 기록) │

└───────────────────────────────────────────────────────────────┘

| 계층 | 저장 위치 | 수명 주체 | 만료 시 효과 |

| --- | --- | --- | --- |

| 앱 세션 | 각 앱의 쿠키/세션 저장소 | 앱 | 그 앱만 로그아웃 |

| IdP 세션(SSO 쿠키) | IdP 도메인 쿠키 | IdP | 새 SSO 로그인 불가, 기존 앱 세션은 유지될 수 있음 |

| SSO 세션(서버 상태) | IdP 서버/DB | IdP | RT 갱신 실패, 신규 토큰 발급 불가 |

실무에서 가장 많은 혼란이 "로그아웃했는데 다른 앱은 왜 로그인되어 있나요?"입니다. 답은 이 3계층이 독립적으로 만료되기 때문입니다. 앱 A에서 로그아웃해도(앱 세션 A 삭제), IdP 세션이 살아 있으면 앱 A에 다시 접근할 때 자동 재로그인됩니다. 반대로 IdP 세션을 죽여도 앱 B의 자체 세션 쿠키가 살아 있으면 앱 B는 계속 동작합니다. 이를 정리하려면 뒤에서 다룰 로그아웃 전파가 필요합니다.

Keycloak 세션 설정 상세

Keycloak은 이 모델을 SSO Session, Client Session, Offline Session으로 구현합니다. Realm Settings의 Sessions와 Tokens 탭에서 설정합니다.

SSO Session

SSO Session Idle: 기본 30분

- 이 시간 동안 세션 활동(토큰 갱신 등)이 없으면 세션 만료

- RT의 실효 idle 수명을 결정 (RT 수명 = min(이 값, client session 값))

SSO Session Max: 기본 10시간

- 활동과 무관하게 최초 인증 후 이 시간이 지나면 세션 만료

- "아무리 열심히 갱신해도 10시간 후엔 재로그인"의 근거

Client Session

Client Session Idle / Client Session Max: 기본 0 (= SSO 값 상속)

- 클라이언트 단위로 더 짧은 토큰 수명을 강제하고 싶을 때 사용

- 예: realm 전체는 idle 30일이지만, 결제 클라이언트만 idle 30분

- 클라이언트의 Advanced Settings에서 개별 재정의도 가능

중요한 동작: refresh token의 만료 시각은 **SSO 세션과 클라이언트 세션 중 먼저 끝나는 쪽**에 묶입니다. 즉 Keycloak에서 RT 수명은 독립 설정값이 아니라 세션 수명의 파생물입니다. 이 사실을 모르면 "RT 수명을 늘렸는데 적용이 안 돼요" 같은 미스터리에 빠집니다.

Offline Session

백그라운드 동기화처럼 사용자가 브라우저를 닫은 뒤에도 토큰 갱신이 필요한 경우를 위한 별도 트랙입니다. scope에 offline_access를 포함해 요청하면 offline token이 발급됩니다.

Offline Session Idle: 기본 30일

- offline RT를 30일 안에 한 번씩 사용하면 계속 연장

Offline Session Max Limited: 활성화 시 절대 상한 적용

Offline Session Max: 기본 60일

- 갱신 여부와 무관한 절대 만료

offline token은 일반 SSO 세션과 분리되어 관리되며, 사용자가 로그아웃해도 살아남습니다. 강력한 만큼 발급 대상을 엄격히 제한하고(클라이언트 scope 통제), Admin Console의 사용자별 Consents/Sessions에서 주기적으로 감사해야 합니다.

토큰 수명 설정

Access Token Lifespan: 기본 5분 (늘리지 마세요)

Access Token Lifespan For Implicit: 레거시, 무시

Client Login Timeout: 인가 코드 → 토큰 교환의 허용 시간

설정 예시를 kcadm으로 정리하면 다음과 같습니다.

kcadm.sh update realms/myrealm \

-s accessTokenLifespan=600 \

-s ssoSessionIdleTimeout=1209600 \

-s ssoSessionMaxLifespan=7776000 \

-s offlineSessionIdleTimeout=2592000 \

-s offlineSessionMaxLifespanEnabled=true \

-s offlineSessionMaxLifespan=15552000 \

-s revokeRefreshToken=true \

-s refreshTokenMaxReuse=0

(위 예시: AT 10분, SSO idle 14일, SSO max 90일, offline idle 30일, offline max 180일, rotation 활성화.)

디바이스별 세션 관리

한 사용자는 여러 디바이스에서 동시에 로그인합니다. 각 로그인은 독립된 SSO 세션(따라서 독립된 토큰 패밀리)이어야 합니다.

사용자 alice의 세션 목록 (IdP 관점)

┌────────────┬──────────────┬─────────────┬──────────────┐

│ 세션 ID │ 디바이스 │ 시작 │ 마지막 활동 │

├────────────┼──────────────┼─────────────┼──────────────┤

│ sess-a1 │ MacBook/Chrome│ 06-10 09:12 │ 06-12 11:40 │

│ sess-b2 │ iPhone/앱 │ 06-08 20:01 │ 06-12 08:15 │

│ sess-c3 │ 회사 PC/Edge │ 06-11 08:55 │ 06-11 18:02 │

└────────────┴──────────────┴─────────────┴──────────────┘

이 구조가 주는 운영 능력은 다음과 같습니다.

1. **세션 목록 표시**: "내 계정에서 로그인된 기기" 화면. 사용자가 직접 의심 세션을 종료할 수 있게 합니다.

2. **개별 무효화**: 분실한 폰의 세션만 종료. 다른 디바이스는 영향 없음.

3. **이상 감지의 단위**: 동일 패밀리의 RT가 서로 다른 국가 IP에서 사용되면 그 세션만 격리할 수 있습니다.

Keycloak Admin REST API로 세션을 조회/종료할 수 있습니다.

사용자 세션 목록 조회

kcadm.sh get users/USER-UUID/sessions -r myrealm

특정 세션만 종료

kcadm.sh delete sessions/SESSION-ID -r myrealm

사용자의 모든 세션 종료 (모든 디바이스 로그아웃)

kcadm.sh create users/USER-UUID/logout -r myrealm

로그아웃과 세션 정리

로그아웃은 "쿠키 삭제"가 아니라 **3계층 세션과 토큰 패밀리를 일관되게 정리하는 분산 트랜잭션**입니다. 완전한 로그아웃은 다음을 모두 수행해야 합니다.

1. 앱 세션 삭제 (앱 자신의 세션 쿠키/저장소)

2. IdP 세션 종료 (OIDC RP-Initiated Logout: /logout 엔드포인트)

3. RT 무효화 (token revocation: RFC 7009 /revoke)

4. 다른 앱들에 전파 (Back-Channel Logout: RFC 적용 또는 OIDC 스펙)

전파 메커니즘은 두 가지가 있습니다.

| 방식 | 동작 | 장단점 |

| --- | --- | --- |

| Front-Channel Logout | 브라우저가 각 앱의 logout URL을 iframe 등으로 순회 호출 | 구현 단순 / 브라우저 의존, 3rd-party 쿠키 차단에 취약 |

| Back-Channel Logout | IdP가 각 앱 서버로 logout token(JWT)을 직접 POST | 신뢰성 높음, 2026년 권장 / 앱이 세션-sid 매핑을 유지해야 함 |

Back-Channel Logout을 받는 앱 쪽 책임이 중요합니다. logout token의 서명과 클레임(iss, aud, events, sid)을 검증한 뒤, sid에 해당하는 **앱 세션을 실제로 파기**해야 합니다. 이 매핑(IdP의 sid → 앱 세션 ID)을 로그인 시점에 저장해 두지 않으면 전파를 받아도 할 수 있는 일이 없습니다.

Back-Channel Logout 흐름

IdP ── POST logout_token(JWT, sid=xyz) ──> App B의 /backchannel-logout

├ 서명/클레임 검증

├ sid=xyz → 앱 세션 s-42 조회

└ s-42 파기, 204 응답

BFF(Backend-for-Frontend) 패턴

SPA의 토큰 관리 문제를 구조적으로 해소하는 패턴입니다. 토큰을 브라우저에 두지 않고, 프런트엔드 전용 백엔드가 토큰의 보관자이자 프록시가 됩니다.

┌─────────┐ HttpOnly 세션 쿠키 ┌─────────────┐ AT/RT 보관 ┌────────┐

│ Browser │ <─────────────────────> │ BFF │ <───────────> │ IdP │

│ (SPA) │ /api/* 프록시 │ (서버 세션) │ └────────┘

└─────────┘ │ │ │ AT 첨부

│ └──────┼──────────────> APIs

└─────────────┘

동작 방식:

1. 로그인은 BFF가 confidential client로서 code + PKCE flow를 수행합니다.

2. AT/RT는 BFF의 서버 측 세션 저장소(Redis 등)에만 존재합니다.

3. 브라우저는 HttpOnly + Secure + SameSite=Strict 쿠키로 BFF와 통신합니다.

4. SPA의 API 호출은 BFF가 프록시하며, 이때 AT를 붙입니다. AT 만료 시 BFF가 RT로 조용히 갱신합니다.

| 항목 | 토큰을 브라우저에 둘 때 | BFF |

| --- | --- | --- |

| XSS로 토큰 유출 | 가능 | 불가능 (토큰이 브라우저에 없음) |

| CSRF | 해당 없음 | SameSite + CSRF 토큰으로 방어 필요 |

| rotation 구현 위치 | SPA (탭 간 경합 문제) | BFF (단일 지점, 단순) |

| 운영 비용 | 낮음 | BFF 인프라 추가 |

여러 탭이 동시에 RT 갱신을 시도하며 rotation과 충돌하는 고질적인 SPA 문제(탭 A가 갱신해서 RT가 바뀌었는데 탭 B가 구 RT로 갱신 시도 → 재사용 감지 오발)는 BFF에서 갱신을 단일화하면 자연히 사라집니다. 새로 시작하는 프로젝트라면 BFF를 기본값으로 검토하기를 권합니다.

BFF의 토큰 갱신 핵심부를 Node/Express로 스케치하면 다음과 같습니다. 갱신을 세션 단위 락으로 직렬화하는 부분이 요점입니다.

// BFF의 토큰 갱신 미들웨어 (개념 스케치)

const sessionLocks = new Map(); // 세션별 갱신 직렬화

async function ensureFreshToken(req, res, next) {

const session = await store.get(req.sessionId);

if (!session) return res.status(401).end();

const skewMs = 30_000; // 만료 30초 전부터 선제 갱신

if (session.atExpiresAt - Date.now() > skewMs) {

req.accessToken = session.accessToken;

return next();

}

// 같은 세션의 동시 갱신을 하나로 직렬화 (rotation 오발 방지)

let lock = sessionLocks.get(req.sessionId);

if (!lock) {

lock = oidcClient

.refresh(session.refreshToken) // rotation: 새 RT가 돌아옴

.then(async (tokens) => {

await store.update(req.sessionId, {

accessToken: tokens.access_token,

refreshToken: tokens.refresh_token, // 구 RT는 즉시 폐기

atExpiresAt: Date.now() + tokens.expires_in * 1000,

});

return tokens.access_token;

})

.finally(() => sessionLocks.delete(req.sessionId));

sessionLocks.set(req.sessionId, lock);

}

try {

req.accessToken = await lock;

next();

} catch (err) {

await store.destroy(req.sessionId); // 갱신 실패 = 세션 종료

res.status(401).end();

}

}

여러 인스턴스로 BFF를 수평 확장하는 경우에는 위의 인메모리 락 대신 Redis 분산 락(또는 갱신 전용 단일 워커)으로 동일한 직렬화를 보장해야 한다는 점에 유의하세요.

보안 사고 시나리오와 대응

시나리오 1: 인포스틸러로 RT 대량 유출 의심

징후: 재사용 감지 이벤트가 평소의 수십 배로 급증

대응:

1. 감지된 패밀리는 자동 무효화되고 있음을 확인 (이미 방어 동작 중)

2. 영향 사용자 추출 → 강제 전체 세션 종료 + 비밀번호/passkey 재등록 안내

3. offline token 보유 사용자는 별도 점검 (로그아웃에도 살아남으므로)

4. AT 수명 임시 단축 (10분 → 5분) 검토

시나리오 2: 특정 사용자 계정 탈취 신고

1. 즉시 모든 세션 종료 (모든 디바이스에서 로그아웃)

kcadm.sh create users/USER-UUID/logout -r myrealm

2. offline 토큰 포함 동의(consent) 철회

kcadm.sh delete users/USER-UUID/consents/CLIENT-ID -r myrealm

3. 자격증명 재설정 요구 (비밀번호 + passkey 재등록)

kcadm.sh update users/USER-UUID -r myrealm \

-s 'requiredActions=["UPDATE_PASSWORD","webauthn-register-passkey"]'

AT는 차단할 수 없으므로(stateless), AT 수명만큼의 잔여 위험은 수용하거나, 고위험 API에 한해 introspection으로 세션 생존을 확인하게 합니다.

시나리오 3: IdP 서명 키 유출 의심

토큰 수명주기 설계가 빛나는 순간입니다. 키를 회전(구 키 즉시 제거)하면 구 키로 서명된 모든 AT가 한꺼번에 무효화됩니다. AT 수명이 10분이라면 "유출 키로 위조 가능한 창"도 키 제거 즉시 닫힙니다. RT는 서버 측 상태로 검증되므로 세션 무효화로 대응합니다.

모니터링 지표

| 지표 | 의미 | 경보 기준 예 |

| --- | --- | --- |

| RT 재사용 감지 수 | 탈취 시도 or 클라이언트 버그 | 시간당 N건 초과 |

| 동일 패밀리 다국가 IP 사용 | 세션 하이재킹 | 1건이라도 |

| invalid_grant 비율 | 만료/오용/공격 혼합 신호 | 평시 대비 3배 |

| offline token 발급 수 | 장기 자격증명 증가 | 주간 추세 감시 |

| 세션당 평균 수명 | 정책 실효성 확인 | 분포 변화 |

안티패턴 모음

| 안티패턴 | 문제 | 교정 |

| --- | --- | --- |

| AT 수명 24시간 | 차단 불가 토큰의 피해 창 24시간 | 5~15분 + RT 갱신 |

| rotation 없이 RT 90일 | 탈취 감지 수단 전무 | rotation + reuse detection |

| RT를 localStorage에 저장 | XSS 한 번에 장기 자격증명 유출 | HttpOnly 쿠키 또는 BFF |

| 로그아웃 시 쿠키만 삭제 | IdP 세션/RT 생존 → 자동 재로그인 | RP-Initiated Logout + revoke |

| 모든 클라이언트에 offline_access 허용 | 로그아웃 불가 토큰 남발 | scope를 필요 클라이언트로 제한 |

| 세션 저장소 없이 다중 인스턴스 IdP | 재사용 감지가 인스턴스별로 동작 | 공유 저장소/클러스터 캐시 |

| 탭마다 독립 RT 갱신 | rotation 오발 무효화 | 갱신 단일화 (lock 또는 BFF) |

마치며

탈취에 강한 토큰 수명주기 설계의 핵심을 요약합니다.

- **AT는 짧게, 차단 불가를 전제로**: 5~15분. 피해 창은 수명으로 통제합니다.

- **RT는 stateful하게, 탈취를 전제로**: rotation + reuse detection + 패밀리 무효화. 도둑과 주인을 구분할 필요 없이, 충돌 즉시 전부 끊습니다.

- **세션은 3계층으로 사고하세요**: 앱 세션, IdP 세션(쿠키), SSO 세션(서버 상태)은 따로 만료됩니다. Keycloak에서 RT 수명은 세션 수명의 파생물이라는 점을 기억하세요.

- **로그아웃은 분산 트랜잭션입니다**: RP-Initiated Logout + token revocation + Back-Channel Logout 전파까지가 한 세트입니다.

- **SPA라면 BFF를 기본값으로**: 토큰을 브라우저에서 치우면 rotation의 동시성 문제와 XSS 유출이 함께 사라집니다.

- **사고 대응 절차를 미리 연습하세요**: 세션 강제 종료, consent 철회, 키 회전 명령을 런북으로 만들어 두면, 새벽 3시의 대응 속도가 달라집니다.

인증의 진짜 실력은 로그인 화면이 아니라 토큰이 만료되고, 회전하고, 폐기되는 그 보이지 않는 수명주기에서 드러납니다. 지금 운영 중인 시스템의 realm 설정을 열어, 각 타임아웃 값에 "왜?"를 물어보는 것부터 시작해 보시기 바랍니다.

참고 자료

- [OAuth 2.1 draft (draft-ietf-oauth-v2-1)](https://datatracker.ietf.org/doc/draft-ietf-oauth-v2-1/)

- [RFC 9700 - Best Current Practice for OAuth 2.0 Security](https://datatracker.ietf.org/doc/html/rfc9700)

- [RFC 6749 - The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749)

- [RFC 7009 - OAuth 2.0 Token Revocation](https://datatracker.ietf.org/doc/html/rfc7009)

- [RFC 7662 - OAuth 2.0 Token Introspection](https://datatracker.ietf.org/doc/html/rfc7662)

- [RFC 9449 - OAuth 2.0 Demonstrating Proof of Possession (DPoP)](https://datatracker.ietf.org/doc/html/rfc9449)

- [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)

- [OpenID Connect RP-Initiated Logout 1.0](https://openid.net/specs/openid-connect-rpinitiated-1_0.html)

- [OpenID Connect Back-Channel Logout 1.0](https://openid.net/specs/openid-connect-backchannel-1_0.html)

- [OpenID Connect Session Management 1.0](https://openid.net/specs/openid-connect-session-1_0.html)

- [Keycloak Documentation](https://www.keycloak.org/documentation)

- [Keycloak Server Administration - Managing user sessions](https://www.keycloak.org/docs/latest/server_admin/index.html)

- [Keycloak 26.6.0 Release Notes](https://www.keycloak.org/2026/04/keycloak-2660-released)

현재 단락 (1/244)

인증 시스템에서 가장 어려운 질문은 "어떻게 로그인시킬까"가 아니라 "**로그인 상태를 얼마나, 어떻게 유지할까**"입니다. 토큰 수명을 길게 잡으면 사용자 경험은 좋아지지만 탈취...

작성 글자: 0원문 글자: 11,132작성 단락: 0/244