반응형
JWT 인증과 인가 흐름
1. Axios 인터셉터를 활용한 자동 토큰 갱신 예시
Axios 인터셉터 설정
- Axios를 사용하여 Access Token의 만료를 감지하고, Refresh Token을 사용하여 새로운 Access Token을 발급받는 방식으로 자동화할 수 있음.
import axios from 'axios';
// Axios 인스턴스 생성
const api = axios.create({
baseURL: 'https://example.com/api',
timeout: 10000,
headers: { 'Content-Type': 'application/json' },
});
// 요청 인터셉터 (요청이 보내지기 전에 처리)
api.interceptors.request.use(
config => {
// localStorage에서 Access Token을 가져와 Authorization 헤더에 넣음
const accessToken = localStorage.getItem('accessToken');
if (accessToken) {
config.headers['Authorization'] = `Bearer ${accessToken}`;
}
return config;
},
error => Promise.reject(error)
);
// 응답 인터셉터 (응답이 돌아왔을 때 처리)
api.interceptors.response.use(
response => {
// 정상적인 응답 처리
return response;
},
async error => {
// 401 에러 (Access Token 만료된 경우) 처리
if (error.response && error.response.status === 401) {
try {
// Refresh Token을 사용하여 새로운 Access Token 요청
const refreshToken = localStorage.getItem('refreshToken');
const response = await axios.post('/api/refresh-token', { refreshToken });
// 새로운 Access Token을 localStorage에 저장
const { accessToken } = response.data;
localStorage.setItem('accessToken', accessToken);
// 원래의 요청을 새로운 Access Token으로 재요청
const originalRequest = error.config;
originalRequest.headers['Authorization'] = `Bearer ${accessToken}`;
return api(originalRequest); // 재요청
} catch (refreshError) {
// Refresh Token이 만료되었거나 에러가 발생한 경우, 로그아웃 처리
console.error('Refresh Token도 만료되었거나 에러가 발생했습니다.');
// 예: 로그아웃 처리
window.location.href = '/login';
}
}
// 401 외의 오류는 그대로 처리
return Promise.reject(error);
}
);
export default api;
작동 원리
- 요청 인터셉터: 모든 API 요청 전에 Access Token을 Authorization 헤더에 추가.
- 응답 인터셉터: 응답에서 401 Unauthorized 에러가 발생하면, Refresh Token을 사용하여 새로운 Access Token을 요청하고, 이를 사용해 원래 요청을 재전송.
- 자동 토큰 갱신: Access Token이 만료되면, Refresh Token을 통해 새로운 토큰을 발급받아 자동으로 재요청함.
2. Access Token과 Refresh Token의 정의 및 저장 방법
Access Token
정의:
- 인증된 사용자의 권한을 증명하는 짧은 유효 기간을 가진 JWT 토큰.
- 서버에서 생성하고, 클라이언트는 이를 사용하여 보호된 리소스에 접근할 수 있음.
저장 방법:
- 보통 localStorage 또는 쿠키에 저장됨.
장점:
- 서버에 요청 시 빠르게 인증을 처리할 수 있음.
- 클라이언트에서 쉽게 헤더에 추가하여 요청할 수 있음.
단점:
- 유효 기간이 짧아, 만료 후 갱신이 필요함.
- localStorage에 저장 시 XSS 공격에 취약할 수 있음.
- 쿠키에 저장 시 CSRF 공격에 취약할 수 있음.
Refresh Token
정의:
- Access Token의 만료 후, 새로운 Access Token을 발급받기 위한 긴 유효 기간을 가진 JWT 또는 임의의 문자열.
- 일반적으로 서버에서만 저장되며, 클라이언트는 이를 통해 Access Token을 갱신할 수 있음.
저장 방법:
- 보통 httpOnly 쿠키에 저장하여 XSS 공격으로부터 보호.
장점:
- 긴 유효 기간을 가지므로 Access Token의 만료 시 계속해서 새로운 Access Token을 발급받을 수 있음.
- httpOnly 쿠키에 저장하면 XSS 공격에 강한 보안을 제공함.
단점:
- Refresh Token의 탈취가 발생하면 액세스 권한을 부여받은 상태로 새로운 Access Token을 발급받을 수 있기 때문에 보안상 위험이 있음.
- 만약 로그아웃 처리가 제대로 되어 있지 않으면, Refresh Token이 계속해서 사용될 수 있음.
3. Access Token과 Refresh Token의 저장 방법 비교
저장 방법 | 장점 | 단점 |
---|---|---|
localStorage | - 쉽게 접근 가능하고, 다른 요청에서 사용하기 용이함. | - XSS 공격에 취약함. |
쿠키 (일반 쿠키) | - CSRF 공격에 취약할 수 있음. | - 쿠키의 크기에 제한이 있어, 저장할 수 있는 정보에 제한이 있음. |
쿠키 (httpOnly) | - XSS 공격에 강함. | - CSRF 공격에 취약할 수 있음. |
세션 저장소 | - 세션이 끝날 때 토큰이 자동으로 삭제됨. | - 페이지 새로 고침 시 토큰이 삭제됨. |
추천
- Access Token은 localStorage에 저장하고, Refresh Token은 httpOnly 쿠키에 저장하는 것이 보안성과 편리성을 고려한 좋은 방법임.
- localStorage에 Access Token을 저장하면 서버 요청 시 빠르게 Authorization 헤더에 추가할 수 있음.
- httpOnly 쿠키에 Refresh Token을 저장하면 XSS 공격으로부터 보호받을 수 있음.
4. 요약
- 프런트엔드는 Access Token을 Authorization 헤더에 포함하여 API 요청을 보냄.
- 서버는 Access Token을 검증하여 유효하면 요청을 처리하고, 유효하지 않으면 401 Unauthorized를 반환함.
- 401 오류가 발생하면, 프런트엔드는 Refresh Token을 사용하여 새로운 Access Token을 발급받고, 이를 사용해 원래의 요청을 다시 보냄.
- Access Token은 짧은 유효 기간을 가지며 localStorage 또는 쿠키에 저장됨.
- Refresh Token은 긴 유효 기간을 가지며, 보통 httpOnly 쿠키에 저장됨.
반응형