Step 7. 프로바이더 로그인 버튼 예시
"use client";
import useAuth from "@/hooks/useAuth";
import { showAlert } from "@/lib/openCustomAlert";
import { usePathname } from "next/navigation";
import { FcGoogle } from "react-icons/fc";
function GoogleLogInButton() {
const { loginWithProvider } = useAuth();
const pathname = usePathname();
const handleClickGoogle = async () => {
if (pathname === "/recover") {
return showAlert("caution", "비밀번호 복구 페이지에서는 소셜로그인이 불가합니다");
}
loginWithProvider("google");
};
return
<FcGoogle className="w-11 h-11 cursor-pointer" onClick={handleClickGoogle} />;
}
export default GoogleLogInButton;
대략 위처럼 만들면 됩니다.
그러면 loginWithProvider 를 봐야겠죠?
Step 8. loginWithProvider 함수
const loginWithProvider = async (provider: string) => {
try {
setIsPending(true);
const response = await fetch(
`${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/provider?provider=${provider}`
);
if (!response.ok) {
throw new Error("fetch 실패");
}
const data = await response.json();
queryClient.invalidateQueries({ queryKey: ["user"] });
router.replace(data.url);
showAlert("success", "로그인 성공");
} catch (error) {
console.error(error);
}
};
대략 위처럼 생겼습니다.
/api/auth/provider 를 향해서 get 을 날리고 파라미터로 프로바이더 종류를 넘깁니다.
Step 9. route handler(provider)
import { createClient } from "@/supabase/server";
import { Provider } from "@supabase/supabase-js";
import { NextRequest, NextResponse } from "next/server";
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const provider = searchParams.get("provider");
const supabase = createClient();
const { data, error } = await supabase.auth.signInWithOAuth({
provider: provider as Provider,
options: {
redirectTo: `${process.env.NEXT_PUBLIC_BASE_URL}/api/auth/callback`,
},
});
if (error) {
return NextResponse.json({ error: error?.message }, { status: 401 });
}
return NextResponse.json(data, { status: 200 });
}
역시 대략 위처럼 생겼읍니다.
포인트는 /api/auth/callback 여기로 리다이렉트 시킨다는 점입니다.
왜 그러한가? 수파베이스가 그렇게 하라고 했기때문입죠.
Step 10. route handler(callback)
import { createServerClient, type CookieOptions } from "@supabase/ssr";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get("code");
const next = searchParams.get("next") ?? "/";
if (code) {
const cookieStore = cookies();
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
cookieStore.set({ name, value, ...options });
},
remove(name: string, options: CookieOptions) {
cookieStore.delete({ name, ...options });
},
},
}
);
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (!error) {
return NextResponse.redirect(`${origin}${next}`);
}
}
// 여기도 auth-code-error 이런 페이지가 있어야 리다이렉트 되니 미리 만들어놓아야함
// 싫으면 다른데로 보내면 됨
return NextResponse.redirect(`${origin}/auth/auth-code-error`);
}
// 만일 소셜 로그인인데, 이메일이 같으면(깃헙로그인이든 구글이든) 수파베이스 auth 에는 그냥 업데이트만 됨
callback 은 위처럼 생겼습니다.
코드 내용물은 supabase 가이드와 똑같으니 참고 하면 될 것 같습니다.
여기참고
그런데 희한한 점은 소셜 로그인인데 이메일이 같을 경우...
예를들어 깃헙에 사용된 이메일이 gmail 이고 이것이 google 과 같은 아디라면,
provider가 다름에도 하나의 로우만 생기고,
접속시간등도 수파베이스 auth 스키마에는 그냥 업데이트만 됩니다? 허허
때문에 프로필 수정등을 해도 아이디가 같다면 다른 provider 로 접속했어도
똑같이 업데이트만 되므로 주의를 요합니다.
'nextjs' 카테고리의 다른 글
[240717 TIL] Next.js Sharp (0) | 2024.07.17 |
---|---|
[240716 TIL] NextJs Pwa (0) | 2024.07.16 |
[240714 TIL] Supabase 인증인가 with NextJs 2편 (0) | 2024.07.13 |
[240711 TIL] Supabase 인증인가 with NextJs #1 (1) | 2024.07.11 |
[240704 TIL] (공식문서번역)Template.tsx (0) | 2024.07.04 |