Importación de feature/registration
This commit is contained in:
@@ -6,6 +6,9 @@ import cors from 'cors';
|
||||
import { Pool } from 'pg';
|
||||
import bcrypt from'bcrypt';
|
||||
|
||||
import { Issuer, generators } from 'openid-client';
|
||||
import cookieSession from 'cookie-session';
|
||||
|
||||
// Rutas
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
@@ -39,6 +42,14 @@ app.set('trust proxy', true);
|
||||
app.use(express.static(path.join(__dirname, 'pages')));
|
||||
|
||||
|
||||
app.use(cookieSession({
|
||||
name: 'sid',
|
||||
secret: process.env.SESSION_SECRET,
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: false // en prod detrás de https: true
|
||||
}));
|
||||
|
||||
// Configuración de conexión PostgreSQL
|
||||
|
||||
const dbConfig = {
|
||||
@@ -65,6 +76,20 @@ async function verificarConexion() {
|
||||
}
|
||||
}
|
||||
|
||||
// Descubrimiento OIDC (una sola vez)
|
||||
let oidcClient;
|
||||
async function getClient() {
|
||||
if (oidcClient) return oidcClient;
|
||||
const ISSUER = process.env.OIDC_ISSUER_INTERNAL; // ej: http://authentik:9000/application/o/suitecoffee/
|
||||
const issuer = await Issuer.discover(`${ISSUER}.well-known/openid-configuration`);
|
||||
oidcClient = new issuer.Client({
|
||||
client_id: process.env.OIDC_CLIENT_ID,
|
||||
client_secret: process.env.OIDC_CLIENT_SECRET,
|
||||
redirect_uris: [`${process.env.BASE_URL}${process.env.OIDC_REDIRECT_PATH}`],
|
||||
response_types: ['code']
|
||||
});
|
||||
return oidcClient;
|
||||
}
|
||||
|
||||
// === Servir páginas estáticas ===
|
||||
|
||||
@@ -178,6 +203,58 @@ app.post('/api/login', async (req, res) => {
|
||||
});
|
||||
|
||||
|
||||
// --- login: redirige a Authentik con PKCE
|
||||
app.get('/auth/login', async (req, res) => {
|
||||
const client = await getClient();
|
||||
const state = generators.state();
|
||||
const code_verifier = generators.codeVerifier();
|
||||
const code_challenge = generators.codeChallenge(code_verifier);
|
||||
|
||||
req.session.state = state;
|
||||
req.session.code_verifier = code_verifier;
|
||||
|
||||
const authUrl = client.authorizationUrl({
|
||||
scope: 'openid profile email',
|
||||
state,
|
||||
code_challenge,
|
||||
code_challenge_method: 'S256'
|
||||
});
|
||||
|
||||
res.redirect(authUrl);
|
||||
});
|
||||
|
||||
// --- callback: intercambia code por tokens y guarda sesión mínima
|
||||
app.get(process.env.OIDC_REDIRECT_PATH || '/auth/callback', async (req, res) => {
|
||||
const client = await getClient();
|
||||
const { state, code } = req.query;
|
||||
|
||||
if (!state || state !== req.session.state) {
|
||||
return res.status(400).send('state inválido');
|
||||
}
|
||||
const params = { state, code, code_verifier: req.session.code_verifier };
|
||||
const tokenSet = await client.callback(`${process.env.BASE_URL}${process.env.OIDC_REDIRECT_PATH}`, params, { state });
|
||||
|
||||
// Guarda lo que necesites para pruebas (id_token y claims)
|
||||
req.session.user = tokenSet.claims();
|
||||
req.session.id_token = tokenSet.id_token;
|
||||
req.session.access_token = tokenSet.access_token;
|
||||
|
||||
// Redirigí a donde quieras (página de bienvenida)
|
||||
res.redirect('/auth/me');
|
||||
});
|
||||
|
||||
// --- ver quién soy (para probar)
|
||||
app.get('/auth/me', (req, res) => {
|
||||
if (!req.session?.user) return res.status(401).json({ error: 'no autenticado' });
|
||||
res.json({ user: req.session.user });
|
||||
});
|
||||
|
||||
// --- logout simple (borra cookie)
|
||||
app.post('/auth/logout', (req, res) => {
|
||||
req.session = null;
|
||||
res.status(204).end();
|
||||
});
|
||||
|
||||
// Colores personalizados
|
||||
let primaryColor = chalk.hex('#'+`${process.env.COL_PRI}`);
|
||||
let secondaryColor = chalk.hex('#'+`${process.env.COL_SEC}`);
|
||||
|
||||
Reference in New Issue
Block a user