티스토리 뷰
JWT 토큰을 사용하는 경우, 보통은 사용자 세션을 갱신하거나 관리하는데 필요한 특별한 단계가 없습니다. 왜냐하면 JWT는 stateless하며, 토큰이 만료되기 전까지는 사용자 인증 정보를 포함하고 있기 때문입니다.
그러나 만약 사용자가 로그아웃하거나 세션을 갱신해야 하는 경우에는 몇 가지 옵션이 있습니다.
1. 토큰 만료시간 짧게 설정하고 갱신 토큰 사용: 액세스 토큰의 만료시간을 짧게 (예: 15분) 설정하고, 별도의 갱신 토큰(refresh token)을 발급하여 사용합니다. 사용자가 로그인을 하면, 둘 다 발급됩니다. 액세스 토큰은 사용자 인증을 위한 짧은 기간 동안 사용하고, 만료되면 갱신 토큰을 사용하여 새 액세스 토큰을 발급받습니다.
2. 토큰 만료 체크 및 갱신: 클라이언트는 액세스 토큰이 만료되기 전에 서버에 요청하여 새 토큰을 받습니다. 이 방법은 토큰 갱신을 자동으로 처리하기 위한 기능을 클라이언트 측에 구현해야 합니다.
3. 로그아웃 시 토큰 삭제: 로그아웃을 할 때는, 클라이언트가 토큰을 삭제합니다. JWT는 상태가 없으므로 서버에서 특정 토큰을 무효화하는 것은 어렵습니다. 그래서 로그아웃 시에는 클라이언트가 토큰을 삭제하고, 필요하다면 갱신 토큰 목록에서도 해당 토큰을 제거합니다.
참고로 JWT를 관리하는 방식에는 많은 변형이 있을 수 있으며, 각각의 방법은 사용자 경험, 보안 요구 사항, 애플리케이션의 복잡성 등 다양한 요소에 따라 선택해야 합니다. 특히 보안 측면에서는 JWT 사용에 많은 주의가 필요합니다. 토큰이 탈취당하면 해당 토큰은 사용자 인증 정보를 포함하고 있기 때문에 악용될 수 있습니다. 따라서 HTTPS와 같은 안전한 채널을 통해 토큰을 전송하는 것이 중요하며, 가능하다면 HttpOnly 쿠키를 사용하여 토큰을 저장하는 것이 좋습니다.
jsonwebtoken 라이브러리를 이용하여 액세스 토큰과 갱신 토큰을 발행하고 갱신하는 Node.js 코드 예제는 다음과 같습니다:
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
// Secret keys (should be stored in environment variables)
const ACCESS_TOKEN_SECRET = 'your-access-token-secret';
const REFRESH_TOKEN_SECRET = 'your-refresh-token-secret';
// In a real-world application, the refresh tokens should be stored in a secure database
let refreshTokens = [];
app.post('/login', (req, res) => {
const { email, password } = req.body;
// Validate and authenticate the user
const user = authenticateUser(email, password);
if (!user) {
return res.status(401).send('Unauthorized');
}
// Create an access token and a refresh token
const accessToken = jwt.sign({ id: user.id }, ACCESS_TOKEN_SECRET, { expiresIn: '15m' });
const refreshToken = jwt.sign({ id: user.id }, REFRESH_TOKEN_SECRET);
// Save the refresh token
refreshTokens.push(refreshToken);
// Return the tokens
res.status(200).send({ accessToken, refreshToken });
});
app.post('/token', (req, res) => {
const { refreshToken } = req.body;
// Ensure the refresh token exists
if (!refreshToken || !refreshTokens.includes(refreshToken)) {
return res.status(403).send('Forbidden');
}
// Verify the refresh token
jwt.verify(refreshToken, REFRESH_TOKEN_SECRET, (err, user) => {
if (err) {
return res.status(403).send('Forbidden');
}
// Create a new access token
const accessToken = jwt.sign({ id: user.id }, ACCESS_TOKEN_SECRET, { expiresIn: '15m' });
// Return the new access token
res.status(200).send({ accessToken });
});
});
app.post('/logout', (req, res) => {
const { refreshToken } = req.body;
// Remove the refresh token
refreshTokens = refreshTokens.filter(token => token !== refreshToken);
// Return success status
res.status(204).send();
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
위 코드에서는 /login 엔드포인트에서 액세스 토큰과 갱신 토큰을 모두 생성하고 클라이언트에 반환하고 있습니다. 액세스 토큰은 15분 후에 만료되며, 갱신 토큰은 만료되지 않습니다.
갱신 토큰은 서버 메모리에 임시적으로 저장됩니다. 실제 어플리케이션에서는 이러한 토큰을 데이터베이스 등 안전한 장소에 보관해야 합니다.
/token 엔드포인트는 갱신 토큰을 받아 새로운 액세스 토큰을 생성하고 반환하는 역할을 합니다.
/logout 엔드포인트는 갱신 토큰을 받아 서버의 갱신 토큰 목록에서 해당 토큰을 제거하며, 이를 통해 로그아웃을 구현합니다.
참고로, 위 코드는 간단한 예시일 뿐, 실제 프로덕션 수준의 코드에서는 보안과 에러 처리 등에 더 많은 주의를 기울여야 합니다. 특히, ACCESS_TOKEN_SECRET과 REFRESH_TOKEN_SECRET는 실제 코드에서 직접적으로 노출되어서는 안 되며, 대신 환경 변수 등을 통해 안전하게 관리되어야 합니다.
'개발' 카테고리의 다른 글
[개발]JWT 갱신 토큰 관리 방법(3)-DB 사용 (0) | 2023.07.03 |
---|---|
[개발]JWT 갱신 토큰 관리 방법 (2) - 로컬스토리지/쿠키 사용 (0) | 2023.07.03 |
[개발]JWT 갱신 토큰 관리 방법(1) (0) | 2023.07.03 |
[개발]JWT(Json Web Token)을 이용한 인증(feat. NodeJS) (0) | 2023.07.03 |
[개발] 로그인 API 개발 방식 (0) | 2023.07.03 |