인증 상태에 따른 페이지 접근제한

jew·2024년 5월 27일

내가 원하는 조건 ->

  • 로그인 상태가 아닐 경우 접근 제한: /signin 이외의 모든 route ('/today, /calendar')
  • 로그인 상태일 경우 접근 제한: /signin
  • 실제 페이지에 접근 후 리다이렉트되는 게 아니라 그 이전에 서버에서 체크

그런데 클라이언트 쪽에서 인증 페이지를 구분하고 로그인 페이지로 리다이렉트할 경우 인증되지 않은 사용자가 페이지를 방문했을 때 일시적으로 화면이 표시된 후 페이지가 리다이렉트되면서 깜박거린다 !

루트에 있는 middleware.ts를 많이 사용하시길래 방법을 찾아봤는데, middleware.ts 파일에서 요청하면 API 라우트 또는 페이지 요청 전에 실행되기 때문에 보호해야 할 경로에 대한 초기 접근 제어가 가능하다고 한다.

나는 세션을 가져와서 사전 체크를 진행했는데, (세션 써본적없어서 ... 궁금해서) 구글링 해보니까 쿠키에 담긴 토큰을 확인하는 사례가 많더라.?? 이 부분은 나중에 보안 관련해서 더 찾아보고 수정할 것 같다.

// 로그인해야 접근할 수 있는 루트[]
const protectedRoutes = ['/today', '/calendar']

export async function middleware(request: NextRequest) {
  const response = await updateSession(request)
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: { 
    	/* 쿠키 get/set/remove 설정 */
      },
    },
  )

  // session 값 여부에 따라 리다이렉션
  const { data: { session }, error} = await supabase.auth.getSession() 

  if (request.nextUrl.pathname === '/signin' && session) {
    url.pathname = '/'
    return NextResponse.redirect(url)
  }

  if (protectedRoutes.includes(request.nextUrl.pathname)) {
    if (!session) {
      url.pathname = '/signin'
      return NextResponse.redirect(url)
    }
  }
  if(error) {
    console.error(error)
  }
  return response
}

(하단은 추가 구현 내용)

로그인 없이 접근하면 안되는 페이지에 접근하면, 그때 유저의 세션 확인으로 접근 제한했으면 좋겠는데 로그인하지 않은 상태로 웹페이지에 들어가기만 해도 세션없다는 에러가 뜬다. 먼가 좋은 방법이 없을까....

위 문제 방법을 찾고 수정했다. (글의 3차 시도 부분)
+ 사용자 정보 전역 관리

문제 하나 더 찾았다.

  • 일반 로그인 성공 -> '/'로 이동하는데, fetchUser로 데이터 들어오기 전에 서버에서 session 먼저 체크해서 '/'로 이동하기 때문에 로그인 상태가 아닌 상태로 페이지 이동을 하는 상황으로 보인다. (task create하려고 하면 user.id가 null, 새로고침을 하면 데이터가 들어온다.)
  • oauth 로그인 성공 -> '/signin'에 그대로 있는데, fetchUser가 먼저 작동되었는지 사이드바에 유저 데이터가 들어와 있다.

일반 로그인 버그는 로그인 버튼 함수끝에 이걸로 해결함

if (response && response.error) {
        alert('일치하는 계정이 없습니다. 다시 작성해주세요. ')
      } else {
        await checkisLogin() // 요거
      }
      
  • oauth 로그인 이거 이 부분 이유를 알아냄 황당함ㅋ
const handleGoogleLogin = async () => {
    const supabase = createClient()
    const { error } = await supabase.auth.signInWithOAuth({
      provider: 'google',
      options: {
        redirectTo: 'http://localhost:3000/auth/callback', // 이 부분을 안 쓰고 있었음 그리고 기존에 내가 위에서 작성한 액션 함수는 경로가 잘못되어서 적용이 안되고 잇엇음!!!
        queryParams: {
          access_type: 'offline',
          prompt: 'consent',
        },
      },
    })

이렇게 옳은 경로로 수정해주니 원하던 대로 oauth 성공하면 /로 이동된다. 황당하다. 공식문서를 잘 읽자.

profile
문제 있으면 의식의 흐름대로 작성하는 블.log

0개의 댓글