Skip to content

fix(auth): migrate e-mail-keyed storage only for a verified e-mail - #751

Merged
yeongseon merged 1 commit into
mainfrom
fix/issue-750-migrate-verified-email-only
Oct 5, 2026
Merged

yeongseon merged 1 commit into
mainfrom
fix/issue-750-migrate-verified-email-only

Conversation

@Eomdahyeon

Copy link
Copy Markdown
Collaborator

Closes #750

문제

#740 (#731) 이 넣은 로그인 시 이전은 user:<e-mail> 아래 저장된 브라우저 데이터를 로그인한 계정의 sub:<issuer>#<subject> 키로 옮기면서 그 e-mail 이 검증된 것인지 보지 않았다. 공용 브라우저에서 주소를 주장하기만 하는 계정이 그 주소 아래 저장된 것을 가져가고, 이전은 복사가 아니라 이동이라 되돌릴 수 없다. 제가 넣은 코드의 결함이다.

변경

  • features/auth/store.ts: emailVerified: boolean. OIDC 세션에서만 참이 될 수 있고, mock 세션·로그아웃 상태는 거짓이다.
  • features/auth/init.ts: 토큰의 email_verified 를 읽는다. 리터럴 true 만 인정한다 — 클레임이 없거나 문자열 "true" 이면 검증되지 않은 것으로 본다.
  • features/auth/storageOwner.ts: migrateEmailOwnedStorage 는 emailVerified 가 아니면 아무것도 옮기지 않는다.
  • CHANGELOG.

소유 키 자체(resolveStorageOwnerKey)는 바꾸지 않았다. 미검증 계정도 자기 sub: 키 아래에 저장하고 읽는다 — 막는 것은 e-mail 키의 데이터를 가져오는 것뿐이다.

테스트

  • __tests__/storageOwner.test.ts: 미검증 계정의 로그인은 아무것도 옮기지 않고 원래 항목이 그대로 남으며, 그 뒤 검증된 계정이 로그인하면 옮겨진다. 값을 주지 않은 identity 는 미검증이고 clear() 가 거짓으로 되돌린다.
  • features/auth/init.test.ts: 실제 로그인 경로(initAuth → syncIdentity)에서 email_verified 가 true / 없음 / false / 문자열 "true" 인 네 경우 — 첫 경우만 옮긴다.
  • 기존 이전 테스트는 검증된 identity 로 돌게 했다(도우미의 기본값). 그 기본값 없이 돌리면 기존 테스트 2개가 실패한다 — 새 조건이 실제로 걸린다는 뜻이다.

검증

  • npx vitest run __tests__/storageOwner.test.ts src/features/auth → Tests 64 passed (64).
  • npx tsc --noEmit, npx eslint src/features/auth __tests__/storageOwner.test.ts 출력 없음.
  • 전체 스위트는 로컬에서 돌리지 않았다 — CI 에 맡긴다. 실제 Keycloak 토큰으로 확인하지도 않았다.

알아 둘 것

  • 이미 옮겨진 데이터는 되돌리지 않는다. refactor(auth): own browser storage by issuer and subject instead of e-mail #740 머지(2026-10-04) 뒤 미검증 계정으로 로그인한 브라우저가 있었다면 그 이전은 이미 끝났다. Builder 가 미검증 토큰을 401 로 거절하므로 그런 계정이 실제로 쓰였을 가능성은 낮다고 보지만 확인한 것은 아니다.
  • Keycloak 클라이언트에 email scope 가 없어 access token 에 email_verified 가 실리지 않는 배포에서는 이전이 일어나지 않는다. 그런 배포는 Builder 도 토큰을 거절한다(docs/troubleshooting.md 의 email_verified Precondition).

🤖 Generated with Claude Code

The sign-in migration moved browser data saved under user:<e-mail> to the
signed-in account's issuer+subject key whatever the token said about the
address. On a shared browser, an account that only claims an address took the
data saved under it, and the move is not a copy. Read email_verified from the
token and move nothing unless it is true.

Closes #750

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@yeongseon yeongseon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diff 를 읽었고 CLEAN 이라 승인합니다. 리터럴 true 만 인정하고(없음·false·문자열 "true" 는 미검증), 실제 로그인 경로(initAuth → syncIdentity)에서 네 경우를 테스트합니다. 소유 키 자체는 그대로 두고 e-mail 키의 데이터를 가져오는 것만 막은 범위도 맞습니다.

이미 옮겨진 데이터는 되돌리지 않는다는 점은 본문대로 알아 두면 됩니다.

@yeongseon
yeongseon merged commit 916bba7 into main Oct 5, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(auth): the storage migration does not check that the account's e-mail is verified

2 participants