211019コードキャンプ32日目


RefreshToken
  • 以前に学んだAccessTokenは、登録データを記録して登録の有無を判断することができる.
    しかし、ほとんどのサイトではセキュリティなどの理由で有効期限が設定されています.
    有効期限が過ぎた場合、AccessTokenが有効期限が切れた場合、新しいAccessTokenを受信するプロセスRefreshTokenって!
  • AccessTokenの有効期限が1時間の場合、ユーザーは1時間ごとに再ログインする必要があります.そうなると、とても不便で探したくないサイトになるかもしれません.
    このため、AccessTokenを発行する場合には、RefreshTokenを同時に発行することもできる.
  • であれば、AccessTokenが期限切れになっても、RefreshTokenはこっそりユーザーにログインし、新しいAccessTokenを気兼ねなく入手し、ユーザーに自然なサイト利用を提供することができます.
  • でもRefreshTokenは満期時間もあるので、RefreshTokenが満期になったら再登録します.
  • RefreshTokenの適用_app.js
      useEffect(() => {
        // const accessToken = localStorage.getItem("accessToken") || "";
        // setAccessToken(accessToken); // 이 두줄은 로컬스토리지에 저장하는 방법
        if (localStorage.getItem("refreshToken")) getAccessToken(setAccessToken);
      }, []);
    // 만약 로컬 스토리지에 refreshToken가 true 값으로 존재할 경우 AccessToken을 받아온다.
      const errorLink = onError(({ graphQLErrors, operation, forward }) => {
        // @apollo/client의 onError의 기능을 사용한다.
        if (graphQLErrors) {
          for (const err of graphQLErrors) {
            if (err.extensions?.code === "UNAUTHENTICATED") {
              operation.setContext({
                headers: {
                  ...operation.getContext().headers,
                  authorization: `Bearer ${getAccessToken(setAccessToken)}`,
                },
              });
              return forward(operation);
            }
          }
        }
      });
      const client = new ApolloClient({
        link: ApolloLink.from([errorLink, uploadLink]), // 순서가 중요!
        cache: new InMemoryCache(),
      });
    login.tsx
    ...
    export default function LoginPage() {
      ...
        async function onClickLogin() {
        const result = await loginUser({
          variables: {
            email: myEmail,
            password: myPassword,
          },
        });
        localStorage.setItem("refreshToken", "true"); 
        // LocalStorage에 refreshToken을 true값으로 저장해준다.
        setAccessToken(result.data?.loginUserExample.accessToken);
        router.push("/32-02-login-success");
      }
      ...
      return (
        <>
          이메일 : <input type="text" onChange={onChangeEmail} />
          <br />
          비밀번호 : <input type="password" onChange={onChangePassword} />
          <br />
          <button onClick={onClickLogin}>로그인하기</button>
        </>
      );
    }