local stragy 전략을 사용하다가, 모바일에서 문제가 터졌다.
login을 하면 보통 token을 발급받고 retrofit interceptor에서 token을 심고 header로 보내는 방식이었는데,
login을 안하고 상시 백그라운드 작업이 들어가면서
token 만료기간이 문제가 된 것.
이 문제를 해결하기 위해 retrofit auth 를 설정해 줄 수 있지만
( 401이 떨어졌을때 token을 재발급 받아 다시 요청해 줄 수 있음 )
현재는 발급 조건이 login에만 붙어있기 때문에 비밀번호를 받을 수는 없었고,
만료된 토큰을 서버단에서 체크 한 후 다시 발급해주는 로직이 필요했다.
하지만 현재 개발중인 서비스에서는 user 관련 테이블에 token값을 저장하지 않고 있었고
(jwt 인증만 하고 id값 추출)
만료된 상태로 요청이 오기때문에 해당 api를 만든다고 해도 permitAll() 인 상태라 (401이 떨어지기 때문),
어디서든 접근이 가능했기 때문에 만료된 토큰만 가지고 어떤 행동을 하기에는 애매한 상태였다.
물론 이런식으로 토큰에 private한 값을 넣어서 조금 더 체크하기는 할 수 있지만
Claims claims = Jwts.claims().
setSubject(userPrincipal.getUsername())
.setIssuedAt(new Date());
claims.put("PRIVATE KEY", "PRIVATE VALUE");
jwt특성상 해독이야 쉽고 페이로드에 어떤 값을 추가하는것은 지양해야 한다.
그리하여 나온것이 refresh token인데,
사용하려면 access token / refresh token을 동시 최초 발급 한 후 DB에 보관해서
access token이 만료된 상태로 요청이 오게되면 DB에서 refresh token으로 인증을 먼저 한뒤
access token을 재발급 하는 식이다.
이렇게되면 어쨋든 refresh token은 access token보다 유효시간이 길어야 하고,
retrofit auth 설정에서 401이 떨어졌을 때에만 refresh token을 포함하여 인증 받아야 하고,
서버에서도 refresh token이 평소에 인증이 되야하는 것이 아니라, exccess token이랑 구분되어서 판단 해야한다.
또한, 긴 유효시간의 refresh token 탈취도 생각해 보아야한다 어쨋든 refresh token으로 access token을 생성 할 수 있기 때문에..
심지어 jwt토큰의 장점을 조금 무마시키는 storage를 따로 넣어줘야하기때문에
( db나 redis 등등 storage token column 두개 추가되니까. )
조금 부담스러운 면도 있다.
참고로 refresh 관련 로직은 카카오톡 developer 홈페이지에서 참고했다.
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
그럼 어떻게 진행해야 할까,
1.
redis를 이용해서 파기된 refresh token을 체크한다거나, KMS서비스인 vault를 사용할 수도 있지만
관리포인트가 늘어나서 소규모 프로젝트에는 필요하지 않을 수도 있다.
2.
sliding sessions 전략을 사용해 볼 수 있다.
요청마다 iat 시간값을 참조해서 token을 새로 발급한다거나
중요한 post/patch 작업 전에 발급이 된다거나 등등, 토큰 유지시간을 늘리는 방법이다.
3.
refresh token 및 sliding sessions 방법을 동시 적용 할 수도 있겠으나,
api에 많은 부하가 있을거 같다.
4.
평범하게 사용되는 refresh token 로직을 따라간다.
더닝크루거 효과가 로그인부분에서 제일 심하게 있는 듯 하다.
처음배울땐 정말 쉬웠지만..
배우면 배울수록..
권한 / 인증 토큰발급도 해주어야하고,
필요에 따라 MFA이나 AD연동도 생각해야 하고
spring security 적용도 해야하고,
여러개의 was를 사용시 session store도 고려해야하며..
이젠 토큰만료시 재발급도 고민하고 있는 중..
'프로그래밍 공부 > Spring Boot' 카테고리의 다른 글
[Slack] slack bot message (0) | 2022.10.19 |
---|---|
[Kotlin] java POI 를 이용한 write / download (0) | 2022.03.08 |
[Java] spring boot - firebase message server (11) | 2021.07.27 |
[Spring Boot/ldaps] AD 연동 (0) | 2020.07.24 |
[GraphQL] Spring Boot + 그래프QL 사용하기 (CRUD) (4) | 2019.07.08 |