220425

solsolsol·2022년 4월 25일
0

TIL

목록 보기
30/32

RefreshToken

accessToken

브라우저에서 백엔드에 이메일과 비밀번호를 전송하면 JWT를 통해 백엔드는 브라우저에게 accessToken을 발급해줬다. 이 과정을 인증(Authentication) 이라고 부른다.

이렇게 발급된 accessToken 은 사용자가 생성, 수정, 삭제와 같은 요청(request)을 할 때 header에 담겨서 백엔드에 전송된다.

백엔드는 이 accessToken을 가지고 로그인 만료 시간이 남아있는지, 올바른 사용자가 맞는지 등을 인가(Authorization)해서 요청에 대한 응답(response)을 보내준다.

accessToken은 탈취되면 안 되기 때문에 만료 시간을 정해둔다. 만료 시간이 지날 때마다 새롭게 로그인을 해야하는 번거로움이 있다. 이 부분을 해결하기 위해 토큰 재발급(refreshToken)이 생겼다.

refreshToken

사용자가 로그인 했을 때 백엔드는 JWT를 2개 만든다.

accessToken 은 payload 로 받고
refreshToken은 cookie 로 받는다. cookie의 httpOnly와 secure 옵션을 이용해 자바스크립트에서 꺼내 건드릴 수 없게 만든다.

사용자의 요청이 있을 때 인가 과정에서 토큰 만료가 확인되면 브라우저에 에러를 띄운다.

error: UNAUTEHNTICATED

브라우저는 백엔드에 restoreAccessToken을 요청한다. 이때 쿠키에 저장돼있던 refreshToken이 함께 들어간다.(쿠키에 있는 데이터들은 요청 시 자동으로 첨부가 되어서 백엔드에 들어감)
refreshToken 의 만료 기간은 1,2 달 정도 된다. 오랜 시간 로그인 하지 않으면 로그인 창으로 보낸다.
restoreAccessToken은 accessToken이 될 새로운 JWT를 만들어 브라우저에 보낸다.

  1. onError로 UNAUTHENTICATED 캐치 (if UNAUTHENTICATED ~)
  2. restoresAccessToken 요청
  3. 방금 실패한 API 요청 재시도

매우 빠른 속도로 이루어지기 때문에 유저는 에러가 뜨는지 조차 알 수 없다. 그렇기 때문에 이 과정을 silentAuth 라고 부른다.

실습

  1. restoreAccessToken mutation 만들기
 const RESTORE_ACCESS_TOKEN = gql`
    mutation restoreAccessToken {
      restoreAccessToken {
        accessToken
      }
    }
  `;
  1. 에러를 캐치하고 확인할 콜백함수를 포함한 onError 함수 작성
  // graphQLErrors(에러), operation(방금 실패한 쿼리), forward(전송)
  const errorLink = onError(({ graphQLErrors, operation, forward }) => {
    // 1-1. 에러를 캐치
    if (graphQLErrors) {
     
      for (const err of graphQLErrors) {

        // 1-2. 해당 에러가 토큰 만료 에러인지 체크(UNAUTHENTICATED)
        if (err.extensions.code === "UNAUTHENTICATED")
  1. refreshToken 으로 accessToken 재발급
	{  const graphQLClient = new GraphQLClient(
            // cookie 의 secure 옵션 
            "https 로 시작하는 endpoint"
          );
          const result = await graphQLClient.request(RESTORE_ACCESS_TOKEN);
          const newAccessToken = result.restoreAccessToken.accessToken;
          // 재발급 받은 accessToken을 global state에 저장
          setAccessToken(newAccessToken);

graphqlclient 세팅 전 useQuery, useMutaiton을 사용하기 위해 graphql-request 라이브러리 설치 필요 yarn add grapql-request

  1. 재발급 받은 accessToken으로 실패한 쿼리 재요청
          operation.setContext({
            headers: {
              // headers 에 저장된 내용들 spread로 가져온 후
              ...operation.getContext().headers, 
              // authorization만 새로운 데이터로 바꾸기
              Authorization: `Bearer ${newAccessToken}`,
            },
          });
          // 변경된 operation 재요청하기
          return forward(operation);
        }
      }
    }
  });

getContext() : api 에서 등록됐던 부분을 가져온다
setContext() : api 에 등록된 옵션을 바꾼다!

네트워크에서 graphql 요청에 refreshToken 이 들어와있는 걸 확인할 수 있다.

application의 쿠키에서도 확인 가능하다!

Graphql

Graphql은 endpoint가 POST/grapql 하나인 rest-api 방식으로 rest api의 언더페칭과 오버페칭 문제를 해결해준다. 데이터를 실행시킬 함수를 묶어서 보내줘야하기 때문에 create, fetch 에 상관 없이 항상 post 방식이다.

또한, POST/graphql 요청 자체는 무조건 성공이다. 한 번에 여러개의 api를 실행하기 때문에 어떤 게 성공하고 어떤 게 실패할지 알 수 없기 때문이다. 그렇기 때문에 네트워크에는 항상 요청 성공을 의미하는 200이 출력된다.

postman

graphql이 rest-api 이기 때문에 postman에서도 실행이 가능하다.

{
	"query": "query { fetchBoards{ writer, title, contents} }"
}

여기서 query 는 graphql의 query와 전혀 상관 없는 key 값이다. mutation 이든 query든 모두 query 이니 혼동하지 말 것.

axios

axios.post("endpoint", {"query": "mutation createBoard(writer: ... ){title, ... }"})

따라서 아래의 두 소스 코드는 같은 요청이라고 볼 수 있다.

graphQLClient 로 요청

const graphQLClient = new GraphQLClient(
      "endpoint",
      { credentials: "include" }
    );
    const result = await graphQLClient.request(RESTORE_ACCESS_TOKEN);
    const newAccessToken = result.restoreAccessToken.accessToken;
    return newAccessToken;

axios 로 요청

axios.post("endpoint", {
  query: `
  mutation restoreAccessToken {
    restoreAccessToken {
      accessToken
    }
  }
`

MSA(Micro Service Architecture)

API들을 관련있는 것들끼리 묶어서 잘게 쪼개는 것으로 요즘 백엔드의 트렌드.

MAS를 사용하는 이유

문제 발생 시 api 작동

이전에는 전체가 하나의 소스 코드에 있었기 때문에 api들을 한 번에 실행했다. 이때는 하나의 소스코드라도 문제가 있다면 모든 api들이 작동을 멈췄다. 하지만 MSA는 문제가 생긴 api의 폴더들만 작동하지 않는다.

배포

쉬운 배포가 가능하다. 배포를 할 때는 build 이후에 dev 하게 되는데 build 에서는 최적화 과정이 이루어진다. 하나의 소스 코드를 수정하더라도 모든 폴더를 다시 최적화해야 했던 이전과는 다르게 MSA는 소스 코드를 수정한 폴더만 최적화 과정을 거치면 된다.

AuthService

인증 관련 API들이 있는 폴더

  • login
  • logout
  • restoreAccessToken

Open Authentication(OAuth)

openAPI 형태로 인증 AuthService를 지원해주는 것. 이미 가입된 사이트의 로그인 정보를 이용해 로그인 하는 것으로 social login이라고도 불린다.

  • 구글 계정으로 로그인
  • 카카오 계정으로 로그인
  • 네이버 계정으로 로그인

ResourceService

인가 관련 API들이 있는 폴더

  • createBoard
  • fetchBoard
  • createProduct
  • fetchProduct
    .
    .
    .

ResourceService는 다시 관련된 요청끼리 묶어 BoardService, ProductService 로 나뉠 수 있다.

0개의 댓글