- Updated CSRF middleware to enhance cookie value decoding. - Reformatted OAuth proxy token store initialization for better clarity. - Adjusted Challonge proxy router for consistent line breaks and readability. - Enhanced OAuth router error handling and response formatting. - Improved session router for better readability and consistency in fetching provider records. - Refactored OAuth token store to improve key derivation logging. - Cleaned up cookie options utility for better readability. - Enhanced Challonge client credentials composable for consistent API calls. - Streamlined OAuth composable for improved logging. - Refactored main.js for better readability in session initialization. - Improved Challonge v2.1 service error handling for better clarity. - Cleaned up API client utility for improved readability. - Enhanced ApiKeyManager.vue for better text formatting. - Refactored ChallongeTest.vue for improved readability in composable usage.
131 lines
3.5 KiB
JavaScript
131 lines
3.5 KiB
JavaScript
/**
|
|
* OAuth Proxy Server for Challonge API
|
|
*
|
|
* This server handles OAuth token exchange and refresh for the Challonge API.
|
|
* It keeps client_secret secure by running on the backend.
|
|
*
|
|
* Usage:
|
|
* Development: node server/oauth-proxy.js
|
|
* Production: Deploy with Docker (see docker-compose.production.yml)
|
|
*/
|
|
|
|
import 'dotenv/config';
|
|
import express from 'express';
|
|
import cors from 'cors';
|
|
import cookieParser from 'cookie-parser';
|
|
import gamemasterRouter from './gamemaster-api.js';
|
|
import { createAuthRouter } from './routes/auth.js';
|
|
import { createOAuthRouter } from './routes/oauth.js';
|
|
import { createSessionRouter } from './routes/session.js';
|
|
import { createChallongeProxyRouter } from './routes/challonge.js';
|
|
import { createDiscordRouter } from './routes/discord.js';
|
|
import { validateOrExit, getConfig } from './utils/env-validator.js';
|
|
import logger, { requestLogger, errorLogger } from './utils/logger.js';
|
|
import {
|
|
setupGracefulShutdown,
|
|
createHealthCheckMiddleware
|
|
} from './utils/graceful-shutdown.js';
|
|
import { sidMiddleware } from './middleware/sid.js';
|
|
import { csrfMiddleware } from './middleware/csrf.js';
|
|
import { createOAuthTokenStore } from './services/oauth-token-store.js';
|
|
|
|
// Validate environment variables
|
|
validateOrExit();
|
|
|
|
// Get validated configuration
|
|
const config = getConfig();
|
|
|
|
const app = express();
|
|
|
|
// Behind nginx reverse proxy in production
|
|
app.set('trust proxy', 1);
|
|
|
|
// Middleware
|
|
app.use(
|
|
cors({
|
|
origin: config.cors.origin,
|
|
credentials: true
|
|
})
|
|
);
|
|
app.use(cookieParser());
|
|
app.use(express.json());
|
|
app.use(requestLogger);
|
|
|
|
// Per-session identity (httpOnly signed SID cookie)
|
|
app.use(
|
|
sidMiddleware({
|
|
sessionSecret: config.session.secret,
|
|
config
|
|
})
|
|
);
|
|
|
|
// Encrypted per-session provider token store
|
|
const tokenStore = createOAuthTokenStore({
|
|
sessionSecret: config.session.secret
|
|
});
|
|
|
|
// Mount API routes (nginx strips /api/ prefix before forwarding)
|
|
app.use('/gamemaster', gamemasterRouter);
|
|
app.use(
|
|
'/auth',
|
|
createAuthRouter({
|
|
secret: config.secret,
|
|
adminPassword: config.adminPassword
|
|
})
|
|
);
|
|
|
|
// Session + CSRF helpers
|
|
app.use('/session', createSessionRouter({ config, tokenStore }));
|
|
|
|
// Provider OAuth (server-owned tokens; browser never receives access/refresh tokens)
|
|
app.use(
|
|
'/oauth',
|
|
csrfMiddleware({
|
|
requireOriginCheck: config.isProduction,
|
|
allowedOrigin: config.cors.origin
|
|
})
|
|
);
|
|
app.use('/oauth', createOAuthRouter({ config, tokenStore }));
|
|
|
|
// Provider API proxies (no split brain)
|
|
app.use('/challonge', createChallongeProxyRouter({ config, tokenStore }));
|
|
app.use('/discord', createDiscordRouter({ tokenStore }));
|
|
|
|
/**
|
|
* Health check endpoint (with graceful shutdown support)
|
|
* GET /health
|
|
*/
|
|
app.get('/health', createHealthCheckMiddleware());
|
|
|
|
// Error logging middleware (must be after routes)
|
|
app.use(errorLogger);
|
|
|
|
// Start server
|
|
const server = app.listen(config.port, () => {
|
|
logger.info('🔐 OAuth Proxy Server started', {
|
|
port: config.port,
|
|
nodeEnv: config.nodeEnv,
|
|
challongeConfigured: config.challonge.configured
|
|
});
|
|
|
|
if (!config.challonge.configured) {
|
|
logger.warn(
|
|
'⚠️ Challonge OAuth not configured - OAuth endpoints disabled'
|
|
);
|
|
logger.warn(
|
|
' Set CHALLONGE_CLIENT_ID and CHALLONGE_CLIENT_SECRET to enable'
|
|
);
|
|
}
|
|
|
|
logger.info('✅ Ready to handle requests');
|
|
});
|
|
|
|
// Setup graceful shutdown
|
|
setupGracefulShutdown(server, {
|
|
timeout: 30000,
|
|
onShutdown: async () => {
|
|
logger.info('Running cleanup tasks...');
|
|
// Add any cleanup tasks here (close DB connections, etc.)
|
|
}
|
|
});
|