efe3e514b0
Security: - Escape user-supplied values in LDAP filters and DNs (group_ldap.js, user_ldap.js) - Replace Math.random() token/UUID/OTP generation with crypto.randomUUID / crypto.randomInt - Refuse startup when oauth.jwtSecret is missing or placeholder Fixes: - Correct from-address template rendering in email.js Packaging: - Remove private flag and bump version to 1.1.16 Co-Authored-By: Claude <noreply@anthropic.com>
464 lines
16 KiB
JavaScript
464 lines
16 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('crypto');
|
|
const jwt = require('jsonwebtoken');
|
|
const express = require('express');
|
|
const conf = require('@simpleworkjs/conf');
|
|
const { OAuthClient } = require('../models/oauth_client');
|
|
const { OAuthCode, OAuthAccessToken, OAuthRefreshToken } = require('../models/oauth_code');
|
|
const { User } = require('../models/user');
|
|
const { Group } = require('../models/group_ldap');
|
|
const buildInfo = require('../utils/build_info');
|
|
|
|
const oauthConf = conf.oauth || {};
|
|
const issuer = oauthConf.issuer || `http://localhost:${conf.port || 3000}`;
|
|
const jwtSecret = oauthConf.jwtSecret;
|
|
if (!jwtSecret || jwtSecret === '__in secrets file__' || jwtSecret === 'change-me-in-secrets') {
|
|
throw new Error('oauth.jwtSecret is not configured. Set it in your secrets file before starting the app.');
|
|
}
|
|
|
|
const pageLocals = {
|
|
title: conf.environment !== 'production' ? 'dev' : '',
|
|
titleIcon: conf.environment !== 'production' ? '<i class="fa-brands fa-dev"></i>' : '',
|
|
name: conf.name,
|
|
logo: conf.logo,
|
|
...buildInfo,
|
|
};
|
|
|
|
// --- helpers ---
|
|
|
|
function makeError(name, message, status) {
|
|
const error = new Error(name);
|
|
error.name = name;
|
|
error.message = message;
|
|
error.status = status;
|
|
return error;
|
|
}
|
|
|
|
// A registered redirect_uri may use `*` (one hostname label, no '.' or '/') or
|
|
// `**` (anything) as a wildcard — e.g. `https://*.example.com/__proxy_auth/callback`
|
|
// covers every host theta42/proxy fronts under example.com, so operators don't
|
|
// have to register each proxied host's callback individually. Mirrors the
|
|
// */** wildcard convention proxy's own Host.host field already uses.
|
|
function redirectUriAllowed(patterns, uri) {
|
|
if (!Array.isArray(patterns) || !uri) return false;
|
|
for (const pattern of patterns) {
|
|
if (pattern === uri) return true;
|
|
if (typeof pattern !== 'string' || pattern.indexOf('*') === -1) continue;
|
|
|
|
const DOUBLE = ' |