✍🏼 write by @주원 서 / Siena
🚨 문제
토큰이 없는 요청에 대해 401 대신 403 응답을 반환하는 문제를 발견했습니다.
☄️ 원인 : @Secured
어노테이션의 보안 적용 방식의 미흡한 이해
역할(Role) 기반으로 API 접근을 제어하기 위해 @EnableMethodSecurity(securedEnabled = true)를
설정하면서 메서드 수준의 보안이 활성화 하였고, @Secured 어노테이션을 접근 권한을 제어하였습니다.
처음에는 어노테이션을 설정하지 않으면 인증된 사용자만 접근 가능할 것이라고 예상했지만
@Secured를 적용하지 않은 경우, Spring Security 필터와 설정에 의해 인증이 되지 않은 사용자도 접근이 가능한 상태가 되었습니다.
@Secured는 인증된 사용자에 대해서만 역할(Role) 기반 접근 제어를 수행하지만, 어노테이션이 없을 경우 인증이 필요하지 않게 되어, 보안이 적용되지 않는 문제가 발생했습니다.
즉, @Secured를 사용하면 인증된 사용자에 대한 역할 검증만 수행하므로, 보안이 필요한 API에는 @Secured("ROLE_USER")
와 같이 명시적으로 역할을 부여해야만 인증되지 않은 사용자의 접근을 막을 수 있습니다.
💡해결
기존에는 토큰이 없는 요청의 경우, 다음 필터 체인을 수행하도록 설정되어 있었습니다. 이 방식에서는 일반적으로 Authentication
객체가 없기 때문에 에러가 발생했겠지만, 메서드 수준의 보안 설정이 활성화되어 있어 인증되지 않은 사용자도 접근할 수 있는 문제가 발생했습니다.
이를 해결하기 위해 swagger, favicon등 토큰의 검증이 필요하지 않은 엔드포인트들에 대해서만 필터체인을 타도록
다음과 같이 shouldNotFilter를 오버라이드 하였습니다.
그리고 authentication 필터에서 로그인, 토큰 재발급과 같이 토큰이 필요하지 않은 엔드포인트 들에 대해서 토큰이 없다면 다음 필터체인으로 넘기고, 이외의 경우에는 토큰을 resolve하는 과정을 거치도록 로직을 수정하였습니다.