ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NextJS - next-auth
    NextJS 2022. 9. 13. 10:42

    인증 방법

    1. Server-side Sessions

    - 서버 사이드 세션은 서버에 고유 식별자를 저장하는 방식

        ㆍ1. 고유한 세션 ID를 생성하고 DB같은 서버에 저장하고 클라이언트에 동일한 식별자를 전송

        ㆍ2. 클라이언트는 해당 ID, 해당 식별자를 저장

        ㆍ3. 서버의 보호된 리소스에 요청을 보낼 때 저장된 식별자 첨부

        ㆍ4. 서버에는 들어오는 요청에서 해당 식별자를 추출해 저장된 식별자가 맞는지 확인

        ㆍ5. 식별자가 옳다면 액세스를 허가하고 틀렸다면 액세스를 거부

    - 식별자의 도난은 연결을 암호화하는데 SSL을 사용하니깐 전송 중에는 도난 X

    - 클라이언트 사이드에선 대체로 쿠키에 식별자를 저장하는데 사이트 간 스크립팅(Cross site scripting) 공격을

       방지하기 위해 JavaScript를 통해서는 쿠키에 접근할 수 없도록 구성한다. 

    - 그러면 나가는 요청에 첨부되었을 때 서버에서만 읽을 수 있다.

    - 사이트 간 스크립팅 공격을 막을 수 있다면 클라이언트 사이드 저장소에 저장된 인증 권한은 아주 안전할 것

     

    2. Authentication Tokens

    - 서버가 어떤 식별자도 저장하지 않는다. 대신 임의의 문자열인 토큰을 생성하고 서명한다.

    - 클라이언트는 해당 토큰을 저장하고 나가는 요청에 다시 첨부해 서버에 액세스를 허가해도 된다고 알린다.

    - 그 토큰을 DB에 저장해 두지 않았더라도 서버는 해당 토큰에 어떻게 서명했는지 기억하고 있다.

     

    * SPA가 왜 세션 대신 토큰을 사용하는 이유 * 

    - 모든 페이지에서 서버에 요청(getServerSideProps)을 보내지 않는다.

        ㆍ서버가 인증여부를 직접 확인할 수 없는 상태에서 페이지가 로드

    - 싱글페이지 애플리케이션에 사용되는 백엔드 API는 일반적으로 무상태

        ㆍ연결된 개별 클라이언트를 신경 X

        ㆍAPI 자체는 연결된 클라이언트에 대한 어떠한 추가 정보 저장 X

    - 클라이언트가 본인이 인증되었음을 증명하는 독립적 권한을 얻어야 한다. - 토큰 사용

     

    npm install --save-exact next-auth@3

    - 전부 /api/auth로 시작하며 NextAuth에서 처리

    npm install bcryptjs

    - password 암호화

    export const hashPassword = async (password) => {
        hash(password, 12);
    }

    - 두번째 인수는 솔트(Salt)의 라운드(Round) 값을 정한다

        ㆍ암호화 정도를 결정하는 값

        ㆍ값이 크면 함수완료가 오래 걸리고, 작으면 보안성이 떨어진다.

     

    NextAuth

    * config *

    import NextAuth from "next-auth";
    import Providers from "next-auth/providers";
    
    export default NextAuth({
        // 인증된 사용자에 대한 세션을 관리하는 방법을 구성할 수 있는 객체
        session:{},
        providers: [
            // 고유의 크리덴셜을 제공
            Providers.Credentials({
                // NextAuth가 우리 대신 로그인 양식을 만들어줌
                credentials: {}
    
                // 들어오는 로그인 요청을 Next.js가 수신할 때 호출해주는 메서드
                // 크리덴셜이 유효한지 확인하고 아니라면 사용자에게 알림
                async authorize(credentials, req) {
    
                }
            }),
        ]
    });

     

    * 클라이언트 사용 *

    import {signIn} from "next-auth/client";
    
    if(isLogin){
      const result = await signIn('credentials',{
        redirect:false, // 페이지이동 X - next는 Error가 뜨면 404페이지로 이동하기에
        email: enteredEmail,
        password: enteredPassword
      });
    
      console.log(result);
    }
    import {useSession} from "next-auth/client";
    
    const [session, loading] = useSession();

    - session : 세션의 활성 상태를 나타내는 세션(session) 객체

    - loading : 사용자가 현재 페이지에 로그인된 상태인지 로그아웃된 상태인지를 Next.js가 확인하는 요소

    import {signOut} from "next-auth/client";
    
    
    const logoutHandler = () => {
      signOut();
    }

    - 쿠키와 세션 정보를 Next.js가 삭제함으로써 활성화된 사용자의 기록을 없애준다.

     

    useSession VS getSession

    - useSession : 즉시 여기 이 세션과 로딩을 가져오고 세션 데이터가 가져와지면 세션과 로딩을 전부 변경

        ㆍ로그아웃해서 세션이 없다면 세션은 변경되지 않는다. 로딩도 유지

        ㆍ로딩이 유지되기에 Loading 페이지를 만들어주면 Loading에 멈춰있음

    - getSession : 새 요청을 보내서 최근 세션 데이터를 가져온다.

        ㆍ해당 요청에 대한 응답에 반응

        ㆍ세션을 가져오는 동안 로딩 상태를 관리하며 적절하게 행동 가능

     

    ex1) 클라이언트 사이드 가드

    import {getSession} from "next-auth/client";
    
    const [isLoading, setIsLoading] = useState(true);
    
    useEffect(()=> {
        getSession().then(session => {
            if(!session){
                window.location.href = '/auth';
            }else{
                    setIsLoading(false);
            }
        })
    }, []);
    
    if(isLoading){
        return <p className={classes.profile}>Loading...</p>;
    }

    ex2) 서버사이드 가드

    export const getServerSideProps = async (context) => {
      const session = await getSession({req: context.req});
    
      if(!session) {
        return {
          redirect: {
            destination: '/auth',
            permanent: false
          }
        };
      }
    
      return {
         props: {session}
      };
    };

    댓글

Designed by Tistory.