[Study-Hub] Jwt 인가 + 보안관련 문제
프로젝트를 진행하며 팀원과 함께 코드리뷰를 하던 중 부족한 부분이 많이 보여 정리해보고자 한다.
문제점
1. User 엔티티의 Id 값을 그대로 파라미터로 받아온 것
2. Jwt 인가 과정에서 로직을 잘못 작성해서 nullPointerException 에러가 발생한 것
User 엔티티의 Id 값을 파라미터로 받아오면 무슨 문제가 생길까?
Study Hub 서비스에서 User 관련정보에는 이메일, 학년, 전공 등 개인정보가 다수 포함돼 있으므로 절대 노출돼서는 안된다. 만약 악성 사용자에 의해 User 엔티티의 Id 값을 담은 HttpRequest 가 탈취될 경우 악성 사용자는 Id 값을 이용해 게시글 삭제, 회원탈퇴 등을 자유롭게 할 수 있게 되는것이다.
이를 방지하기 위해 Jwt accessToken 을 발급해 Controller 의 파라미터로 Token 만 보낸 뒤 서버측에서 이를 디코딩해 Claim 에 있는 User 엔티티의 id 값을 받아오는 방법을 선택한 것이다.
아래 그림은 Token 이 전송되었을때 이를 User 엔티티의 id 값으로 변환해 Controller에 전달해주는 로직이다.
위와같은 방법을 사용하면 User 엔티티의 Id 값을 따로 받을 필요가 없는데 코드를 작성할 때 생각이 짧아 아래처럼 토큰과 User 엔티티의 Id 를 모두 받는 로직을 작성했다.
[수정 코드]
평소 알고리즘 문제를 풀 때 아래 세가지 순서대로 문제를 푼다.
1. 문제를 읽고 시간복잡도, 공간복잡도를 고려해 어떤 알고리즘을 사용할 것인지 생각한다.
2. 어떤 알고리즘을 사용할 지 나왔으면 그 알고리즘의 정의에 대해 생각한다.
3. 코드를 작성한다
만약 개발 시 위의 세가지 순서를 따랐으면 왜 Jwt 토큰을 사용했는지 생각할 수 있을것이고 User 엔티티의 Id 값을 파라미터로 보내는 코드를 작성하지 않았을 것이다.
단순히 동작하기 위해 코드를 짜지말고 왜 라는 질문을 항상 던져보자.
두번째 조회는 회원 단건 조회 API 에서 발생한 문제였다.
아래 그림처럼 Client 가 보낸 AccessToken 을 AuthorizationFilter 에서 받은 뒤 Token 이 유효한지 검증 하고 이를 ArgumentResolver 로 보내 로직을 수행해야한다.
하지만 스웨거에서 Authorize 값에 토큰을 넣어 코드를 실행했을 때 계속 nullPointerException Error 가 발생했다.
그래서 위의 코드에 한줄한줄 로그를 찍어 확인한 결과 메소드 실행 시 올바른 AccessToken 값을 보내도 isHeaderVerify 값이 false가 되는 것이었다.
로직 문제가 아니라 스웨거가 문제였다.
accessToken 을 담아줄 때 우측 하단에 있는 Authorize 안에 토큰값을 담아줬는데 이 "Authorize" 가 Http Header의 키값이었던 것이다.
근데 isHeaderVerify 메소드에서 Http 헤더에 존재하지도 않는 ACCESS_TOKEN 이라는 key 값만 하루종일 찾고있으니 false 가 반환될 수밖에 없는것이다.
이후 "ACCESS_TOKEN" 을 "Authrorize" 로 바꾼 뒤 실행시켜주니 정상작동했다.
같이 프로젝트 진행하는 웰빙도우 님께서 잘 캐치해주셔서 쉽게 해결했다.
https://github.com/study-hub-inu/study-hub-server
GitHub - study-hub-inu/study-hub-server
Contribute to study-hub-inu/study-hub-server development by creating an account on GitHub.
github.com