로컬에서 프로젝트를 진행하다가 리액트와 Node.js를 각각 다른 도메인에 호스팅하고 진행을 하게되었다. 그 후에 리액트에서 Node.js로 API를 요청하면서 쿠키가 잘 전달되는지를 확인해보니 CORS 이슈때문에 제대로 작동하지않았다.
Cross Origin Resource Sharing 의 약자로 서로 다른 도메인에서 리소스를 요청하게 되면 보안상의 이유로 교차 출저 HTTP 요청을 제한하는것이다.
처음 로컬에서 진행할 때에도 CORS 문제가 발생했었다.
리액트의 주소는 http://localhost:3000 을 사용중이고
Node.js의 주소는 http://localhost:4000 을 사용했기 때문에 CORS로 인해 요청이 되지않았다.
해결 방법으로는 http-proxy-middleware 을 사용하여 src/setupProxy.js 파일을
만들어줬다.
// src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'localhost:4000', // 백앤드 서버
changeOrigin: true,
})
);
};
위와같이 proxy 설정을 추가해준 뒤 axios 로 API를 요청하면
http://localhost:3000/api/resource/1 의 요청이
http://localhost:4000/api/resource/1 로 요청이 가게된다.
(이전 리액트 버전에서는 package.json 에 proxy 를 추가하게 되면
CORS를 해결할수 있었던 모양이다.)
리액트는 Firebase 을 사용하였고 Node.js는 Heroku 를 사용하여 호스팅을 하였다.
로컬에서 진행할때 클라이언트 쪽에서 설정을 했다면 이번엔 서버쪽에서 설정을 해주었다.
// src/index.js
const Koa = require('koa');
const cors = require('@koa/cors');
const app = new Koa();
// CORS 옵션
let corsOptions = {
origin: process.env.CLIENT_HOST,
credentials: true,
}
// CORS 허용
app.proxy = true; // true 일때 proxy 헤더들을 신뢰함
app.use(cors(corsOptions));
... (생략)
const port = process.env.PORT || 4000;
app.listen(port, () => {
console.log('bgs server is listening to port ' + port);
});
@koa/cors을 사용하여 간단히 설정하였다.
이외에도 allowedHeaders 나 methods 설정을 추가할 수 있다.
20년 2월 4일 구글 크롬 80버전이 릴리즈 되었는데 이때부터 쿠키정책이 바뀌어서
Cookie의 SameSite 속성의 기본값이 'None' 에서 'Lax'로 변경이 되었다.
SameSite 속성은 도서 다른 도메인간의 쿠키 전송에 대한 보안을 설정한다.
따라서 SameSite를 설정하기 위해서 쿠키를 설정할때마다 sameSite 속성을 추가하였다.
// JWT 토큰 쿠키 설정
ctx.cookies.set('access_token', freshToken, {
maxAge: 1000 * 60 * 60 * 24 * 7, // 7days
httpOnly: true,
sameSite: 'none',
secure: true
});
여기서 sameSite: 'none' 을 사용할 때는 꼭 secure: true 속성도 같이 붙여줘야 한다.
해당 속성을 추가하면 쿠키는 HTTPS 프로토콜에서만 전송이 가능해진다.
만약 secure 속성이 없다면 브라우저에서 경고메세지를 띄우게된다.
참고자료
1. https://hoons-up.tistory.com/26
2. https://ifuwanna.tistory.com/223