maplestory/backend/routes/auth.js
caadiq 4bbb496724 초기 프로젝트 설정
- React + Vite + Tailwind 프론트엔드
- Express + Sequelize + MariaDB 백엔드
- 넥슨 OAuth 2.0 인증 (캐릭터 목록 조회)
- 주간 보스 결정석 수익 계산기 UI (리스트형)
- Docker Compose + Caddy 리버스 프록시 설정
- 보스/난이도 이미지 에셋 포함

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 18:55:06 +09:00

66 lines
1.9 KiB
JavaScript

import { Router } from 'express';
import crypto from 'crypto';
import { exchangeToken, getUserInfo, refreshToken } from '../services/nexon.js';
import { User } from '../models/index.js';
const router = Router();
router.get('/login', (req, res) => {
const state = crypto.randomBytes(16).toString('hex');
req.session.oauthState = state;
const params = new URLSearchParams({
response_type: 'code',
client_id: process.env.NEXON_CLIENT_ID,
redirect_uri: process.env.NEXON_REDIRECT_URI,
scope: 'maplestory.characterlist',
state,
});
res.redirect(`https://openid.nexon.com/oauth2/authorize?${params}`);
});
router.get('/callback', async (req, res) => {
const { code, state } = req.query;
if (!code || state !== req.session.oauthState) {
return res.status(400).json({ error: '잘못된 요청입니다' });
}
delete req.session.oauthState;
try {
const tokens = await exchangeToken(code);
const userInfo = await getUserInfo(tokens.access_token);
const [user] = await User.findOrCreate({
where: { nexon_uid: userInfo.uid },
});
req.session.userId = user.id;
req.session.accessToken = tokens.access_token;
req.session.refreshToken = tokens.refresh_token;
req.session.tokenExpiresAt = Date.now() + tokens.expires_in * 1000;
res.redirect('/');
} catch (err) {
console.error('OAuth 콜백 오류:', err.message);
res.status(500).json({ error: '로그인 처리 중 오류가 발생했습니다' });
}
});
router.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) return res.status(500).json({ error: '로그아웃 실패' });
res.clearCookie('connect.sid');
res.json({ success: true });
});
});
router.get('/me', (req, res) => {
if (!req.session?.userId) {
return res.json({ authenticated: false });
}
res.json({ authenticated: true, userId: req.session.userId });
});
export default router;