프로젝트를 하면서 파이어베이스에서 토큰을 받아 소셜 로그인 과정을 좀 더 간단하게 하기 위해 연동을 시켰다.
파이어베이스는 사용자 인증 및 권한 부여를 관리하기 위한 클라우드 기반 플랫폼으로, 스프링 시큐리티와 함께 사용하면 스프링 애플리케이션에서 파이어베이스의 인증 및 권한 기능을 활용할 수 있다.
연동을 시킨후에, 포스트맨에서 간단한 기능을 테스트 해보았는데 Invalid Token도 뜨지 않고 401에러만 났다.
처음엔 원인을 알 수 없었으나 Get요청은 되지만 그 외의 요청들은 401에러가 떴다.
문제의 원인은 스프링 시큐리티 였다.
스프링 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크
인증(Authentication) ⇒ 로그인
인가(Authorization) ⇒ 로그인으로 인증 한 후 활동 시도할 때
서버가 로그인 되어있음을 알고 허가 해주는 것
접근 주체 (Principal) | 보호된 대상에 접근하는 유저 |
---|---|
비밀번호 (Credential) | 대상에 접근하는 유저의 비밀번호 |
Spring Security 에서는 이러한 인증, 인가를 위해 Principal 을 아이디로 Credential 을 비밀번호로 사용하는 Credential 기반의 인증 방식 (인증이 먼저 이루어지고 인가를 해주는 방식) 을 사용한다.
CSRF protection은 spring security에서 default로 설정된다. 즉, protection을 통해 GET요청을 제외한 상태를 변화시킬 수 있는 POST, PUT, DELETE 요청으로부터 보호한다.
csrf protection을 적용하였을 때, html에서 다음과 같은 csrf 토큰이 포함되어야 요청을 받아들이게 됨으로써, 위조 요청을 방지하게 됩니다.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
CSRF 공격
Cross Site Request Forgery 공격
보통 사용자는 로그아웃 버튼을 잘 누르지 않는다.
인터넷 뱅킹이나 쇼핑몰에 로그인한 후, 로그아웃 메뉴를 누르지 않고,
악성 코드가 있는 사이트에 들어가면 위험하다.
아직 로그인 상태인 쇼핑몰 계정에 악성 코드가 접근할 수 있기 때문이다.
이것을 CSRF 공격이라고 한다.
CSRF 공격을 막는 기능이 spring security에 잘 구현되어 있다.
CSRF를 비활성화 해주었더니 요청을 잘 처리해주었다.
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .build(); }
spring security documentation에 non-browser clients(웹 브라우저가 아닌 클라이언트) 만을 위한 서비스라면 csrf를 disable 하여도 좋다고 한다.
이 이유는 rest api를 이용한 서버라면, session 기반 인증과는 다르게 stateless하기 때문에 서버에 인증정보를 보관하지 않는다. rest api에서 client는 권한이 필요한 요청을 하기 위해서는 요청에 필요한 인증 정보를(OAuth2, jwt토큰 등)을 포함시켜야 한다. 따라서 서버에 인증정보를 저장하지 않기 때문에 굳이 불필요한 csrf 코드들을 작성할 필요가 없다.