1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-13 12:24:36 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Saad Jutt
9ed10109c1 chore: specified domain for cookie 2022-10-09 19:24:42 +05:00
Saad Jutt
ef9cca575f fix: added domain check if provided 2022-10-04 23:47:41 +05:00
11 changed files with 83 additions and 20 deletions

View File

@@ -1,5 +1,6 @@
MODE=[desktop|server] default considered as desktop MODE=[desktop|server] default considered as desktop
CORS=[disable|enable] default considered as disable for server MODE & enable for desktop MODE CORS=[disable|enable] default considered as disable for server MODE & enable for desktop MODE
ALLOWED_DOMAINS=<space separated urls, each starting with protocol `http` or `https`>
WHITELIST=<space separated urls, each starting with protocol `http` or `https`> WHITELIST=<space separated urls, each starting with protocol `http` or `https`>
PROTOCOL=[http|https] default considered as http PROTOCOL=[http|https] default considered as http

View File

@@ -3,10 +3,21 @@ import cors from 'cors'
import { CorsType } from '../utils' import { CorsType } from '../utils'
export const configureCors = (app: Express) => { export const configureCors = (app: Express) => {
const { CORS } = process.env
if (CORS === CorsType.ENABLED) {
const whiteList = getWhiteListed()
console.log('All CORS Requests are enabled for:', whiteList)
app.use(cors({ credentials: true, origin: whiteList }))
}
}
export const getWhiteListed = (): string[] => {
const whiteList: string[] = []
const { CORS, WHITELIST } = process.env const { CORS, WHITELIST } = process.env
if (CORS === CorsType.ENABLED) { if (CORS === CorsType.ENABLED) {
const whiteList: string[] = []
WHITELIST?.split(' ') WHITELIST?.split(' ')
?.filter((url) => !!url) ?.filter((url) => !!url)
.forEach((url) => { .forEach((url) => {
@@ -14,8 +25,6 @@ export const configureCors = (app: Express) => {
// removing trailing slash of URLs listing for CORS // removing trailing slash of URLs listing for CORS
whiteList.push(url.replace(/\/$/, '')) whiteList.push(url.replace(/\/$/, ''))
}) })
console.log('All CORS Requests are enabled for:', whiteList)
app.use(cors({ credentials: true, origin: whiteList }))
} }
return whiteList
} }

View File

@@ -0,0 +1,29 @@
import { Express } from 'express'
import { checkDomain } from '../middlewares'
import { getWhiteListed } from './configureCors'
export const configureDomains = (app: Express) => {
// const domains: string[] = []
const domains = new Set<string>()
const { ALLOWED_DOMAINS } = process.env
const allowedDomains = ALLOWED_DOMAINS?.trim().split(' ') ?? []
const whiteListed = getWhiteListed()
const combinedUrls = [...allowedDomains, ...whiteListed]
combinedUrls
.filter((domainName) => !!domainName)
.forEach((url) => {
try {
const domain = new URL(url)
domains.add(domain.hostname)
} catch (_) {}
})
if (domains.size) {
process.allowedDomains = [...domains]
console.log('Allowed Domain(s):', process.allowedDomains)
app.use(checkDomain)
}
}

View File

@@ -1,10 +1,9 @@
import { Express } from 'express' import { Express, CookieOptions } from 'express'
import mongoose from 'mongoose' import mongoose from 'mongoose'
import session from 'express-session' import session from 'express-session'
import MongoStore from 'connect-mongo' import MongoStore from 'connect-mongo'
import { ModeType } from '../utils' import { ModeType, ProtocolType } from '../utils'
import { cookieOptions } from '../app'
export const configureExpressSession = (app: Express) => { export const configureExpressSession = (app: Express) => {
const { MODE } = process.env const { MODE } = process.env
@@ -19,6 +18,15 @@ export const configureExpressSession = (app: Express) => {
}) })
} }
const { PROTOCOL } = process.env
const cookieOptions: CookieOptions = {
secure: PROTOCOL === ProtocolType.HTTPS,
httpOnly: true,
sameSite: PROTOCOL === ProtocolType.HTTPS ? 'none' : undefined,
maxAge: 24 * 60 * 60 * 1000, // 24 hours
domain: 'sas.4gl.io'
}
app.use( app.use(
session({ session({
secret: process.secrets.SESSION_SECRET, secret: process.secrets.SESSION_SECRET,

View File

@@ -1,4 +1,5 @@
export * from './configureCors' export * from './configureCors'
export * from './configureDomains'
export * from './configureExpressSession' export * from './configureExpressSession'
export * from './configureLogger' export * from './configureLogger'
export * from './configureSecurity' export * from './configureSecurity'

View File

@@ -1,5 +1,5 @@
import path from 'path' import path from 'path'
import express, { ErrorRequestHandler, CookieOptions } from 'express' import express, { ErrorRequestHandler } from 'express'
import cookieParser from 'cookie-parser' import cookieParser from 'cookie-parser'
import dotenv from 'dotenv' import dotenv from 'dotenv'
@@ -8,7 +8,6 @@ import {
getWebBuildFolder, getWebBuildFolder,
instantiateLogger, instantiateLogger,
loadAppStreamConfig, loadAppStreamConfig,
ProtocolType,
ReturnCode, ReturnCode,
setProcessVariables, setProcessVariables,
setupFolders, setupFolders,
@@ -16,6 +15,7 @@ import {
} from './utils' } from './utils'
import { import {
configureCors, configureCors,
configureDomains,
configureExpressSession, configureExpressSession,
configureLogger, configureLogger,
configureSecurity configureSecurity
@@ -29,15 +29,6 @@ if (verifyEnvVariables()) process.exit(ReturnCode.InvalidEnv)
const app = express() const app = express()
const { PROTOCOL } = process.env
export const cookieOptions: CookieOptions = {
secure: PROTOCOL === ProtocolType.HTTPS,
httpOnly: true,
sameSite: PROTOCOL === ProtocolType.HTTPS ? 'none' : undefined,
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
const onError: ErrorRequestHandler = (err, req, res, next) => { const onError: ErrorRequestHandler = (err, req, res, next) => {
console.error(err.stack) console.error(err.stack)
res.status(500).send('Something broke!') res.status(500).send('Something broke!')
@@ -58,6 +49,11 @@ export default setProcessVariables().then(async () => {
***********************************/ ***********************************/
configureCors(app) configureCors(app)
/***********************************
* Allowed Domains *
***********************************/
configureDomains(app)
/*********************************** /***********************************
* DB Connection & * * DB Connection & *
* Express Sessions * * Express Sessions *

View File

@@ -0,0 +1,17 @@
import { RequestHandler } from 'express'
export const checkDomain: RequestHandler = (req, res, next) => {
const { allowedDomains } = process
// pass if no allowed domain is specified
if (!allowedDomains.length) return next()
if (allowedDomains.includes(req.hostname)) return next()
console.log('allowedDomains', allowedDomains)
console.log('hostname not allowed', req.hostname)
res.writeHead(404, {
'Content-Type': 'text/plain'
})
return res.end('Not found')
}

View File

@@ -1,5 +1,6 @@
export * from './authenticateToken' export * from './authenticateToken'
export * from './authorize' export * from './authorize'
export * from './checkDomain'
export * from './csrfProtection' export * from './csrfProtection'
export * from './desktop' export * from './desktop'
export * from './verifyAdmin' export * from './verifyAdmin'

View File

@@ -12,5 +12,6 @@ declare namespace NodeJS {
logger: import('@sasjs/utils/logger').Logger logger: import('@sasjs/utils/logger').Logger
runTimes: import('../../utils').RunTimeType[] runTimes: import('../../utils').RunTimeType[]
secrets: import('../../model/Configuration').ConfigurationType secrets: import('../../model/Configuration').ConfigurationType
allowedDomains: string[]
} }
} }

View File

@@ -252,7 +252,7 @@ const verifyRUN_TIMES = (): string[] => {
return errors return errors
} }
const verifyExecutablePaths = () => { const verifyExecutablePaths = (): string[] => {
const errors: string[] = [] const errors: string[] = []
const { RUN_TIMES, SAS_PATH, NODE_PATH, PYTHON_PATH, R_PATH, MODE } = const { RUN_TIMES, SAS_PATH, NODE_PATH, PYTHON_PATH, R_PATH, MODE } =
process.env process.env

View File

@@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "ES6",
"module": "commonjs", "module": "commonjs",
"rootDir": "./", "rootDir": "./",
"outDir": "./build", "outDir": "./build",