[mirotalksfu] - add token endpoint
هذا الالتزام موجود في:
@@ -73,6 +73,31 @@ paths:
|
|||||||
$ref: '#/definitions/JoinResponse'
|
$ref: '#/definitions/JoinResponse'
|
||||||
'403':
|
'403':
|
||||||
description: 'Unauthorized!'
|
description: 'Unauthorized!'
|
||||||
|
/token:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- 'token'
|
||||||
|
summary: 'Get token'
|
||||||
|
description: 'Get token'
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: token
|
||||||
|
description: Custom Token.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/TokenRequest'
|
||||||
|
consumes:
|
||||||
|
- 'application/json'
|
||||||
|
produces:
|
||||||
|
- 'application/json'
|
||||||
|
security:
|
||||||
|
- secretApiKey: []
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: 'Get token done'
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/TokenResponse'
|
||||||
|
'403':
|
||||||
|
description: 'Unauthorized!'
|
||||||
|
|
||||||
securityDefinitions:
|
securityDefinitions:
|
||||||
secretApiKey:
|
secretApiKey:
|
||||||
@@ -143,6 +168,11 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
join:
|
join:
|
||||||
type: string
|
type: string
|
||||||
|
TokenResponse:
|
||||||
|
type: 'object'
|
||||||
|
properties:
|
||||||
|
token:
|
||||||
|
type: string
|
||||||
Peer:
|
Peer:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
|||||||
36
app/api/token/token.js
Normal file
36
app/api/token/token.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
async function getMeeting() {
|
||||||
|
try {
|
||||||
|
// Use dynamic import with await
|
||||||
|
const { default: fetch } = await import('node-fetch');
|
||||||
|
|
||||||
|
const API_KEY_SECRET = 'mirotalksfu_default_secret';
|
||||||
|
const MIROTALK_URL = 'https://sfu.mirotalk.com/api/v1/token';
|
||||||
|
//const MIROTALK_URL = 'http://localhost:3010/api/v1/token';
|
||||||
|
|
||||||
|
const response = await fetch(MIROTALK_URL, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
authorization: API_KEY_SECRET,
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: 'username',
|
||||||
|
password: 'password',
|
||||||
|
presenter: true,
|
||||||
|
expire: '1h',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.error) {
|
||||||
|
console.log('Error:', data.error);
|
||||||
|
} else {
|
||||||
|
console.log('token:', data.token);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching data:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getMeeting();
|
||||||
37
app/api/token/token.php
Normal file
37
app/api/token/token.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$API_KEY_SECRET = "mirotalksfu_default_secret";
|
||||||
|
$MIROTALK_URL = "https://sfu.mirotalk.com/api/v1/token";
|
||||||
|
#$MIROTALK_URL = "http://localhost:3010/api/v1/token";
|
||||||
|
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $MIROTALK_URL);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, 1);
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'authorization:' . $API_KEY_SECRET,
|
||||||
|
'Content-Type: application/json'
|
||||||
|
];
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||||
|
|
||||||
|
$data = array(
|
||||||
|
"username" => "username",
|
||||||
|
"password" => "password",
|
||||||
|
"presenter" => true,
|
||||||
|
"expire" => "1h",
|
||||||
|
);
|
||||||
|
|
||||||
|
$data_string = json_encode($data);
|
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
echo "Status code: $httpcode \n";
|
||||||
|
$data = json_decode($response);
|
||||||
|
echo "token: ", $data->{'token'}, "\n";
|
||||||
29
app/api/token/token.py
Normal file
29
app/api/token/token.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# pip3 install requests
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
API_KEY_SECRET = "mirotalksfu_default_secret"
|
||||||
|
MIROTALK_URL = "https://sfu.mirotalk.com/api/v1/token"
|
||||||
|
#MIROTALK_URL = "http://localhost:3010/api/v1/token"
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"authorization": API_KEY_SECRET,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"username": "username",
|
||||||
|
"password": "password",
|
||||||
|
"presenter": "true",
|
||||||
|
"expire": "1h"
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
MIROTALK_URL,
|
||||||
|
headers=headers,
|
||||||
|
json=data
|
||||||
|
)
|
||||||
|
|
||||||
|
print("Status code:", response.status_code)
|
||||||
|
data = json.loads(response.text)
|
||||||
|
print("token:", data["token"])
|
||||||
11
app/api/token/token.sh
Executable file
11
app/api/token/token.sh
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_KEY_SECRET="mirotalksfu_default_secret"
|
||||||
|
MIROTALK_URL="https://sfu.mirotalk.com/api/v1/token"
|
||||||
|
#MIROTALK_URL="http://localhost:3010/api/v1/token"
|
||||||
|
|
||||||
|
curl $MIROTALK_URL \
|
||||||
|
--header "authorization: $API_KEY_SECRET" \
|
||||||
|
--header "Content-Type: application/json" \
|
||||||
|
--data '{"username":"username","password":"password","presenter":"true", "expire":"1h"}' \
|
||||||
|
--request POST
|
||||||
@@ -41,7 +41,7 @@ dependencies: {
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.3.75
|
* @version 1.3.76
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -579,7 +579,7 @@ function startServer() {
|
|||||||
return res.status(403).json({ error: 'Unauthorized!' });
|
return res.status(403).json({ error: 'Unauthorized!' });
|
||||||
}
|
}
|
||||||
// setup meeting URL
|
// setup meeting URL
|
||||||
let meetingURL = api.getMeetingURL();
|
const meetingURL = api.getMeetingURL();
|
||||||
res.json({ meeting: meetingURL });
|
res.json({ meeting: meetingURL });
|
||||||
// log.debug the output if all done
|
// log.debug the output if all done
|
||||||
log.debug('MiroTalk get meeting - Authorized', {
|
log.debug('MiroTalk get meeting - Authorized', {
|
||||||
@@ -608,7 +608,7 @@ function startServer() {
|
|||||||
return res.status(403).json({ error: 'Unauthorized!' });
|
return res.status(403).json({ error: 'Unauthorized!' });
|
||||||
}
|
}
|
||||||
// setup Join URL
|
// setup Join URL
|
||||||
let joinURL = api.getJoinURL(req.body);
|
const joinURL = api.getJoinURL(req.body);
|
||||||
res.json({ join: joinURL });
|
res.json({ join: joinURL });
|
||||||
// log.debug the output if all done
|
// log.debug the output if all done
|
||||||
log.debug('MiroTalk get join - Authorized', {
|
log.debug('MiroTalk get join - Authorized', {
|
||||||
@@ -618,6 +618,35 @@ function startServer() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// request token endpoint
|
||||||
|
app.post([restApi.basePath + '/token'], (req, res) => {
|
||||||
|
// Check if endpoint allowed
|
||||||
|
if (restApi.allowed && !restApi.allowed.token) {
|
||||||
|
return res.status(403).json({
|
||||||
|
error: 'This endpoint has been disabled. Please contact the administrator for further information.',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// check if user was authorized for the api call
|
||||||
|
const { host, authorization } = req.headers;
|
||||||
|
const api = new ServerApi(host, authorization);
|
||||||
|
if (!api.isAuthorized()) {
|
||||||
|
log.debug('MiroTalk get token - Unauthorized', {
|
||||||
|
header: req.headers,
|
||||||
|
body: req.body,
|
||||||
|
});
|
||||||
|
return res.status(403).json({ error: 'Unauthorized!' });
|
||||||
|
}
|
||||||
|
// Get Token
|
||||||
|
const token = api.getToken(req.body);
|
||||||
|
res.json({ token: token });
|
||||||
|
// log.debug the output if all done
|
||||||
|
log.debug('MiroTalk get token - Authorized', {
|
||||||
|
header: req.headers,
|
||||||
|
body: req.body,
|
||||||
|
token: token,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// SLACK API
|
// SLACK API
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|||||||
@@ -28,49 +28,46 @@ module.exports = class ServerApi {
|
|||||||
const { room, roomPassword, name, audio, video, screen, notify, token } = data;
|
const { room, roomPassword, name, audio, video, screen, notify, token } = data;
|
||||||
|
|
||||||
const roomValue = room || uuidV4();
|
const roomValue = room || uuidV4();
|
||||||
const roomPasswordValue = roomPassword || false;
|
|
||||||
const nameValue = name || 'User-' + this.getRandomNumber();
|
const nameValue = name || 'User-' + this.getRandomNumber();
|
||||||
|
const roomPasswordValue = roomPassword || false;
|
||||||
const audioValue = audio || false;
|
const audioValue = audio || false;
|
||||||
const videoValue = video || false;
|
const videoValue = video || false;
|
||||||
const screenValue = screen || false;
|
const screenValue = screen || false;
|
||||||
const notifyValue = notify || false;
|
const notifyValue = notify || false;
|
||||||
|
const jwtToken = token ? '&token=' + this.getToken(token) : '';
|
||||||
|
|
||||||
let jwtToken = '';
|
const joinURL =
|
||||||
|
|
||||||
if (token) {
|
|
||||||
// JWT.io
|
|
||||||
const { username, password, presenter, expire } = token;
|
|
||||||
|
|
||||||
const usernameValue = username || 'username';
|
|
||||||
const passwordValue = password || 'password';
|
|
||||||
const presenterValue = String(presenter);
|
|
||||||
const expireValue = expire || JWT_EXP;
|
|
||||||
|
|
||||||
jwtToken =
|
|
||||||
'&token=' +
|
|
||||||
jwt.sign({ username: usernameValue, password: passwordValue, presenter: presenterValue }, JWT_KEY, {
|
|
||||||
expiresIn: expireValue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
'https://' +
|
'https://' +
|
||||||
this._host +
|
this._host +
|
||||||
'/join?room=' +
|
'/join?' +
|
||||||
roomValue +
|
`room=${roomValue}` +
|
||||||
'&roomPassword=' +
|
`&roomPassword=${roomPasswordValue}` +
|
||||||
roomPasswordValue +
|
`&name=${encodeURIComponent(nameValue)}` +
|
||||||
'&name=' +
|
`&audio=${audioValue}` +
|
||||||
nameValue +
|
`&video=${videoValue}` +
|
||||||
'&audio=' +
|
`&screen=${screenValue}` +
|
||||||
audioValue +
|
`¬ify=${notifyValue}` +
|
||||||
'&video=' +
|
jwtToken;
|
||||||
videoValue +
|
|
||||||
'&screen=' +
|
return joinURL;
|
||||||
screenValue +
|
}
|
||||||
'¬ify=' +
|
|
||||||
notifyValue +
|
getToken(token) {
|
||||||
jwtToken
|
if (!token) return '';
|
||||||
);
|
|
||||||
|
const { username = 'username', password = 'password', presenter = false, expire } = token;
|
||||||
|
|
||||||
|
const expireValue = expire || JWT_EXP;
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
username: String(username),
|
||||||
|
password: String(password),
|
||||||
|
presenter: String(presenter),
|
||||||
|
};
|
||||||
|
|
||||||
|
const jwtToken = jwt.sign(payload, JWT_KEY, { expiresIn: expireValue });
|
||||||
|
|
||||||
|
return jwtToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRandomNumber() {
|
getRandomNumber() {
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ module.exports = {
|
|||||||
meetings: false,
|
meetings: false,
|
||||||
meeting: true,
|
meeting: true,
|
||||||
join: true,
|
join: true,
|
||||||
|
token: true,
|
||||||
//...
|
//...
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mirotalksfu",
|
"name": "mirotalksfu",
|
||||||
"version": "1.3.75",
|
"version": "1.3.76",
|
||||||
"description": "WebRTC SFU browser-based video calls",
|
"description": "WebRTC SFU browser-based video calls",
|
||||||
"main": "Server.js",
|
"main": "Server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -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 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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.3.75
|
* @version 1.3.76
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
* @license For commercial or closed source, contact us at license.mirotalk@gmail.com or purchase directly via CodeCanyon
|
* @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
|
* @license CodeCanyon: https://codecanyon.net/item/mirotalk-sfu-webrtc-realtime-video-conferences/40769970
|
||||||
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
* @author Miroslav Pejic - miroslav.pejic.85@gmail.com
|
||||||
* @version 1.3.75
|
* @version 1.3.76
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم