From 932c93628496a5155c472ca909d04861b6aeed4d Mon Sep 17 00:00:00 2001 From: Henry Jang Date: Mon, 19 Oct 2026 11:41:06 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EA=B4=80=EB=A6=AC=20=EC=BD=98=EC=86=94?= =?UTF-8?q?=20SSO=EB=8A=94=20lodestar=EC=9D=98=20MFA=20acr(=EC=8B=A0?= =?UTF-8?q?=EB=A2=B0=20=EA=B8=B0=EA=B8=B0=20=ED=8F=AC=ED=95=A8)=EC=9D=84?= =?UTF-8?q?=20=EB=B0=9B=EC=95=84=20=EC=BD=98=EC=86=94=206=EC=9E=90?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EA=B1=B4=EB=84=88=EB=9B=B4=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 왜: 2026-10-19 사용자 결정 — SSO로 들어올 때 IdP에서 이미 MFA를 했으면 콘솔에서 다시 묻지 않는다(다른 서비스처럼). lodestar는 MFA 세션에 acr `https://refeds.org/profile/mfa`를 싣고, 신뢰 기기 로그인도 같은 acr이다. 편의를 위해 신뢰 기기까지 lodestar 판단에 맡기기로 했다. 문서에는 "계약 없이 로컬 TOTP"라고 적혀 있어 실제 운영과 달랐다. - OPERATIONS §8 E3: 계약 값(acceptAcr + maxAgeSec 43200 = 콘솔 세션 절대 수명), 신뢰 기기 포함이라는 대가, TOTP만 받으려면 amr 기반(`requireAmrAll: ["totp"]`)으로 바꾸는 방법, step-up은 여전히 로컬 TOTP. - oidc-client.ts 머리 주석의 낡은 lodestar 설명을 고쳤다. 코드 변경 없음. Co-Authored-By: Claude Opus 5.5 --- docs/OPERATIONS.md | 6 +++++- packages/core/src/oidc-client.ts | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index a1635ce..3adad36 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -338,7 +338,11 @@ Bearer 토큰 입력 칸은 없앴다. API 키(`api-key-create`)는 REST 자동 - 응답의 acr이 목록에 있거나 amr에 지정한 값이 모두 있고, `auth_time`이 N초 안이면 그 로그인을 MFA로 인정한다. - 요청한 값(acr_values·max_age)이 아니라 **응답의 클레임**으로만 판정한다. - 계약이 없거나 응답이 충족하지 못하면 로컬 TOTP를 묻는다(생략·폴백 없음). - - ⚠ lodestar는 지금 ID 토큰에 amr이 없고 acr에 신뢰 기기가 섞여, TOTP 계약을 적을 수 없다. 계약 없이 쓰고 로컬 TOTP를 요구한다. + - lodestar(관리 콘솔 SSO): `acr`이 MFA(`https://refeds.org/profile/mfa`)이고 인증 시각이 12시간(콘솔 세션 절대 수명) 안이면 인정한다 — + `{"acceptAcr":["https://refeds.org/profile/mfa"],"maxAgeSec":43200}`. lodestar는 **신뢰 기기 로그인도** 이 acr을 주므로, + 그 경우에도 콘솔 6자리를 묻지 않는다(2026-10-19 사용자 결정 — 편의를 위해 신뢰 기기까지 lodestar 판단에 맡긴다). + TOTP 증거만 받으려면 lodestar가 amr을 싣게 된 뒤(`amr`에 `totp`, 신뢰 기기는 `trusted_device`) `requireAmrAll: ["totp"]`로 바꾼다. + - 계약이 있어도 민감·파괴 명령의 재확인(step-up)은 로컬 TOTP다 — 콘솔 TOTP는 등록해 둬야 한다. - 지원 제한: 민감 작업의 재확인(step-up)은 언제나 **로컬 TOTP**다(IdP 재인증 step-up은 없다). 그래서 관리 콘솔 관리자는 IdP 계약을 충족해도 로컬 TOTP를 먼저 등록해야 한다. 셀프서비스는 미등록이면 목록만 볼 수 있다(D3). - IdP에서 사용자를 정지해도 이미 열린 세션은 그대로다(IdP 철회 신호를 받지 않는다). 세션 수명 안에서 유지되고, diff --git a/packages/core/src/oidc-client.ts b/packages/core/src/oidc-client.ts index f010161..4000172 100644 --- a/packages/core/src/oidc-client.ts +++ b/packages/core/src/oidc-client.ts @@ -10,7 +10,8 @@ * - 요청한 `acr_values`·`prompt=login`·`max_age`만으로 충족으로 보지 않는다 — **응답의 클레임**만 본다. * - `auth_time`이 계약의 최근성 안이어야 한다. refresh로 받은 토큰의 iat를 새 MFA 시각으로 보지 않는다(refresh를 쓰지 않는다). * - 계약이 없거나 응답이 충족하지 못하면 **MFA 생략·자동 폴백 없이** 로컬 TOTP를 요구한다(호출자 몫 — `mfaSatisfiedAt`이 null). - * lodestar는 현재 ID 토큰에 amr이 없고 acr에 신뢰 기기가 섞여 계약을 충족할 수 없다(orc 경유 보고, 2026-10-18). + * lodestar는 MFA(신뢰 기기 포함) 세션에 acr `https://refeds.org/profile/mfa`를 싣는다. 관리 콘솔은 이 acr을 계약으로 받는다 + * (2026-10-19 사용자 결정 — 신뢰 기기까지 lodestar 판단에 맡김, OPERATIONS §8). TOTP만 받으려면 amr 기반 계약을 쓴다. */ import { createHash, randomBytes } from "node:crypto"; import { decodeJwt, JwtError, verifyJwt, type Jwk, type JwtClaims } from "./jose.ts";