🤍 전 강의 25% 할인 중 🤍

2024년 상반기를 돌아보고 하반기에도 함께 성장해요!
인프런이 준비한 25% 할인 받으러 가기 >>

  • 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    해결됨

spring boot를 사용한 social login

24.05.27 17:15 작성 조회수 106

0

Next.js와 Spring boot를 사용해서 소셜 로그인을 추가하려고 합니다.

소셜 로그인의 경우 코드와 토큰을 프론트에서 관리하지 않는 것이 좋다고 하여 백엔드에서 모든 로직을 처리하고 있습니다.

 

현재 프론트에서 window.location.href = "http://localhost:8080/oauth2/authorization/google";

위와 같은 경로로 백엔드로 소셜 로그인 요청을 보내고

 

백엔드에서는 소셜 로그인을 진행한 뒤에 유저 정보를 생성하고 JWT를 생성한 뒤 응답의 헤더에 쿠키 형태로 JWT를 넣어 response.sendRedirect("http://localhost:3000/auth/social");로 리다이렉트하고 있습니다.

 

프론트에서는 /auth/social 페이지에서 쿠키에 있는 JWT를 꺼내 유저 정보를 가져오는 API를 다시 호출해 유저 정보를 가져오고 있습니다.

이 후 auth.js 라이브러리를 통한 session 관리를 하고자 하는데 session을 업데이트 하려면 어떻게 해야 하나요..?

(session.user가 있는지 없는지를 통한 로그인 체크를 위해 사용한다고 이해했습니다.)

 

서버 컴포넌트에서 import { auth } from "@/auth"; 를 통해 가져온 session에 데이터를 넣어보았지만 데이터가 제대로 들어가지 않는 것 같아 조언을 구해봅니다..

답변 1

답변을 작성해보세요.

0

조금 복잡하긴 한데 POST /api/auth/session을 하시면 됩니다. csrfToken을 넣으셔야 할 수 있습니다. 다음 댓글 참고하세요. 서버컴포넌트라는 가정 하에 진행됩니다.

https://github.com/nextauthjs/next-auth/discussions/9715#discussioncomment-9225447

이우열님의 프로필

이우열

질문자

2024.05.27

if (csrfToken) {
  fetch("/api/auth/session", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      cookies: `authjs.csrf-token=${csrfToken}`,
    },
    body: JSON.stringify({
      csrfToken: csrfToken?.split("|")[0],
      user: {
        ...user,
      },
    }),
  });
} 

csrfToken을 추출해서 위의 링크 예시대로 요청을 보내봤습니다.

근데 jwt 콜백 함수로 넘어가지 않는 것 같네요...

지금 callbacks.jwt나 callbacks.session이 있는 상황이신가요? 지금 jwt가 아니라 session 쪽이 호출되고있는지도 모르겠습니다.

https://authjs.dev/reference/nextjs#unstable_update

이렇게 signOut같은 것 불러오는 것처럼 unstable_update를 불러서 세션 업데이트 하는 함수도 있네요.

이우열님의 프로필

이우열

질문자

2024.05.29

최대한 시도를 해봤는데 로직을 변경해야 할 것 같습니다..ㅎㅎ
스프링과 협업할 당시 동일 window.location.href = "http://localhost:8080/oauth2/authorization/google"; API 주소로 하이퍼링크 요청을 보내면

auth.js에서 세션에 유저 정보를 등록하고자 하는데 이 때 어떤 방식으로 해야 할까요..

일단 oauth의 핵심은 구글이 redirect url로 요청을 쏴준다는 것이고, 그 url에서 다시 POST /api/auth/session을 호출하셔서 세션 등록을 해야합니다.

이우열님의 프로필

이우열

질문자

2024.05.29

import { cookies } from "next/headers";
import { getUserInfo } from "./c/getUserInfo";
import { auth } from "@/auth";
import { redirect } from "next/navigation";

export default async function SocialRedirectPage() {
  const cookieStore = cookies();
  const accessToken = cookieStore.get("AccessToken")?.value!;
  const refreshToken = cookieStore.get("RefreshToken")?.value!;
  const csrfToken = cookieStore.get("authjs.csrf-token")?.value!;
  const pk = cookieStore.get("Pk")?.value!;

  const session = await auth();

  // console.log({ accessToken, refreshToken, csrfToken });

  const user = await getUserInfo(accessToken, pk);

  // console.log({ user });

  if (csrfToken) {
    const response = await fetch(
      `${process.env.NEXTAUTH_URL}/api/auth/session`,
      {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Cookie: `authjs.csrf-token=${csrfToken}`,
        },
        body: JSON.stringify({
          csrfToken: csrfToken?.split("|")[0],
          user: {
            name: user.nickname,
            email: user.email,
            image: user.profileImage,
          },
        }),
      }
    );

    // console.log({ response });
  }

  // console.log({ session });

  // redirect("/auth/social/c");

  return <div>Redirecting...</div>;
}

이런 식으로 짜봤습니다.
콜백으로 jwt, session 둘 다 사용하고 있어서 체크해보았지만 post 요청을 보내도 콜백 함수에는 찍히는게 없네요

response로 찍어본 post 요청에는 200으로 성공 코드가 돌아오긴 합니다..

콘솔에 user도 잘 나오는데 session을 찍어보면 null이라고만 뜨네요..

이우열님의 프로필

이우열

질문자

2024.05.30

며칠 간의 고생 끝에 해결했습니다..

auth.js의 구조 자체가 로그인이 인증되지 않으면 세션 값이 없으며 접근 또한 불가능하게 되어있다고 하네요..

소셜 로그인의 경우 Credentials를 통해 인증이 되지 않아 세션 데이터를 업데이트든 뭐든 할 수 없는 상황이었습니다.

 

제 해결 방법은 기존 아이디와 패스워드를 입력하고 진행되는 로그인 방식을 살리면서 소셜 로그인을 추가하는 방법이었기 때문에 분리가 필요했습니다.

 

클라이언트 요청

"use client";

import { signIn, useSession } from "next-auth/react";

signIn("social-login", { redirect: false, accessToken, refreshToken, pk })

 

src/auth.ts

// 기존 아이디 비밀번호 입력 로그인
Credentials({
  id: "default-login",
  name: "DefaultLogin",
  credentials: {
    userIdOrEmail: {},
    password: {},
  },
  ...
})

// 소셜 로그인
Credentials({
  id: "social-login",
  name: "SocialLogin",
  credentials: {
    accessToken: { label: "Access Token", type: "text" },
    refreshToken: { label: "Refresh Token", type: "text" },
    pk: { label: "User PK", type: "text" },
  },
  ...
})

이렇게 Credentials에 id를 부여하여 signIn을 진행했습니다.

이렇게 하니 const { status } = useSession(); 로 출력된 status가 unauthenticated에서 정상적으로 authenticated로 변경되는 것을 확인할 수 있었습니다.

로그인이 된 상태기 때문에 session에 접근해서 데이터도 확인할 수 있었습니다!!

흐어 고생하셨습니다. 분명 세션이 바뀌어야하는데 왜 안 되나 했더니 기존에 세션이 존재하지 않아서였군요.

채널톡 아이콘