From a17e1eafb0dbc4b61029c24f685387408b03bb34 Mon Sep 17 00:00:00 2001 From: Miroslav Pejic Date: Thu, 23 Nov 2023 17:46:13 +0100 Subject: [PATCH] [mirotalksfu] - add host.auth_user --- README.md | 83 +++++++++++++++++++++++++------ app/api/join/join.js | 2 +- app/api/join/join.php | 14 +++--- app/api/join/join.py | 2 +- app/api/join/join.sh | 2 +- app/src/Server.js | 95 +++++++++++++++++++++++++++--------- app/src/ServerApi.js | 4 +- app/src/config.template.js | 3 +- package.json | 2 +- public/images/forbidden.png | Bin 0 -> 3660 bytes public/js/Room.js | 32 +++++++++++- public/js/RoomClient.js | 27 +++++++++- public/views/login.html | 8 ++- 13 files changed, 217 insertions(+), 57 deletions(-) create mode 100644 public/images/forbidden.png diff --git a/README.md b/README.md index c5f663ad..d8201237 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ - Unlimited conference rooms with no time limitations. - Translated into 133 languages. - Host protection to prevent unauthorized access. +- User auth to prevent unauthorized access. - Room password protection. - Compatible with desktop and mobile devices. - Optimized mobile room URL sharing. @@ -79,26 +80,76 @@
- You can `directly join a room` by using link like: -- https://sfu.mirotalk.com/join?room=test&password=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0 +- https://sfu.mirotalk.com/join?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0 - | Params | Type | Description | - | -------- | -------------- | --------------- | - | room | string | Room Id | - | password | string/boolean | Room password | - | name | string | User name | - | audio | boolean | Audio stream | - | video | boolean | Video stream | - | screen | boolean | Screen stream | - | notify | boolean | Welcome message | + | Params | Type | Description | + | ------------ | -------------- | --------------- | + | room | string | Room Id | + | roomPassword | string/boolean | Room password | + | name | string | User name | + | audio | boolean | Audio stream | + | video | boolean | Video stream | + | screen | boolean | Screen stream | + | notify | boolean | Welcome message | + | username | string | auth username | + | password | string | auth password | > **Note** > -> When [host protection is enabled](https://github.com/miroslavpejic85/mirotalksfu/commit/ab21686e9ad4b75e14c3ee020141d61b33111dde#commitcomment-62398736) the host needs to provide a valid username and password as specified in the `app/src/config.js`. -> -> After host authentication, participants can join the room using any of the following URL formats: -> -> - https://sfu.mirotalk.com/join/test (URL path) -> - https://sfu.mirotalk.com/join/?room=test&password=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0 (URL with query parameters for direct join) +> The `username` and `password` parameters are required when either `host.protected` or `host.user_auth` is set to `true` in the `app/src/config.js` file. The valid list of users is defined in the `host.users` configuration. + + + +
+Host Protection Configuration + +
+ +When [host.protected](https://github.com/miroslavpejic85/mirotalksfu/commit/ab21686e9ad4b75e14c3ee020141d61b33111dde#commitcomment-62398736) or `host.user_auth` is enabled, the host/users must provide a valid username and password as specified in the `app/src/config.js` file. + +| Params | Value | Description | +| ---------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `host.protected` | `true` if protection is enabled, `false` if not (default false) | Requires the host to provide a valid username and password during room initialization. | +| `host.user_auth` | `true` if user authentication is required, `false` if not (default false). | Determines whether host authentication is required. | +| `host.users` | JSON array with user objects: `{"username": "username", "password": "password"}` | List of valid host users with their credentials. | + +Example: + +```js + host: { + protected: true, + user_auth: true, + users: [ + { + username: 'username', + password: 'password', + }, + { + username: 'username2', + password: 'password2', + }, + //... + ], + }, +``` + +### Room Initialization + +To bypass the login page, join the room with URL parameters: + +- [https://sfu.mirotalk.com/join/?room=test&username=username&password=password](https://sfu.mirotalk.com/join/?room=test&username=username&password=password) + +### Participant Room Entry + +If `host.protected` is enabled, participants can join after host authentication using: + +- [https://sfu.mirotalk.com/join/test](https://sfu.mirotalk.com/join/test) (URL path) +- [https://sfu.mirotalk.com/join/?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0](https://sfu.mirotalk.com/join/?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0) (URL with query parameters) + +If `host.user_auth` is enabled, participants can join with mandatory credentials: + +- [https://sfu.mirotalk.com/join/?room=test&username=username&password=password](https://sfu.mirotalk.com/join/?room=test&username=username&password=password) (URL path) +- [https://sfu.mirotalk.com/join/?room=test&name=mirotalk&audio=0&video=0&screen=0¬ify=0&username=username&password=password](https://sfu.mirotalk.com/join/?room=test&name=mirotalk&audio=0&video=0&screen=0&¬ify=0&username=username&password=password) (URL with query parameters)
diff --git a/app/api/join/join.js b/app/api/join/join.js index ef797d8a..c9cf48f2 100644 --- a/app/api/join/join.js +++ b/app/api/join/join.js @@ -17,7 +17,7 @@ async function getJoin() { }, body: JSON.stringify({ room: 'test', - password: false, + roomPassword: false, name: 'mirotalksfu', audio: true, video: true, diff --git a/app/api/join/join.php b/app/api/join/join.php index d64c38f7..beac30c5 100644 --- a/app/api/join/join.php +++ b/app/api/join/join.php @@ -17,13 +17,13 @@ $headers = [ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $data = array( - "room" => "test", - "password" => false, - "name" => "mirotalksfu", - "audio" => true, - "video" => true, - "screen" => true, - "notify" => true, + "room" => "test", + "roomPassword" => false, + "name" => "mirotalksfu", + "audio" => true, + "video" => true, + "screen" => true, + "notify" => true, ); $data_string = json_encode($data); diff --git a/app/api/join/join.py b/app/api/join/join.py index 72cfb7a9..c331334f 100644 --- a/app/api/join/join.py +++ b/app/api/join/join.py @@ -13,7 +13,7 @@ headers = { data = { "room": "test", - "password": "false", + "roomPassword": "false", "name": "mirotalksfu", "audio": "true", "video": "true", diff --git a/app/api/join/join.sh b/app/api/join/join.sh index d3dd0828..fd1d8534 100755 --- a/app/api/join/join.sh +++ b/app/api/join/join.sh @@ -7,5 +7,5 @@ MIROTALK_URL="https://sfu.mirotalk.com/api/v1/join" curl $MIROTALK_URL \ --header "authorization: $API_KEY_SECRET" \ --header "Content-Type: application/json" \ - --data '{"room":"test","password":"false","name":"mirotalksfu","audio":"true","video":"true","screen":"false","notify":"true"}' \ + --data '{"room":"test","roomPassword":"false","name":"mirotalksfu","audio":"true","video":"true","screen":"false","notify":"true"}' \ --request POST \ No newline at end of file diff --git a/app/src/Server.js b/app/src/Server.js index f1597052..a661792e 100644 --- a/app/src/Server.js +++ b/app/src/Server.js @@ -40,7 +40,7 @@ dependencies: { * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.2.7 + * @version 1.2.8 * */ @@ -92,6 +92,7 @@ const host = 'https://' + 'localhost' + ':' + config.server.listen.port; // conf const hostCfg = { protected: config.host.protected, + user_auth: config.host.user_auth, users: config.host.users, authenticated: !config.host.protected, }; @@ -269,13 +270,30 @@ function startServer() { // no room name specified to join || direct join app.get('/join/', (req, res) => { - if (hostCfg.authenticated && Object.keys(req.query).length > 0) { + if (Object.keys(req.query).length > 0) { log.debug('Direct Join', req.query); - // http://localhost:3010/join?room=test&password=0&name=mirotalksfu&audio=1&video=1&screen=1¬ify=1 - const { room, password, name, audio, video, screen, notify, isPresenter } = checkXSS(req.query); - // if (room && password && name && audio && video && screen && notify) { - if (room) { + // http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0¬ify=1 + // http://localhost:3010/join?room=test&roomPassword=0&name=mirotalksfu&audio=1&video=1&screen=0¬ify=0&username=username&password=password + const { room, roomPassword, name, audio, video, screen, notify, username, password, isPresenter } = + checkXSS(req.query); + + const isPeerValid = isAuthPeer(username, password); + + if (hostCfg.protected && isPeerValid && !hostCfg.authenticated) { + const ip = getIP(req); + hostCfg.authenticated = true; + authHost = new Host(ip, true); + log.debug('Direct Join user auth as host done', { + ip: ip, + username: username, + password: password, + }); + } + + if (room && (hostCfg.authenticated || isPeerValid)) { return res.sendFile(views.room); + } else { + return res.sendFile(views.login); } } if (hostCfg.protected) { @@ -323,6 +341,11 @@ function startServer() { res.send(stats); }); + // handle login if user_auth enabled + app.get(['/login'], (req, res) => { + res.sendFile(views.login); + }); + // handle logged on host protected app.get(['/logged'], (req, res) => { const ip = getIP(req); @@ -340,24 +363,26 @@ function startServer() { // handle login on host protected app.post(['/login'], (req, res) => { - if (hostCfg.protected) { - let ip = getIP(req); - log.debug(`Request login to host from: ${ip}`, req.body); - const { username, password } = checkXSS(req.body); - const isValidUser = - hostCfg.users && hostCfg.users.some((user) => user.username === username && user.password === password); - if (isValidUser) { - hostCfg.authenticated = true; - authHost = new Host(ip, true); - log.debug('LOGIN OK', { ip: ip, authorized: authHost.isAuthorized(ip) }); - res.status(200).json({ message: 'authorized' }); - } else { - log.debug('LOGIN KO', { ip: ip, authorized: false }); - hostCfg.authenticated = false; - res.status(401).json({ message: 'unauthorized' }); - } + const ip = getIP(req); + log.debug(`Request login to host from: ${ip}`, req.body); + + const { username, password } = checkXSS(req.body); + + const isPeerValid = isAuthPeer(username, password); + + if (hostCfg.protected && isPeerValid && !hostCfg.authenticated) { + const ip = getIP(req); + hostCfg.authenticated = true; + authHost = new Host(ip, true); + log.debug('HOST LOGIN OK', { ip: ip, authorized: authHost.isAuthorized(ip) }); + return res.status(200).json({ message: 'authorized' }); + } + + if (isPeerValid) { + log.debug('PEER LOGIN OK', { ip: ip, authorized: true }); + return res.status(200).json({ message: 'authorized' }); } else { - res.redirect('/'); + return res.status(401).json({ message: 'unauthorized' }); } }); @@ -896,6 +921,26 @@ function startServer() { log.debug('User joined', data); + // User Auth required, we check if peer valid + if (hostCfg.user_auth) { + const peer_username = data.peer_info.peer_username; + const peer_password = data.peer_info.peer_password; + + const isPeerValid = isAuthPeer(peer_username, peer_password); + + log.debug('[' + socket.id + '] JOIN ROOM - HOST PROTECTED - USER AUTH check peer', { + ip: peer_ip, + peer_username: peer_username, + peer_password: peer_password, + peer_valid: isPeerValid, + }); + + if (!isPeerValid) { + // redirect peer to login page + return cb('unauthorized'); + } + } + const room = roomList.get(socket.room_id); room.addPeer(new Peer(socket.id, data)); @@ -1348,6 +1393,10 @@ function startServer() { } } + function isAuthPeer(username, password) { + return hostCfg.users && hostCfg.users.some((user) => user.username === username && user.password === password); + } + async function getPeerGeoLocation(ip) { const endpoint = config.IPLookup.getEndpoint(ip); log.debug('Get peer geo', { ip: ip, endpoint: endpoint }); diff --git a/app/src/ServerApi.js b/app/src/ServerApi.js index d001835a..076ee422 100644 --- a/app/src/ServerApi.js +++ b/app/src/ServerApi.js @@ -25,8 +25,8 @@ module.exports = class ServerApi { this._host + '/join?room=' + data.room + - '&password=' + - data.password + + '&roomPassword=' + + data.roomPassword + '&name=' + data.name + '&audio=' + diff --git a/app/src/config.template.js b/app/src/config.template.js index 4555b3eb..a368f6ee 100644 --- a/app/src/config.template.js +++ b/app/src/config.template.js @@ -39,10 +39,11 @@ module.exports = { host: { /* Host Protection (default: false) - To enhance host security, enable host protection and provide valid + To enhance host security, enable host protection - user auth and provide valid usernames and passwords in the users array. */ protected: false, + user_auth: false, users: [ { username: 'username', diff --git a/package.json b/package.json index 5df6dc43..dd471532 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalksfu", - "version": "1.2.7", + "version": "1.2.8", "description": "WebRTC SFU browser-based video calls", "main": "Server.js", "scripts": { diff --git a/public/images/forbidden.png b/public/images/forbidden.png new file mode 100644 index 0000000000000000000000000000000000000000..685fa92f835958aaedb83e1729497d4dba1df3f5 GIT binary patch literal 3660 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 literal 0 HcmV?d00001 diff --git a/public/js/Room.js b/public/js/Room.js index e43454f3..a77dfbe3 100644 --- a/public/js/Room.js +++ b/public/js/Room.js @@ -11,7 +11,7 @@ if (location.href.substr(0, 5) !== 'https') location.href = 'https' + location.h * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.2.7 + * @version 1.2.8 * */ @@ -86,6 +86,8 @@ let room_id = getRoomId(); let room_password = getRoomPassword(); let peer_name = getPeerName(); let peer_uuid = getPeerUUID(); +let peer_username = getPeerUsername(); +let peer_password = getPeerPassword(); let isScreenAllowed = getScreen(); let notify = getNotify(); isPresenter = isPeerPresenter(); @@ -568,9 +570,33 @@ function getPeerUUID() { return peer_uuid; } +function getPeerUsername() { + if (window.sessionStorage.peer_username) return window.sessionStorage.peer_username; + let qs = new URLSearchParams(window.location.search); + let username = filterXSS(qs.get('username')); + let queryUsername = false; + if (username) { + queryUsername = username; + } + console.log('Direct join', { username: queryUsername }); + return queryUsername; +} + +function getPeerPassword() { + if (window.sessionStorage.peer_password) return window.sessionStorage.peer_password; + let qs = new URLSearchParams(window.location.search); + let password = filterXSS(qs.get('password')); + let queryPassword = false; + if (password) { + queryPassword = password; + } + console.log('Direct join', { password: queryPassword }); + return queryPassword; +} + function getRoomPassword() { let qs = new URLSearchParams(window.location.search); - let roomPassword = filterXSS(qs.get('password')); + let roomPassword = filterXSS(qs.get('roomPassword')); if (roomPassword) { let queryNoRoomPassword = roomPassword === '0' || roomPassword === 'false'; if (queryNoRoomPassword) { @@ -609,6 +635,8 @@ function getPeerInfo() { peer_uuid: peer_uuid, peer_id: socket.id, peer_name: peer_name, + peer_username: peer_username, + peer_password: peer_password, peer_presenter: isPresenter, peer_audio: isAudioAllowed, peer_video: isVideoAllowed, diff --git a/public/js/RoomClient.js b/public/js/RoomClient.js index 30940e53..009444b1 100644 --- a/public/js/RoomClient.js +++ b/public/js/RoomClient.js @@ -9,7 +9,7 @@ * @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.2.7 + * @version 1.2.8 * */ @@ -83,6 +83,7 @@ const image = { email: '../images/email.png', chatgpt: '../images/chatgpt.png', all: '../images/all.png', + forbidden: '../images/forbidden.png', }; const mediaType = { @@ -318,6 +319,12 @@ class RoomClient { .then( async function (room) { console.log('##### JOIN ROOM #####', room); + if (room === 'unauthorized') { + console.log( + '00-WARNING ----> Room is Unauthorized for current user, please provide a valid username and password', + ); + return this.userUnauthorized(); + } if (room === 'isLocked') { this.event(_EVENTS.roomLock); console.log('00-WARNING ----> Room is Locked, Try to unlock by the password'); @@ -4829,6 +4836,24 @@ class RoomClient { // HANDLE ROOM ACTION // #################################################### + userUnauthorized() { + this.sound('alert'); + Swal.fire({ + allowOutsideClick: false, + allowEscapeKey: false, + background: swalBackground, + imageUrl: image.forbidden, + title: 'Oops, Unauthorized', + text: 'The host has user authentication enabled', + confirmButtonText: `Login`, + showClass: { popup: 'animate__animated animate__fadeInDown' }, + hideClass: { popup: 'animate__animated animate__fadeOutUp' }, + }).then(() => { + // Login required to join room + openURL(`/login/?room=${this.room_id}`); + }); + } + unlockTheRoom() { if (room_password) { this.RoomPassword = room_password; diff --git a/public/views/login.html b/public/views/login.html index cae14198..c534fe23 100644 --- a/public/views/login.html +++ b/public/views/login.html @@ -133,7 +133,9 @@ const password = filterXSS(document.getElementById('password').value); // http://localhost:3010/join/?room=test - // http://localhost:3010/join/?room=test&password=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0 + // http://localhost:3010/join/?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0 + // http://localhost:3010/join/?room=test&roomPassword=0&name=mirotalksfu&audio=0&video=0&screen=0¬ify=0&username=username&password=password + const qs = new URLSearchParams(window.location.search); const room = filterXSS(qs.get('room')); @@ -150,6 +152,10 @@ .then(function (response) { console.log(response); + // Store in session + window.sessionStorage.peer_username = username; + window.sessionStorage.peer_password = password; + if (room) { return (window.location.href = '/join/' + window.location.search);