티스토리 뷰

반응형

JWT를 통한 인증 절차

1.[프론트엔드] ID와 비밀번호를 준다.
2.[백엔드] ID와 비밀번호를 검증하고 AccessToken과 RefreshToken, AccessToken의 만료시간을 반환해준다. 이 때 생성한 RefreshToken은 DB에 {ID,RefreshToken}으로 저장한다.
3.[프론트엔드] 반환받은 AccessToken을 매 api 호출마다 헤더에 붙여서 전송한다.
4.[백엔드] api 호출시 헤더의 AccessToken을 확인하고 유효한지, 만료기간이 지났는지를 체크 후 api를 동작시킨다.
5.[프론트엔드] AccessToken의 만료기간이 지나거나, 30초 미만으로 남았다면, 백엔드에 RefreshToken을 붙여 Reissue요청을 보낸다.
6.[백엔드]Reissue 요청이 들어올 경우, RefreshToken이 DB에 있는 것인지 확인한 후, 맞다면 AccessToken과 새로운 AccessToken 만료 시간을 반환한다.
7.[프론트엔드] Reissue결과 반환된 AccessTolen과 만료기간을 저장하여 다음 api호출에 사용한다.

 

JWT 개념

accessToken만 생각했을 때 개념을 생각해보면, 로그인시 백엔드에서 암호화된 AcessToken을 주고, 프론트에서 api요청마다 AccessToken을 헤더에 첨부하여 사용자가 누구인지 백엔드에 알려주는것이다.

1.[프론트엔드] ID와 비밀번호를 준다.
2. [백엔드] ID와 비밀번호를 검증하고 AccessToken을 반환한다.
3. [프론트엔드] AccessToken을 받아 다음 api호출부터 헤더에 붙여준다.
4. [백엔드] api호출시 AccessToken이 유효한지 확인하여 처리한다.

이렇게 간단하게 구현한 방식에 가장 큰 단점은 AccessToken이 한번 탈취당할 경우, 공격자가 무제한을 api에 접근하여 정보를 채갈 수 있다. 그래서 만료시간이라는 개념이 나오는데, AccessToken을 발급할 때, 10분 혹은 30분으로 제한 시간을 둬서 시간이 지난 후에는 해당 AccessToken으로 접근할 수 없게 하는 것이다. 

1.[프론트엔드] ID와 비밀번호를 준다.
2. [백엔드] ID와 비밀번호를 검증하고 AccessToken을 반환한다.이 때 만료시간을 설정한다.
3. [프론트엔드] AccessToken을 받아 다음 api호출부터 헤더에 붙여준다.
4. [백엔드] api호출시 AccessToken이 유효한지 확인하여 처리한다.만료시간이 지나지 않았는지 확인하여 처리한다.

그러나, 이 경우 사용자가 10분, 30분마다 재 로그인을 해야한다는 문제가 생긴다. 이를 보완하기 위해 생긴것이 바로 
RefreshToken이라는 개념이 등장한다. 만료시간이 지났을 경우 RefreshToken을 통해AccessToken을 재발급 받을 수 있도록 구현하는 것이다.

여기서 의문이 생길 수 있다. 그럼 RefreshToken을 탈취당하면 무제한으로 AccessToken을 발급받을 수 있는 것이 아닌가? 맞다.. 따라서 RefeshToken을 더 안전한 곳에 보관할 것을 권장하고 있다. 그럼 애초에  AccessToken을 안전하게 보관하면 되는 문제가 아닌가? .. 

이에대한 문제는 해당 링크에서 참고하면 될듯하다. 

1. [프론트엔드] ID와 비밀번호를 준다.
2. [백엔드] ID와 비밀번호를 검증하고 AccessToken, RefreshToken을 반환한다. 이 때 AccessToken의 만료시간을 설정한다.
3. [프론트엔드] AccessToken을 받아 다음 api호출부터 헤더에 붙여준다. RefreshToken은 안전한 곳에 보관한다.
4. [백엔드] api호출시 AccessToken이 유효한지, 만료시간이 지나지 않았는지 확인하여 처리한다.
5. [프론트엔드] 만약 AccessToken이 만료되어 api 동작이 실패하였다면, RefreshToken을 백엔드에 줘서 Reissue를 건다.
6. [백엔드] Reissue요청이 오면, AccessToken을 새로 만들어 반환한다.

여기에서 RefreshToken의 가장 큰 문제점은 RefreshToken이 탈취될 경우 공격자가 무제한으로 AccessToken을 재발급 받을 수 있다는 것이다. 그래서 가장 최신의 RefreshToken을 DB에 저장하는 방식을 채택한다. 로그인할 때 새로운 RefreshToken을 발급하고, 동시에 DB에 저장한다. Reissue시에는 RefreshToken이 DB에 저장된 것과 같은지 비교한다. 이렇게하면 다른 환경에서 새로 로그인할 경우, 기존의 RefreshToken은 설령 만료 기간이 남았더라도 사용할 수 없게 된다.

이 방식에서는 api를 보내보고 실패할 경우 > reissue를 거는 방식이라 불필요한 api호출이 최소 한 번은 일어나게 된다. 그렇다면 AccessToken의 만료시간을 백엔드로부터 전달받아 만료시간이 다 되었다면 api를 호출하지 않고 Reissue를 먼저 호출한 후 api를 호출하도록 구현할 수 있다.

여기에 더해 고려애햐하는 것이 만료시간인데 프론트엔드에서 백엔드로 api를 요청하는 데는 시간이 걸린다. AccessToken의 만료 시간은 1:10이다. 사용자는 1:09에 api를 호출했다. 프론트엔드에서는 1:10이 지나지 않았기 때문에 Reissue를 하지 않고 그대로 백엔드로 보낸다. 그러나 백엔드에서는 1:10에 api요청을 받는다. 백엔드 입장에선 AccessToken이 만료되었기 때문에 이 api요청은 거부된다. 이 문제를 해결하기 위하여, 프론트엔드에서는 단순히 AccessToken의 만료시간이 지났는지를 기준으로 삼는 것이 아니라, 만료시간이 적게 남았을 경우 + 만료시간이 지났을 경우로 조건을 바꾸어 주어야 한다.

1. [프론트엔드] ID와 비밀번호를 준다.
2. [백엔드] ID와 비밀번호를 검증하고 AccessToken, RefreshToken, AccessToken의 만료시간을 반환해준다. 이 때 생성한 RefreshToken은 DB에 {ID, RefreshToken}으로 저장한다.
3. [프론트엔드]  반환받은 AccessToken을 매 api호출마다 헤더에 붙여준다. 
4. [백엔드] api호출시 AccessToken을 확인하고 유효한지, 만료기간이 지났는지를 체크 후 api를 동작시킨다.
5. [프론트엔드] 만약 AccessToken이 만료기간이 지나거나, 30초 미만으로 남았다면,백엔드에  RefreshToken을 붙여 Reissue 요청을를 보낸다.
6. [백엔드] Reissue요청이 오면,RefreshToken이 DB에 있는 것인지 확인한 후, 맞다면 AccessToken과 새로운 AccessToken 만료시간을 반환한다.
7. [프론트엔드] Reissue결과 반환된 AccessToken과 만료기간을 저장하여 다음 api호출에 사용한다.


참고 : https://han-um.tistory.com/17

반응형

'기타' 카테고리의 다른 글

CI/CD 와 GitHub Actions  (0) 2023.10.06
Node.js의 Timers  (0) 2022.09.28
Jest 유닛테스트(2) - Jest Mocking Modules  (0) 2022.02.12
Jest 유닛테스트(1)-[Jest] jest.fn() 함수  (0) 2022.02.12
Swagger란?  (0) 2022.02.05
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함