"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 를 봐야겠죠?
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 을 날리고 파라미터로 프로바이더 종류를 넘깁니다.
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 여기로 리다이렉트 시킨다는 점입니다.
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 과 같은 아디라면, 수파베이스 auth 에는 그냥 업데이트만 됩니다?