http → http로 서로 다른 도메인에서 쿠키를 심었을 경우
sameSite 기본값(Lax)일 경우
- 쿠키가 저장은 되는데 새로고침하면 증발함
- 쿠키 보내는 것 안됨
- 크롬에서 크로스 사이트를 사용 가능하도록 sameSite를 None 옵션으로 설정해주라고 메세지를 내뱉음. (서버에서 설정해줘야함)
client 코드 - svelte (주소 : localhost:5173)
<script>
import axios from 'axios';
const API = axios.create({
baseURL: `http://localhost:8080`,
});
const getCookie = async () => {
// 의미없는 데이터임
const data = {
id: 'id',
pw: 'pw',
};
// withCredentials 옵션은 단어의 의미에서 알 수 있듯이, 서로 다른 도메인(크로스 도메인)에 요청을 보낼 때 요청에 credential 정보를 담아서 보낼 지를 결정하는 항목입니다.
// 여기서, credential 정보가 포함되어 있는 요청은 아래 두 가지 경우를 의미합니다.
// 1. 쿠키를 첨부해서 보내는 요청
// 2. 헤더에 Authorization 항목이 있는 요청
const config = {
withCredentials: true,
};
await API.post('/login', data, config);
};
const postCookie = async () => {
const data = {
id: 'haha',
pw: 'bb',
};
const config = {
withCredentials: true,
};
await API.post('/cookie', data, config);
};
</script>
<main>
<button on:click={getCookie}>쿠키 심기</button>
<button on:click={postCookie}>쿠키 보내기</button>
</main>
server 코드 - node express (주소 : 172.~~~~~:8080)
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const PORT = 8080;
const app = express();
app.use(cookieParser());
app.use(express.json());
app.use(
cors({
origin: true, // 클라이언트의 Origin
credentials: true, // 요청에 인증 정보를 포함할 것임을 허용
})
);
app.get('/', function (req, res) {
res.send('ㅎㅇㅎㅇ');
});
app.post('/login', (req, res) => {
console.log('요청옴');
// 가정: 로그인이 성공했을 때 사용자 정보를 생성하고 쿠키에 저장한다.
const userInfo = { username: 'exampleUser', id: 123456 };
// 쿠키 만료 시간 설정 (1시간)
const oneHour = 60 * 60 * 1000; // milliseconds
const expiryDate = new Date(Date.now() + oneHour);
// 쿠키 생성
res.cookie('userInfo', userInfo, {
httpOnly: true, // HTTP Only 설정
expires: expiryDate, // 만료 시간 설정
});
res.send('쿠키 심기');
});
app.post('/cookie', (req, res) => {
console.log(req.cookies['userInfo']);
res.send('쿠키 가져오기');
});
// 서버가 실행할 PORT를 지정하고, 실행했을 때 콘솔로그를 찍음
app.listen(PORT, function () {
console.log(`Listening on port ${PORT}! <http://localhost>:${PORT}`);
});
쿠키를 심고 쿠키를 보내기 했을 경우 서버에서 undefined로 뜸
sameSite를 none 으로 설정할 경우
- sameSite none 을 적용 할 경우 secure: true 도 설정해줘야 함
- 마찬가지로 쿠키가 저장은 되는데 새로고침하면 증발함
- 쿠키 보내는 것 안됨
서드 파티 쿠키 제한 확대
https://developers.google.com/privacy-sandbox/3pcd?hl=ko#report-issues
client 코드 (주소 : localhost:5173) 위와 동일
<script>
import axios from 'axios';
const API = axios.create({
baseURL: `http://localhost:8080`,
});
const getCookie = async () => {
// 의미없는 데이터임
const data = {
id: 'id',
pw: 'pw',
};
// withCredentials 옵션은 단어의 의미에서 알 수 있듯이, 서로 다른 도메인(크로스 도메인)에 요청을 보낼 때 요청에 credential 정보를 담아서 보낼 지를 결정하는 항목입니다.
// 여기서, credential 정보가 포함되어 있는 요청은 아래 두 가지 경우를 의미합니다.
// 1. 쿠키를 첨부해서 보내는 요청
// 2. 헤더에 Authorization 항목이 있는 요청
const config = {
withCredentials: true,
};
await API.post('/login', data, config);
};
const postCookie = async () => {
const data = {
id: 'haha',
pw: 'bb',
};
const config = {
withCredentials: true,
};
await API.post('/cookie', data, config);
};
</script>
<main>
<button on:click={getCookie}>쿠키 심기</button>
<button on:click={postCookie}>쿠키 보내기</button>
</main>
server 코드 (주소 : 172.~~~~~:8080)
const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const PORT = 8080;
const app = express();
app.use(cookieParser());
app.use(express.json());
app.use(
cors({
origin: true, // 클라이언트의 Origin
credentials: true, // 요청에 인증 정보를 포함할 것임을 허용
})
);
app.get('/', function (req, res) {
res.send('ㅎㅇㅎㅇ');
});
app.post('/login', (req, res) => {
console.log('요청옴');
// 가정: 로그인이 성공했을 때 사용자 정보를 생성하고 쿠키에 저장한다.
const userInfo = { username: 'exampleUser', id: 123456 };
// 쿠키 만료 시간 설정 (1시간)
const oneHour = 60 * 60 * 1000; // milliseconds
const expiryDate = new Date(Date.now() + oneHour);
// 쿠키 생성
res.cookie('userInfo', userInfo, {
httpOnly: true, // HTTP Only 설정
expires: expiryDate, // 만료 시간 설정
sameSite: 'none',
secure: true, // Secure 설정
});
res.send('쿠키 심기');
});
app.post('/cookie', (req, res) => {
console.log("req.cookies['userInfo'] = ", req.cookies['userInfo']);
res.send('쿠키 가져오기');
});
// 서버가 실행할 PORT를 지정하고, 실행했을 때 콘솔로그를 찍음
app.listen(PORT, function () {
console.log(`Listening on port ${PORT}! <http://localhost>:${PORT}`);
});
sameSite 옵션이 뭘까?
쿠키의 속성 중 하나로, 보안 및 개인 정보 보호 측면에서 중요한 역할을 합니다. SameSite 속성은 웹 브라우저가 쿠키를 어떻게 처리해야 하는지를 지정합니다.
즉, 쿠키에는 이 쿠키가 어떤 도메인에서만 사용할 수 있는지 설정할 수 있는 옵션
SameSite은 크게 세 가지 값으로 설정할 수 있습니다. (기본값은 Lax)
- Strict: 이 옵션을 사용하면 브라우저는 SameSite를 엄격하게 적용하여, 쿠키가 해당 사이트의 페이지로만 전송될 수 있도록 합니다. 즉, 외부 사이트로의 요청에서는 쿠키가 전송되지 않습니다.
- Lax: 이 옵션은 엄격한 제약을 완화시키는 데 사용됩니다. 외부 도메인으로의 GET 요청에 대해서는 쿠키를 전송하지 않지만, POST 요청이나 외부 도메인에서 자동으로 시작되는 요청(ex: 링크를 클릭하여 이동하는 경우)에는 쿠키가 전송됩니다.
- None: 이 옵션은 SameSite를 사용하지 않음을 나타냅니다. 따라서 쿠키는 모든 요청에 대해 전송됩니다. 이 옵션을 사용할 때는 Secure 속성이 함께 설정되어야 하며, HTTPS 프로토콜을 사용하는 환경에서만 적용됩니다.
SameSite 속성은 주로 CSRF (Cross-Site Request Forgery) 공격과 관련이 있습니다. 이를 통해 외부 사이트에서 해당 사이트로 요청을 보내는 공격을 막기 위해 SameSite 속성을 설정할 수 있습니다. 또한 SameSite는 쿠키를 통한 사용자 추적을 제한하고 개인 정보 보호를 강화하는 데 도움이 됩니다.
크롬의 SameSite 기본값 변화(None → Lax)
원래 SameSite를 명시하지 않은 쿠키는 None으로 동작했지만, 2020년 2월 4일 크롬 80 버전이 배포되면서 SameSite의 기본값이 Lax로 변경되었다. 이에 따라 위에서 언급했던 것처럼 예외사항에 포함되지 않으면 다른 도메인 간의 요청에서 쿠키를 담아주지 않는다.
이를 해결하기 위해선 SameSite 속성을 None으로 변경하고 쿠키를 secure 쿠키로 만들어 주면 된다.
(SameSite를 None으로 하려면 무조건 secure를 true로 설정해야만 정상적으로 전송된다.)
- secure: 쿠키가 SSL이나 HTTPS 연결을 통해서만 반횐될지 여부를 명시하는 값
- SameSite: 쿠키가 같은 도메인에서만 접근할 수 있어야 하는지 여부를 결정하는 값
결론
크로스 도메인 쿠키를 제대로 사용하려면 HTTPS 를 적용하고 sameSite 설정을 none로 바꿔주자 !!