diff --git a/.env.template b/.env.template index 0b722ecd..a1574d9a 100644 --- a/.env.template +++ b/.env.template @@ -1,5 +1,5 @@ # ==================================================== -# MiroTalk P2P v.1.6.42 - Environment Configuration +# MiroTalk P2P v.1.6.43 - Environment Configuration # ==================================================== # App environment @@ -72,6 +72,9 @@ HOST_PROTECTED=false # true or false HOST_USER_AUTH=false # true or false HOST_USERS='[{"username": "admin", "password": "admin"},{"username": "guest", "password": "guest"}]' +HOST_MAX_LOGIN_ATTEMPTS=5 # Maximum number of failed login attempts allowed within the time window +HOST_MIN_LOGIN_BLOCK_TIME=15 # Duration of the lockout window (in minutes) + # JWT token config JWT_KEY=mirotalkp2p_jwt_secret diff --git a/app/src/config.template.js b/app/src/config.template.js index 0c9e3584..253ac8f0 100644 --- a/app/src/config.template.js +++ b/app/src/config.template.js @@ -2,7 +2,7 @@ /** * ============================================== - * MiroTalk P2P v.1.6.42 - Configuration File + * MiroTalk P2P v.1.6.43 - Configuration File * ============================================== * * Branding and customizations require a license: diff --git a/app/src/server.js b/app/src/server.js index 525cc9d9..5ec8450b 100755 --- a/app/src/server.js +++ b/app/src/server.js @@ -45,7 +45,7 @@ dependencies: { * @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.6.42 + * @version 1.6.43 * */ @@ -82,6 +82,17 @@ const nodemailer = require('./lib/nodemailer'); const packageJson = require('../../package.json'); +// Login attempts limit +const rateLimit = require('express-rate-limit'); +const maxAttempts = process.env.HOST_MAX_LOGIN_ATTEMPTS || 5; +const minBlockTime = process.env.HOST_MIN_LOGIN_BLOCK_TIME || 15; // in minutes +const loginLimiter = rateLimit({ + windowMs: minBlockTime * 60 * 1000, // 15 minutes default + max: maxAttempts, + message: 'Too many login attempts, please try again later.', + keyGenerator: (req) => req.body.username || ipKeyGenerator(req), +}); + const port = process.env.PORT || 3000; // must be the same to client.js signalingServerPort const host = process.env.HOST || `http://localhost:${port}`; @@ -756,7 +767,7 @@ app.get('/logged', (req, res) => { /* AXIOS */ // handle login on host protected -app.post('/login', (req, res) => { +app.post('/login', loginLimiter, (req, res) => { // const ip = getIP(req); log.debug(`Request login to host from: ${ip}`, req.body); diff --git a/package-lock.json b/package-lock.json index 4ba7df54..4ffd1983 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mirotalk", - "version": "1.6.42", + "version": "1.6.43", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mirotalk", - "version": "1.6.42", + "version": "1.6.43", "license": "AGPL-3.0", "dependencies": { "@mattermost/client": "11.1.0", @@ -22,6 +22,7 @@ "dotenv": "^17.2.3", "express": "^5.1.0", "express-openid-connect": "^2.19.3", + "express-rate-limit": "^8.2.1", "he": "^1.2.0", "helmet": "^8.1.0", "httpolyglot": "0.1.2", @@ -2961,6 +2962,24 @@ "node": ">= 0.6" } }, + "node_modules/express-rate-limit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", + "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", + "license": "MIT", + "dependencies": { + "ip-address": "10.0.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, "node_modules/express/node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -3783,6 +3802,15 @@ "node": ">= 0.4" } }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", diff --git a/package.json b/package.json index e12a5964..5899d2d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalk", - "version": "1.6.42", + "version": "1.6.43", "description": "A free WebRTC browser-based video call", "main": "server.js", "scripts": { @@ -54,12 +54,13 @@ "dotenv": "^17.2.3", "express": "^5.1.0", "express-openid-connect": "^2.19.3", + "express-rate-limit": "^8.2.1", "he": "^1.2.0", "helmet": "^8.1.0", "httpolyglot": "0.1.2", + "js-yaml": "^4.1.1", "jsdom": "^27.2.0", "jsonwebtoken": "^9.0.2", - "js-yaml": "^4.1.1", "nodemailer": "^7.0.10", "openai": "^6.9.1", "qs": "^6.14.0", diff --git a/public/js/brand.js b/public/js/brand.js index 915f1500..a7e54797 100644 --- a/public/js/brand.js +++ b/public/js/brand.js @@ -77,7 +77,7 @@ let brand = { }, about: { imageUrl: '../images/mirotalk-logo.gif', - title: 'WebRTC P2P v1.6.42', + title: 'WebRTC P2P v1.6.43', html: `