Add UA_MAIL_BLOCKLIST option

This commit is contained in:
Jonas Lochmann 2024-03-18 01:00:00 +01:00
parent 120ea33547
commit e6cc08a292
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
3 changed files with 15 additions and 4 deletions

View file

@ -57,3 +57,5 @@
- SIGN_SECRET - SIGN_SECRET
- used for signing tokens - used for signing tokens
- if not set or set to an empty string, then the features that depend on it are disabled - if not set or set to an empty string, then the features that depend on it are disabled
- UA_MAIL_BLOCKLIST
- List of user agents, separated by comma, that are not allowed to trigger sign in mails

View file

@ -17,7 +17,8 @@
import { json } from 'body-parser' import { json } from 'body-parser'
import { Router } from 'express' import { Router } from 'express'
import { BadRequest } from 'http-errors' import { BadRequest, Forbidden } from 'http-errors'
import { config } from '../config'
import { Database } from '../database' import { Database } from '../database'
import { sendLoginCode, signInByMailCode } from '../function/authentication/login-by-mail' import { sendLoginCode, signInByMailCode } from '../function/authentication/login-by-mail'
import { isMailAddressCoveredByWhitelist, isMailServerBlacklisted, sanitizeMailAddress } from '../util/mail' import { isMailAddressCoveredByWhitelist, isMailServerBlacklisted, sanitizeMailAddress } from '../util/mail'
@ -49,6 +50,8 @@ export const createAuthRouter = (database: Database) => {
res.json({ mailAddressNotWhitelisted: true }) res.json({ mailAddressNotWhitelisted: true })
} else if (isMailServerBlacklisted(mail)) { } else if (isMailServerBlacklisted(mail)) {
res.json({ mailServerBlacklisted: true }) res.json({ mailServerBlacklisted: true })
} else if (config.uaMailBlocklist.indexOf(req.headers['user-agent'] || '') !== -1) {
throw new Forbidden()
} else { } else {
const { mailLoginToken } = await sendLoginCode({ const { mailLoginToken } = await sendLoginCode({
mail, mail,

View file

@ -1,6 +1,6 @@
/* /*
* server component for the TimeLimit App * server component for the TimeLimit App
* Copyright (C) 2019 - 2022 Jonas Lochmann * Copyright (C) 2019 - 2024 Jonas Lochmann
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as * it under the terms of the GNU Affero General Public License as
@ -22,6 +22,7 @@ interface Config {
pingInterval: number pingInterval: number
alwaysPro: boolean alwaysPro: boolean
signSecret: string signSecret: string
uaMailBlocklist: Array<string>
} }
function parseYesNo (value: string) { function parseYesNo (value: string) {
@ -34,12 +35,17 @@ function parseYesNo (value: string) {
} }
} }
function parseList(list: string) {
return list.split(',').map((item) => item.trim()).filter((item) => item.length > 0)
}
class ParseYesNoException extends Error {} class ParseYesNoException extends Error {}
export const config: Config = { export const config: Config = {
mailWhitelist: (process.env.MAIL_WHITELIST || '').split(',').map((item) => item.trim()).filter((item) => item.length > 0), mailWhitelist: parseList(process.env.MAIL_WHITELIST || ''),
disableSignup: parseYesNo(process.env.DISABLE_SIGNUP || 'no'), disableSignup: parseYesNo(process.env.DISABLE_SIGNUP || 'no'),
pingInterval: parseInt(process.env.PING_INTERVAL_SEC || '25', 10) * 1000, pingInterval: parseInt(process.env.PING_INTERVAL_SEC || '25', 10) * 1000,
alwaysPro: process.env.ALWAYS_PRO ? parseYesNo(process.env.ALWAYS_PRO) : false, alwaysPro: process.env.ALWAYS_PRO ? parseYesNo(process.env.ALWAYS_PRO) : false,
signSecret: process.env.SIGN_SECRET || '' signSecret: process.env.SIGN_SECRET || '',
uaMailBlocklist: parseList(process.env.UA_MAIL_BLOCKLIST || '')
} }