SNS 계정 연결의 이메일 일치 조건 제거 — 현재 로그인과 새 제공자 인증을 서버에서 확인 · 다른 계정에 연결된 제공자는 거부 · 세션 만료 시 재로그인 안내

This commit is contained in:
Sn-Kinos
2026-10-10 21:14:49 +09:00
parent b66863a149
commit 4d2ce67886
8 changed files with 175 additions and 81 deletions
+30 -3
View File
@@ -96,11 +96,38 @@ describe('SNS 연동', () => {
expect(await codeOf(call({ accessToken: 'good', link: true }, OLD_UID))).toBe('E-AUTH-08');
});
it('이메일이 다르면 붙이지 않는다(different-email) · 카카오 이메일이 없으면 비교를 건너뛴다', async () => {
it('이메일이 달라도 · 카카오 이메일이 없어도 연결한다 — 이메일 일치는 소유 확인이 아니다', async () => {
await getAuth().createUser({ uid: GOOGLE_UID, email: 'fan@fanuzu.co.kr' });
stubKakao('other@kakao.com');
expect(await codeOf(call({ accessToken: 'good', link: true }, GOOGLE_UID))).toBe('different-email');
stubKakao('FAN@fanuzu.co.kr');
expect(await call({ accessToken: 'good', link: true }, GOOGLE_UID)).toEqual({ linked: true });
await getAuth().deleteUser(GOOGLE_UID);
await getAuth().createUser({ uid: GOOGLE_UID, email: 'fan@fanuzu.co.kr' });
stubKakao();
expect(await call({ accessToken: 'good', link: true }, GOOGLE_UID)).toEqual({ linked: true });
const user = await getAuth().getUser(GOOGLE_UID);
expect(user.providerData.some((d) => d.providerId === KAKAO_PROVIDER_ID && d.uid === KAKAO_ID)).toBe(true);
});
it('세션이 폐기된 뒤의 토큰 · 정지된 계정으로는 붙이지 않는다', async () => {
await getAuth().createUser({ uid: GOOGLE_UID });
const before = Math.floor(Date.now() / 1000) - 60;
await getAuth().revokeRefreshTokens(GOOGLE_UID);
const linkAs = (authTime: number) => fnAuthKakao.run(
{ data: { accessToken: 'good', link: true }, auth: { uid: GOOGLE_UID, token: { auth_time: authTime } } } as Req,
);
expect(await codeOf(linkAs(before))).toBe('session');
await getAuth().updateUser(GOOGLE_UID, { disabled: true });
expect(await codeOf(linkAs(Math.floor(Date.now() / 1000) + 5))).toBe('session');
expect((await getAuth().getUser(GOOGLE_UID)).providerData).toEqual([]);
});
it('이미 다른 카카오가 붙어 있으면 E-AUTH-09 · 같은 카카오면 그대로 성공', async () => {
await getAuth().createUser({ uid: GOOGLE_UID });
await getAuth().updateUser(GOOGLE_UID, { providerToLink: { providerId: KAKAO_PROVIDER_ID, uid: '111' } });
expect(await codeOf(call({ accessToken: 'good', link: true }, GOOGLE_UID))).toBe('E-AUTH-09');
await getAuth().deleteUser(GOOGLE_UID);
await getAuth().createUser({ uid: GOOGLE_UID });
expect(await call({ accessToken: 'good', link: true }, GOOGLE_UID)).toEqual({ linked: true });
expect(await call({ accessToken: 'good', link: true }, GOOGLE_UID)).toEqual({ linked: true });
});
});