Skip to content

Feat(auth): 심사용 로그인 플로우 및 JWT 발급 로직 추가#98

Open
annalee8595 wants to merge 5 commits intodevfrom
feat/review-auth
Open

Feat(auth): 심사용 로그인 플로우 및 JWT 발급 로직 추가#98
annalee8595 wants to merge 5 commits intodevfrom
feat/review-auth

Conversation

@annalee8595
Copy link
Contributor

이슈 번호

close #97

주요 변경사항

  • 심사용 접근을 위한 Review 로그인 API (POST /auth/review/login) 추가
  • 소셜 로그인(Kakao) 없이도 JWT 발급이 가능하도록 별도 인증 플로우 분리
  • 기존 인증 구조(JWT + DB 사용자 존재 + AccessTokenGuard)를 그대로 재사용
  • 심사용 로그인은 아래 3가지 환경 변수 조건을 모두 만족할 때만 허용
    REVIEW_LOGIN_ENABLED=true
    요청 secret === REVIEW_LOGIN_SECRET
    요청 email ∈ REVIEW_LOGIN_ALLOWED_EMAILS (comma-separated allowlist)
  • 심사용 유저는 DB에 존재해야 하므로, 로그인 시 유저 자동 생성(upsert) 처리
  • 심사용 계정은 기본 프로필 값으로 생성되어 onboardingRequired=true가 반환되도록 유지 -> 온보딩을 반드시 거치는 심사 플로우 지원
  • Review 로그인은 review/staging 환경에서만 활성화 가능하도록 env 기반 제어

테스트 결과 (스크린샷)

스크린샷 2026-02-10 오전 6 16 39

참고 및 개선사항

  • 현재 review 계정은 AuthProvider.KAKAO를 사용 → CI/CD 환경에서 Prisma enum 마이그레이션 부담을 줄이기 위해
  • 장기적으로 리뷰 계정을 분리 관리할 경우 AuthProvider.REVIEW enum 추가 검토 가능

Copilot AI review requested due to automatic review settings February 9, 2026 21:21
@annalee8595 annalee8595 linked an issue Feb 9, 2026 that may be closed by this pull request
2 tasks
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a dedicated “review login” authentication path that can issue JWTs without Kakao OAuth, while also enhancing Kakao login to persist additional profile attributes and switching cookie handling to cookie-parser.

Changes:

  • Introduces POST /auth/review/login flow (controller/service/DTOs) gated by REVIEW_LOGIN_* env settings, including user auto-create and refresh-token rotation.
  • Extends Kakao login upsert to store birthdate, age, and sex when available from Kakao profile data.
  • Replaces custom cookie parsing middleware with cookie-parser and adds related env schema/dependencies.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/modules/auth/services/review-auth.service.ts Implements review-login gating, user upsert, JWT issuance, and refresh-token rotation.
src/modules/auth/controllers/review-auth.controller.ts Adds POST /auth/review/login endpoint and sets refresh token cookie.
src/modules/auth/dtos/review-login-request.dto.ts Defines request DTO for review login (email/secret).
src/modules/auth/dtos/review-login-response.dto.ts Defines response DTO for review login (access token + onboarding flags + user).
src/modules/auth/services/kakao-auth.service.ts Persists additional Kakao profile fields (birth info, sex) during upsert.
src/modules/auth/auth.module.ts Registers the new controller/service in the auth module.
src/main.ts Uses cookie-parser middleware instead of a custom cookie header parser.
src/config/env.schema.ts Adds REVIEW_LOGIN_* environment variables to the validated schema.
package.json Adds cookie-related dependencies.
package-lock.json Locks new dependencies and updates some pinned versions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

"@prisma/client": "7.2.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.3",
"cookie": "^1.1.1",
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

cookie is added as a direct dependency, but there are no direct imports/usages of the cookie package in the source (only cookie-parser). Unless something outside this PR relies on importing cookie directly, consider removing it to avoid carrying an unused dependency and duplicate cookie versions in the lockfile.

Suggested change
"cookie": "^1.1.1",

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +109
this.logger.debug(
`process.env.REVIEW_LOGIN_ENABLED=${process.env.REVIEW_LOGIN_ENABLED}`,
);
this.logger.debug(
`process.env.REVIEW_LOGIN_SECRET=${process.env.REVIEW_LOGIN_SECRET}`,
);
console.log(
'[DEBUG] REVIEW_LOGIN_ENABLED',
process.env.REVIEW_LOGIN_ENABLED,
);
console.log('[DEBUG] REVIEW_LOGIN_SECRET', process.env.REVIEW_LOGIN_SECRET);
console.log(
'[DEBUG] REVIEW_LOGIN_ALLOWED_EMAILS',
process.env.REVIEW_LOGIN_ALLOWED_EMAILS,
);

Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

assertReviewLoginAllowed logs REVIEW_LOGIN_SECRET (and other env values) via Logger.debug and console.log. This can leak the review-login secret and allowlist into application logs (including centralized log shipping), effectively weakening the protection on this endpoint. Remove these statements and, if diagnostics are needed, log only non-sensitive booleans (e.g., enabled flag / whether secret is configured) without printing secret values.

Suggested change
this.logger.debug(
`process.env.REVIEW_LOGIN_ENABLED=${process.env.REVIEW_LOGIN_ENABLED}`,
);
this.logger.debug(
`process.env.REVIEW_LOGIN_SECRET=${process.env.REVIEW_LOGIN_SECRET}`,
);
console.log(
'[DEBUG] REVIEW_LOGIN_ENABLED',
process.env.REVIEW_LOGIN_ENABLED,
);
console.log('[DEBUG] REVIEW_LOGIN_SECRET', process.env.REVIEW_LOGIN_SECRET);
console.log(
'[DEBUG] REVIEW_LOGIN_ALLOWED_EMAILS',
process.env.REVIEW_LOGIN_ALLOWED_EMAILS,
);

Copilot uses AI. Check for mistakes.
Comment on lines +280 to +316
private buildBirthInfo(
birthyear?: string,
birthday?: string,
): { birthdate?: Date; age?: number } {
if (!birthyear || !birthday || birthday.length !== 4) {
return {};
}

const year = Number(birthyear);
const month = Number(birthday.slice(0, 2));
const day = Number(birthday.slice(2));
if (!Number.isInteger(year) || !Number.isInteger(month)) {
return {};
}
if (month < 1 || month > 12 || day < 1 || day > 31) {
return {};
}

const birthdate = new Date(Date.UTC(year, month - 1, day));
if (Number.isNaN(birthdate.getTime())) {
return {};
}

const today = new Date();
const currentYear = today.getUTCFullYear();
const currentMonth = today.getUTCMonth() + 1;
const currentDay = today.getUTCDate();
let age = currentYear - year;
if (currentMonth < month || (currentMonth === month && currentDay < day)) {
age -= 1;
}
if (age < 0) {
return {};
}

return { birthdate, age };
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

buildBirthInfo accepts any day 1-31 and then constructs a Date with Date.UTC(...), which will silently roll invalid dates (e.g., 02/31) into the next month, producing an incorrect birthdate and age. Since this data comes from an external provider, add a strict validity check (e.g., verify birthdate.getUTCMonth() === month - 1 and birthdate.getUTCDate() === day, and also validate day is an integer) before returning { birthdate, age }.

Copilot uses AI. Check for mistakes.
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.

[Feature] 심사용 로그인 API 추가

2 participants