IT

nuxt-auth/next-auth의 끔찍한 rotation refresh token 문제

bepuri 2023. 8. 1. 14:47
728x90

nuxt-auth는 next-auth를 기반으로 만들어진

nuxt framework 진영의 인증 모듈이다.

 

nuxt3로 넘어오면서 sidebase라는 곳에서 nuxt-auth를 개발 유지보수 중인데,

이게 next-auth를 기반으로 만들어진거라 여러모로 next-auth 도큐먼트를 살펴봐야하는 상황이 생기기도하고,,

nuxt-auth에는 문제가 없더라도 next-auth 자체에 이슈가 있었더라면 원인을 찾는데로 한세월 걸릴수도 있다.

 

당연히 next-auth도 함께 찾아봐야되는데 뭘 기반으로 만들었는지 제대로 모르면 nuxt-auth 쪽만 살펴보고 헤매게 될 여지가 있기 때문이다.

 

쨋든 결론만 말하자면, next-auth에서 rotation refresh token을 구현하는데 치명적인 오류가 있다..

이건 nuxt-auth githut repo에서도 언급됐고, next-auth도 마찬가지로 언급되어있었다..

 

race condition 문제인데, 예를들어 jwt token은 페이지가 새로고침이 일어날때 호출된다.

이외에도 갱신시간을 설정하거나, tab이 활성화 되거나 등 다양한 상황에서 jwt callback이 일어나는데,

보통 이 callback함수에서 token을 갱신하는 코드를 작성한다.

 

근데 여기서 치명적인 오류가 페이지 새로고침이 빠른속도로 일어나는 경우 jwt callback함수에서 token이 갱신중임에도 다시 token이 갱신되는 코드가 호출될수 있다.

 

그럼 갱신된 코드를 blacklist에 추가하지 않는 경우라면 상관없지만 blacklist에 추가하게끔 백엔드에서 로직을 짜놨다면 token 갱신에 오류가 생기는거다. 왜냐면 이미 갱신을 위해 사용한 refreshtoken이 만료되었는데 해당 token을 또 사용하려고 했으니 말이다.

 

이슈에 댓글이나 PR, discussion을 살펴보았을땐 server side에서는 lock을 통해서 해결 하는 방법밖엔 없다는 것이 다수의 의견이였다, redis같은걸써서 lock을 걸어버리는것 밖엔 없다고 했다. 아래 이슈 코멘트를 보면 누가 구현해놨는데 상당히 고통스러웠다고 ㅎ 이걸 next-auth쪽에 포함시켜달라고하니 메인테이너가 redis에 dependency가 생기면 안된다고 거부했다.ㅎ

https://github.com/nextauthjs/next-auth/issues/2071

그리고 좀 더 간단한 방법으로 navigator.locks를 통해 client side에서도 유사한 이슈를 해결할수 있는데 lock을 통해서 해결하는 코드를 PR로 올리니 메인테이너가 peer dependencies를 만드는게 적절한지 모르겠다고 언급하며 해당 이야기로 논의하다가 논의 당시 navigator.locks은 일부 브라우저에서 미지원 상태였기 때문에 대부분의 브라우저에서 지원하는 시점인 navigator.locks v4가 랜딩되면 다시 이야기하자고 하며 PR을 닫아버렸는데 이미 랜딩된지 꽤 시간이 흘렀음에도 별다른 논의가 되고 있지않고 있다..

 

따라서 rotation refresh token은 언급된 lock을 통해서 token이 업데이트 되는 과정이라면 과거 토큰을 가지고 토큰을 refresh 하지 않아야된다..

말이야 쉽지 이걸 구현하는 과정에서는 다양한 부가적인 문제가 생길수 있다..ㅜ 그걸로 next-auth 쪽에서도 여러가지 의견들이 많이 논의되었는데.. 사실 가장간단한방법은 blacklist에 token을 추가하지 않으면 가장 간단하다.

하지만 보안상 refresh token이 탈취되면 악용될 가능성이 있기 때문에, 보안상 바람직하진 않을듯하다.ㅜㅜ

728x90