개인 프로젝트를 진행하다가 로그인을 구현 중 겪은 어려움 및 항상 까먹었던 로그인에 대해 기억하기 위해 작성합니다.
토큰은 크게 3가지로 이루어짐
=> 둘 다 스크립트를 통해 접근할 수 있으므로 XSS 공격에 취약. 따라서 중요한 정보는 서버 측에서 관리하는 것이 편함.
XSS(Cross Site Scripting) 은 공격자가 웹 사이트에 악의적인 스크립트를 주입하는 보안 취약점.
사용자의 브라우저가 악성 스크립트를 실행하게 되면, 공격자는 사용자의 세션 토큰이나 쿠키에 접근하거나, 사용자를 가장하여 행동을 취할 수 있음.
만약 토큰을 로컬스토리지에 저장하면 이러한 XSS에 특히 취약해짐.
로컬 스토리지는 JavaScript를 통해 쉽게 접근할 수 있기 때문에, XSS 공격을 통해 악성 스크립트가 주입되면 이 스크립트는 로컬 스토리지에 저장된 토큰을 읽고 이를 공격자에게 전송할 수 있음.
=> 이를 방지하기 위해 HTTP 쿠키에 HttpOnly
플래그를 설정하여 JavaScript가 쿠키에 접근하지 못하도록 하는 것이 권장됨.
CSRF(Cross-site Request Forgery) 는 공격자가 사용자가 이미 인증된 웹사이트에 대해 악의적인 요청을 보낼 수 있게 하는 공격 방법.
사용자가 로그인한 상태에서 악성 웹사이트를 방문하면, 이 웹사이트는 사용자가 의도하지 않은 요청을 실제 사이트에 대해 자동으로 수행할 수 있음.
쿠키에 자동으로 토큰이 포함되기 때문에 CSRF 공격에 취약함. 공격자는 사용자의 브라우저를 이용해 쿠키를 사용하여 인증된 사용자처럼 요청을 보낼 수 있음.
=> 이를 방지하기 위해 SameSite
쿠키 속성을 사용하거나 CSRF 토큰
과 같은 추가적인 검증 메커니즘을 사용
Next와 Nest로 로그인 구현 중 일단 토큰을 발급 후 로컬스토리지에 간단하게 저장해서 진행하려고했는데, 서버 컴포넌트는 로컬스토리지 접근이 되지 않기때문에 토큰을 쿠키에 저장 시도.
분명 postman에서 실행될때는 설정이 잘 되었지만 브라우저 탭에서 확인을 해보면 쿠키가 저장되어 있지 않음.
None : 동일 사이트, 크로스 사이트 모두 전송 가능. 이로인해 CSRF 공격에 취약.
SameSite를 None으로 한다면 Https 연결이 필요한 Secure 속성을 함께 넣어줘야함.
Strict : 크로스 사이트 요청에는 항상 전송되지 않음. 즉, SameSite에서만 쿠키의 전송을 허용
Lax : 기본적으로 크로스 사이트 차단. 하지만 예외사항이 있어 크로스사이트임에도 일부 요청 방식으로는 쿠키 전송 가능.
Chrome80 부터 SameSite 기본값이 None => Lax로 변경되었음.
현재 프론트는 localhost:3000 서버는 localhost:4000 인 상황.
따라서 쿠키를 설정해주기 위해서는 서버와 클라이언트에 둘 다 Credential
부분을 true
로 변경해줘야함!
credentials 속성을 true로 설정해준다면, nest는 자동으로 응답 헤더에
Access-Control-Allow-Credentials: true
를 포함시킴.
이 설정은 프론트가 다른 출처에서 온 요청에 대해 쿠키나 인증 헤더를 포함할 수 있게 해줌.
프론트의 fetch 에서도 credentials : "include"
적용.
credentials
속성은 브라우저의 fetch API나 XMLHTTPRequest 에서 쿠키와 인증 관련 헤더를 요청과 함께 보낼지 결정하는 옵션.
Access-Control-Allow-Credentials : true
헤더를 설정해줘야 함. 이는 다른 출처(ex: 다른 도메인, 서브도메인, 포트) 의 요청에서도 사용자의 인증 상태를 유지하는 데 필요.프론트엔드와 백엔드가 다른 포트나 도메인에서 실행될 때 CORS 정책에 의해 쿠키가 기본적으로 요청과 함께 전송되지 않음.
따라서 프론트엔드에서 credentials : include
를 설정하고
백엔드에서 Access-Control-Allow-Credentials : true
를 설정.
쿠키 저장 성공!