로그인 프로세스

·2022년 4월 17일
0

TIL

목록 보기
14/36
post-thumbnail

로그인 회원가입만 잘 만들 수 있으면 80%는 다 해요.

개발자의 길로 한발자국 내딪기 전에 웹사이트를 뒤지다가 봤던 말 중 하나다.
일반인에서 생각할 수 있는 회원가입은(내가 배우기 전)

  1. 필요한 정보 적어서 회원가입하면 DB에 그게 저장되고
  2. 아이디 비번을 적으면 로그인이 된다!

두단계만 있으면 되는거아냐? 라고 생각을 했다.

그래서 "아니 저게 뭐가 어렵길래 저것만 할 줄 알면 거의 다 할 수 있다는거지??" 라는 의문을 가졌다.

코캠에 들어오고, 로그인 프로세스 수업을 듣고 나서, 저 말을 이해 할 수 있었다.


로그인 상태 유지는 어떻게 하지?

배우기 전에 잠깐 했던 생각이 있었다.

내가 아이디랑 비밀번호를 쳤어, 그게 DB에 저장된게 맞으면 로그인이 되겠지
근데 내가 로그인을 하긴 했는데 그걸 어떻게 유지를 시키는건데?

우리는 어딘가 로그인을 할 때 내가 미리 설정한 아이디, 비밀번호 단 2개만을 이용하여 접속을 하게 된다.
그리고 아무렇지 않게 사용하고 있던 것들이 나를 괴롭혔다.

Token 그리고 JWT (JSON Web Token)

바로 알맞은 아이디와 비밀번호를 쳐서 로그인을 할 경우
Token 이라는 것이 발급되어 그 유저가 사용하는 웹페이지(게임이라면 클라이언트)를 따라다니면서
얘는 아까 접속한 마요에요! 라고 반복적으로 증명을 해주게 된다.

그럼 Token에는 무슨 정보가 있기에 증명을 할 수 있는 것일까?

Token이 발급되는 과정은 쉽게 표현을 하여 이런식으로 돌아간다.

  1. 유저가 접속할 때 사용한 아이디와 비밀번호를 기반으로 암호화 작업을 거쳐 난수의 값으로 Token이 생성된다.
  2. 유저는 그 토큰을 계속 가지고 다닌다.
  3. 본인을 증명해야되는 일이 생길 때 Token을 백엔드로 발송한다. (로그인한 사람만 할 수 있는 것)
  4. 백엔드는 그것을 복호화(암호를 푼다)해서 그 속에 담겨져있는 값들이 DB에 있는지 확인한다.
  5. DB에 담겨져있다면 유저가 요청한 것을 할 수 있도록 제한을 풀어준다
    5-1 DB에 담겨져있지 않다면 유저가 요청한 것을 거부한다.

이런 과정으로 빙글빙글 돌아가게 된다.

그리고 이 과정 중 암호화와 복호화를 작업해주는 것이 있는데,
이것이 바로 JWT이고, 인터넷 표준이기에 많은 사이트들에서 이 방식을 활용하고 있다.

그럼 Token이 뭔지 알았고, JWT가 뭔지 어느정도는 알게 된 것 같다.
유저를 인증하려면 토큰이 필요한데 토큰을 만들고, 해부해서 확인을 하는 것을 JWT가 해준다고.

그럼 말이 아닌 코드를 보면서 흐름을 따라가보도록 하자.

일단, nestjs에서는 jwt 라이브러리가 기본적으로 등록이 되어있어서 jwtServcie를 주입해서 사용하면 된다.


auth.resolver.ts

맨 처음부터 생각을 하는 것이다.

  1. 아이디와 비밀번호를 작성해서 로그인 버튼을 누른다.
  2. DB에서 들어온 이메일로 회원가입을 한 유저인지 확인을 한다.
    2-1 DB에 정보가 없다면, 회원 가입을 하지 않은 유저입니다. 에러 발생
    2-2 DB에 정보는 있지만, 비밀번호가 다르다면 비밀번호가 다릅니다. 에러 발생
  3. 아이디 비밀번호가 일치하다면 DB에서 찾아온 user의 데이터를 인자로 사용해 토큰 생성 api 실행

요즘 사이트들은 이메일이나 비번 둘 중 하나만 틀려도 이메일 비번 둘 중 하나가 틀리다고 에러보내길래 나도 저렇게 적어놨다.

auth.service.ts

(어 여기 갑자기 헷갈리는데 뭐지....?)

  1. 인자로 받아온 user의 정보 중 몇가지를 사용하고
  2. token의 비밀번호와 유효시간을 지정하여 생성된 token을 유저에게 반환
    2-1. 토큰의 시간은 expiresIn에서 지정할 수 있는데 1m 1h 1d 1w 순서대로 분 시 일 주로 구성된다.

주의점 !!!
토큰은 누구나 볼 수 있고, 복호화 또한 쉽게 할 수 있기 때문에 (jwt 사이트가면 해줌)
중요한 정보를 담지 않고 사용하는 것이 좋다. 최소한의 정보로 확인하기
-> 이때문에 JWT 방식이 안전하지 않다. 라고 하는 의견도 있다고 한다.

어? 근데 위에 RefreshToken은 뭔데?

유저가 접속했는지 안했는지 확인을 하기 위해 Token을 생성하지만
그 Token은 손쉽게 강탈할 수 있기 때문에 최대한 짧은 시간을 지정하여 생성하는 것이 원칙이라고 한다.

그렇다면 Token 시간이 만료되면 로그인이 풀리는 것과 같기 때문에 로그인을 새로 해줘야하는데
툭하면 로그인 풀리면 유저가 짜증난다고 다시는 사이트를 쓰지 않을 수 있기 때문에
방지책으로 Token을 생성함과 동시에 RefreshToken도 함께 생성해서 쿠키에 담아 보내준다.

그렇다면 RefreshToken은 어떻게 사용이 되는걸까?

흐름을 이해하면, 손쉽게 알 수 있다.

참고!
짧은 시간으로 유지되는 Token인 AccessToken 줄여서 AT
긴 시간 유지되는 Token인 RefreshToken을 RF 이라고 적어나가겠다. (원래 이렇게 안쓰는데 길어서)


  1. AT가 만료된 상태로 로그인 한 상태에서만 할 수 있는 작업을 유저가 요청함
  2. 백엔드에서 AT가 만료된 상태라며 에러를 프론트로 발생
  3. 프론트는 에러를 확인하고 유저의 쿠키에 담겨져있는 RF를 헤더에 담아서
    백엔드에 새로운 AT를 생성하는 api 요청
  4. 백엔드는 RF가 정상적인지 복호화를 해서 검증
  5. 검증이 완료됐다면 새로운 AT를 만들어서 프론트로 반환
  6. 프론트는 받은 AT로 1번에서 유저가 요청했던 작업을 재실행

위와 같은 흐름으로 새로운 토큰을 재발급받아 로그인 상태를 유지하며, 로그인일 경우 할 수 있는 작업을 할 수 있게끔 하게 된다.


그럼 여기서 의문이 몇가지가 생긴다.

  1. RefreshToken은 무결한가?
  2. 쿠키란 무엇인가?

1번에 대한 답은 아래와 같다.

열람 불가 등 보안 설정을 해줄 수 있는 것들이 옵션들이 존재해서,
RefreshToken은 생성을 하면서 쿠키에 담을 때 그것을 걸어놓기에 비교적 안전하다.
(무결하다라는 말은 쉽게 쓸 수가 없기에)

2번에 대한 답은 아래와 같다.

이건 크롬 설명이 더 좋아보여서 긁어왔다.

한번이라도 방문해서, 무언가 작업을 했다면 쿠키라는 저장공간에 쌓여있는 것을 이야기한다.

조금 더 손쉽게 이해를 해본다하면, 특정 웹사이트들은 로그인을 해놓고, 브라우저를 껐음에도 불구하고
로그인이 유지되는 것을 볼 수 있는데, 이러한 옵션을 가지고 있는 곳이 쿠키다.

여기서 조금 공부를 해둔 사람이라면 의문이 생길 수 있는 내용이 존재하는데.

그것은 바로 브라우저에 저장공간으로 활용할 수 있는 것이 2가지가 더 있기 때문일 것이다.

바로 localStoragesessionStorage 가 존재하는데
비교적 쉽게 생각을 한다면 localStorage는 하드디스크와 같은 역할을 하며
sessionStorage는 램과 같은 역할을 한다.

하지만 두가지 모두 백엔드에서는 사용을 하지 못하고, 브라우저 상에서만 사용을 할 수 있기 때문에
RefreshToken은 쿠키에 담아서 보내주게 된다.


다시 로그인 프로세스를 정리해보면

  1. 아이디와 비밀번호를 작성해서 로그인 버튼을 누른다.
  2. DB에서 들어온 이메일로 회원가입을 한 유저인지 확인을 한다.
  3. 아이디 비밀번호가 일치하다면 DB에서 찾아온 user의 데이터를 인자로 사용해 토큰 생성 api 실행
  4. 백엔드에서 api를 실행을 해서 가져온 유저의 데이터 일부로 토큰을 생성
    4.1 토큰은 AccessToken, RefreshToken 두개가 있으나 후자는 쿠키에 담아서 발송
  5. 유저는 쿠키에는 리프레시토큰, 브라우저에는 엑세스토큰이 떠다니고 있는 상태

가 되어 유저가 접속하고 있는지, 아닌지 확인을 할 수 있게 된다.

왜 이것이 80%를 해당하는지에 대한 설명은 조금 모자른 것 같은데

그것은 로그인 프로세스에서 이어지는 인증, 인가쪽으로 넘어가야할 것 같아서
글이 너무 길어질 것 같아 여기서 잘라보려고 한다.

그리고 이미 충분히 길다

profile
물류 서비스 Backend Software Developer

0개의 댓글