Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next auth 구현 및 fetch 추상화 개선 #40

Merged
merged 23 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
887bce9
🔨 settings: Next-Auth 패키지 설치 및 환경변수 추가 및 유효성 검사 추가 #10
froggy1014 Jul 29, 2024
6f19a63
🔨 settings: auth 파일 alias 설정 #10
froggy1014 Jul 29, 2024
8cfda3e
🔨 settings: next-auth 기본 config 파일 생성 #10
froggy1014 Jul 29, 2024
2451d58
🔨 settings: 카카오, Next-Auth 관련 환경변수 유효성 검사 업데이트 #10
froggy1014 Jul 30, 2024
ac5333a
🔨 settings: middleware 세팅 #10
froggy1014 Jul 30, 2024
f56c508
✨ feat: auth.js signIn 테스트를 위한 세팅 #10
froggy1014 Jul 30, 2024
7bee494
✅ test: 로그인 리다이렉트 테스트 페이지 #10
froggy1014 Jul 30, 2024
078509d
📝 docs: .env.local.example 업데이트 #10
froggy1014 Jul 30, 2024
649f0db
Merge branch 'feature/onboarding-final' into feat/next-auth
froggy1014 Aug 18, 2024
48c079f
✨ feat: 카카오 스크립트 시작 컴포넌트 추가 #10
froggy1014 Aug 19, 2024
fcd0978
✨ feat: 카카오버튼 로그인 버튼 구현 #10
froggy1014 Aug 19, 2024
b7035e3
🔧 chore: next Auth 사용으로 인한 KakaInit 컴포넌트 제거
froggy1014 Aug 19, 2024
cab45e1
Merge branch 'develop' into feat/next-auth
froggy1014 Aug 21, 2024
4e4c1b0
🔨 settings: jose 패키지 설치 #10
froggy1014 Aug 22, 2024
6fd08f2
✨ feat: auth, profile 관련 API, Type 정의 #10
froggy1014 Aug 22, 2024
d3826a6
✨ feat: extractKeyFromArray, isMatchPath 유틸함수 추가 #10
froggy1014 Aug 22, 2024
f81a3c1
🔧 chore: login 엔드포인트 수정 #10
froggy1014 Aug 22, 2024
9ce0871
✨ feat: auth 관련 세팅 및 callback 핸들링 구현 #10
froggy1014 Aug 22, 2024
dfb542c
✨ feat: 인스턴스 분리로 인한 코드 변경 #10
froggy1014 Aug 22, 2024
f4f79d5
♻️ refactor: 컴포넌트 분리 및 린팅 에러 제거 #10
froggy1014 Aug 22, 2024
4fbfe5e
🐛 fix: instance 분리 롤백 #10
froggy1014 Aug 22, 2024
3196eaa
👷 cicd: remove reviewers
froggy1014 Aug 24, 2024
bdb2a59
🔧 chore: corret the typo
froggy1014 Aug 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.local.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
AUTH_SECRET=<openssl rand -base64 32>
AUTH_KAKAO_ID=<KAKAO_JAVASCRIPT_KEY>
AUTH_KAKAO_SECRET=<openssl rand -base64 32>
NEXT_PUBLIC_STAGE=<STAGE>
NEXT_PUBLIC_BASE_URL=<BASE_URL>
NEXT_PUBLIC_BASE_URL=<BASE_URL>
6 changes: 3 additions & 3 deletions .github/auto_assign.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ addAssignees: author

reviewers:
- punchdrunkard
- Zero-1016
- seokzin
- saseungmin
# - Zero-1016
# - seokzin
# - saseungmin

numberOfReviewers: 4

Expand Down
147 changes: 147 additions & 0 deletions auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// ? Reference https://github.dev/nextauthjs/next-auth-example/blob/main/app/api/protected/route.ts
// ? Reference https://www.heropy.dev/p/MI1Khc

import { decodeJwt } from "jose";
import NextAuth, { Account, NextAuthConfig, Session, User } from "next-auth";
import { AdapterUser } from "next-auth/adapters";
import { JWT } from "next-auth/jwt";
import { ProviderType } from "next-auth/providers";
import Kakao from "next-auth/providers/kakao";

import {
getRefreshToken,
getServerSideSession,
postOauthLogin,
} from "@/apis/auth/auth";
import { SocialLoginRequest } from "@/apis/auth/authType";
import { isMatchPath } from "@/utils";

const AuthRequiredPage = ["/mypage"];

const config = {
providers: [Kakao],
// ? 사용자 지정 로그인, 로그아웃 및 오류 페이지를 만들 때 사용할 URL을 지정합니다. 지정한 페이지는 해당 기본 제공 페이지를 재정의합니다.
pages: {
signIn: "/auth/sign-in",
},
callbacks: {
// * protected page 설정
authorized({ request, auth }) {
const { pathname } = request.nextUrl;

if (isMatchPath(pathname, AuthRequiredPage)) {
return !!auth;
}

return true;
},
// * callbackUrl이 있다면 callbackUrl로 리다이렉트
redirect: async ({ url, baseUrl }: { url: string; baseUrl: string }) => {
if (url.startsWith("/")) return `${baseUrl}${url}`;
if (url) {
const { search, origin } = new URL(url);
const callbackUrl = new URLSearchParams(search).get("callbackUrl");
if (callbackUrl) {
const session = await getServerSideSession();

// 프로필 등록안했으면 onboarding으로
if (!session?.isProfileRegistered) {
return `${baseUrl}/onboarding`;
}

return callbackUrl.startsWith("/")
? `${baseUrl}${callbackUrl}`
: callbackUrl;
}
if (origin === baseUrl) return url;
}
return baseUrl;
},
// ? 이 콜백은 JSON 웹 토큰이 생성되거나(즉, 로그인할 때) 업데이트될 때마다(즉, 클라이언트에서 세션에 액세스할 때마다) 호출됩니다.
// ? 여기서 반환하는 모든 내용은 JWT에 저장되어 세션 콜백으로 전달됩니다. 여기에서 클라이언트에 반환할 항목을 제어할 수 있습니다.
// ? 그 외의 모든 내용은 프런트엔드에서 보관됩니다. JWT는 기본적으로 AUTH_SECRET 환경 변수를 통해 암호화됩니다.
jwt: async ({
token,
account,
user,
}: {
token: JWT;
user?: User | AdapterUser;
account?: Account | null;
}) => {
if (token.accessToken) {
const decodedToken = decodeJwt(token.accessToken);

if (decodedToken.exp && decodedToken.exp * 1000 < Date.now()) {
const { accessToken, refreshToken } = await getRefreshToken(
token.refreshToken as string,
);
token.accessToken = accessToken;
token.refreshToken = refreshToken;
return token;
}

return token;
}

if (!user?.id || !user.email || !account?.access_token) {
throw Error("Login Failed");
}
const body: SocialLoginRequest = {
id: user?.id,
email: user?.email,
accessToken: account?.access_token,
};

const response = await postOauthLogin(body);

token.accessToken = response?.accessToken;
token.refreshToken = response.refreshToken;
token.isProfileRegistered = response.isProfileRegistered;
token.email = user.email;

return token;
},
// ? 로그인한 사용자의 활성 세션입니다.
session: async ({ session, token }: { session: Session; token: JWT }) => {
if (token?.accessToken) {
session.accessToken = token.accessToken;
session.refreshToken = token.refreshToken;
session.isProfileRegistered = token.isProfileRegistered;
}
return session;
},
},
// ? 인증 및 데이터베이스 작업에 대한 디버그 메시지를 사용하려면 디버그를 true로 설정합니다.
// debug: process.env.NODE_ENV !== "production" ? true : false,
} satisfies NextAuthConfig;

export const { signIn, signOut, handlers, auth } = NextAuth(config);

declare module "next-auth" {
// * 카카오 Account 응답에 맞게 수정
interface Account {
access_token?: string;
token_type?: string;
refresh_token?: string;
expires_in?: number;
refresh_token_expires_in?: number;
expires_at?: number;
provider: string;
type: ProviderType;
providerAccountId: string;
}
// * 세션이 accessToken 필드값 추가 ( 필요에 따라 더 추가 )
interface Session {
accessToken?: string;
refreshToken?: string;
isProfileRegistered?: boolean;
}
}
declare module "next-auth/jwt" {
interface JWT {
accessToken?: string;
refreshToken?: string;
isProfileRegistered?: boolean;
}
}
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@
"@radix-ui/react-progress": "^1.1.0",
"@tanstack/react-query": "^5.50.1",
"@tanstack/react-query-devtools": "^5.50.1",
"@types/kakao-js-sdk": "^1.39.5",
"canvas-confetti": "^1.9.3",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"dayjs": "^1.11.12",
"framer-motion": "^11.3.24",
"jose": "^5.7.0",
"lodash": "^4.17.21",
"next": "14.2.4",
"next-auth": "5.0.0-beta.20",
"nuqs": "^1.17.8",
"path-to-regexp": "^7.1.0",
"react": "^18",
"react-daum-postcode": "^3.1.3",
"react-dom": "^18",
Expand Down
Loading