v0.5.14 — вход по токену, JWKS в mock-режиме, production deploy docs
- POST /login-token: принимает реальный JWT (не только clientId) - auth.js: verifyAnyToken — mock + JWKS (Keycloak Nubes) одновременно - auth.js: JWKS предзагружается всегда, даже в mock-режиме - devops-deploy.md: полная production-инструкция для DevOps - .env.example: production-ready шаблон - README.md: актуальный (v0.5.13, архитектура, тесты, ссылки) - .gitignore: очищен от дубликатов
This commit is contained in:
+42
-4
@@ -67,23 +67,61 @@ function createRouter({ auth, MOCK_USERS, authLimiter }) {
|
||||
// GET /login-token — редирект на /login (форма вставки токена там же)
|
||||
router.get('/login-token', (req, res) => res.redirect('/login'));
|
||||
|
||||
// POST /login-token — ручной вход по clientId (отладка)
|
||||
// POST /login-token — вход по Bearer JWT токену (реальному) или clientId (отладка)
|
||||
router.post('/login-token', authLimiter, (req, res) => {
|
||||
const { clientId, returnTo } = req.body;
|
||||
const { token, clientId, returnTo } = req.body;
|
||||
|
||||
// ── Вход по реальному JWT токену ──────────────────────────────────────
|
||||
if (token && token.trim()) {
|
||||
const raw = token.trim().replace(/^Bearer\s+/i, '');
|
||||
// Минимальная проверка: это JWT (3 части, разделённые точками)
|
||||
const parts = raw.split('.');
|
||||
if (parts.length !== 3) {
|
||||
return res.redirect('/login?error=Невалидный+JWT+токен');
|
||||
}
|
||||
// Декодируем payload (без проверки подписи — API проверит)
|
||||
let payload;
|
||||
try {
|
||||
const buf = Buffer.from(parts[1], 'base64url');
|
||||
payload = JSON.parse(buf.toString());
|
||||
if (!payload || typeof payload !== 'object') throw new Error('empty');
|
||||
} catch (_) {
|
||||
return res.redirect('/login?error=Невалидный+payload+токена');
|
||||
}
|
||||
|
||||
// Извлекаем данные пользователя из payload
|
||||
const rawClientId = payload.ClientID || payload.client_id || payload.preferred_username || payload.sub || '';
|
||||
const allClientIds = rawClientId.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const activeClientId = allClientIds[0] || rawClientId;
|
||||
|
||||
req.session.token = raw;
|
||||
req.session.user = {
|
||||
clientId: rawClientId,
|
||||
allClientIds,
|
||||
activeClientId,
|
||||
email: payload.email || payload.login || activeClientId + '@unknown',
|
||||
companyId: payload.company_id || payload.companyId || null,
|
||||
companyName: payload.company_name || payload.companyName || activeClientId,
|
||||
isAdmin: activeClientId === (process.env.ADMIN_CLIENT_ID || 'WZ01112'),
|
||||
};
|
||||
return res.redirect(returnTo || '/');
|
||||
}
|
||||
|
||||
// ── Вход по clientId (отладка, mock) ───────────────────────────────────
|
||||
if (!clientId || !clientId.trim()) return res.redirect('/login?error=Введите+clientId');
|
||||
|
||||
const trimmed = clientId.trim();
|
||||
const allClientIds = trimmed.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const activeClientId = allClientIds[0];
|
||||
|
||||
const token = auth.issueMockToken({
|
||||
const mockToken = auth.issueMockToken({
|
||||
clientId: trimmed,
|
||||
companyId: '00000000-0000-0000-0000-000000000001',
|
||||
companyName: activeClientId,
|
||||
email: activeClientId + '@debug.local',
|
||||
});
|
||||
|
||||
req.session.token = token;
|
||||
req.session.token = mockToken;
|
||||
req.session.user = {
|
||||
clientId: trimmed,
|
||||
allClientIds,
|
||||
|
||||
Reference in New Issue
Block a user