HTTP 인증 방식 완벽 가이드: Basic, Bearer, OAuth까지
1. Basic 인증
가장 기본적인 인증 방식으로, 사용자 이름과 비밀번호를 Base64로 인코딩하여 전송합니다.
구현 예제
// 클라이언트 측
const username = 'user';
const password = 'pass';
const basicAuth = 'Basic ' + btoa(username + ':' + password);
fetch('https://api.example.com', {
headers: {
'Authorization': basicAuth
}
});
// 서버 측 (Express)
const auth = require('basic-auth');
app.use((req, res, next) => {
const credentials = auth(req);
if (!credentials || credentials.name !== 'user' || credentials.pass !== 'pass') {
res.setHeader('WWW-Authenticate', 'Basic');
return res.status(401).send('인증 필요');
}
next();
});
장단점
- 장점: 구현이 간단
- 단점: 보안성이 낮음 (Base64는 쉽게 디코딩 가능)
2. Bearer 토큰 인증
토큰 기반 인증의 일종으로, JWT를 많이 사용합니다.
JWT 구조
헤더.페이로드.서명
JWT 구현 예제
const jwt = require('jsonwebtoken');
// 토큰 생성
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 사용자 검증 후
const token = jwt.sign(
{ id: user.id, username: user.username },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
res.json({ token });
});
// 토큰 검증 미들웨어
const verifyToken = (req, res, next) => {
const bearerHeader = req.headers['authorization'];
if (!bearerHeader) {
return res.status(401).json({ message: '토큰이 필요합니다' });
}
const token = bearerHeader.split(' ')[1];
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(401).json({ message: '유효하지 않은 토큰입니다' });
}
};
3. OAuth 2.0
외부 서비스의 인증을 사용하는 방식입니다.
구현 예제 (Google OAuth)
const passport = require('passport');
const GoogleStrategy = require('passport-google-oauth20').Strategy;
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: "http://localhost:3000/auth/google/callback"
},
function(accessToken, refreshToken, profile, cb) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return cb(err, user);
});
}));
// 라우트 설정
app.get('/auth/google',
passport.authenticate('google', { scope: ['profile', 'email'] })
);
app.get('/auth/google/callback',
passport.authenticate('google', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
}
);
4. 리프레시 토큰
액세스 토큰의 보안을 강화하기 위한 방식입니다.
구현 예제
// 토큰 발급
app.post('/login', async (req, res) => {
const { username, password } = req.body;
// 사용자 검증 후
const accessToken = jwt.sign(
{ id: user.id },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ id: user.id },
process.env.REFRESH_SECRET,
{ expiresIn: '7d' }
);
// 리프레시 토큰 저장
await User.updateOne(
{ _id: user.id },
{ refreshToken }
);
res.json({ accessToken, refreshToken });
});
// 토큰 갱신
app.post('/refresh', async (req, res) => {
const { refreshToken } = req.body;
try {
const decoded = jwt.verify(refreshToken, process.env.REFRESH_SECRET);
const user = await User.findOne({
_id: decoded.id,
refreshToken
});
if (!user) {
throw new Error('Invalid refresh token');
}
const accessToken = jwt.sign(
{ id: user.id },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
res.json({ accessToken });
} catch (err) {
res.status(401).json({ message: '토큰 갱신 실패' });
}
});
5. API Key 인증
서비스 간 인증에 주로 사용됩니다.
구현 예제
const apiKeyMiddleware = async (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (!apiKey) {
return res.status(401).json({ message: 'API key required' });
}
try {
const client = await ApiClient.findOne({ apiKey });
if (!client) {
throw new Error('Invalid API key');
}
req.client = client;
next();
} catch (err) {
res.status(401).json({ message: '유효하지 않은 API key' });
}
};
6. 보안 고려사항
HTTPS 사용
const express = require('express');
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('private.key'),
cert: fs.readFileSync('certificate.crt')
};
https.createServer(options, app).listen(443);
XSS 방지
app.use(helmet()); // 보안 헤더 설정
// JWT 토큰을 HttpOnly 쿠키로 저장
res.cookie('token', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
CSRF 방지
const csrf = require('csurf');
app.use(csrf({ cookie: true }));
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
'개발&프로그래밍' 카테고리의 다른 글
[HTTP] HTTP 주요 헤더와 활용법 (0) | 2025.02.21 |
---|---|
[HTTP] 웹 브라우저 동작 원리 : URL 입력부터 화면 표시까지 (0) | 2025.02.21 |
[HTTP] URL 구조 파헤치기 (0) | 2025.02.20 |
[HTTP] 쿠키와 세션 완벽 가이드: 웹 인증의 기본 (0) | 2025.02.20 |
[HTTP] HTTP 메서드 완벽 가이드: RESTful API의 기초 (0) | 2025.02.19 |
댓글