Skip to content

Commit

Permalink
TURN REST API Credentials
Browse files Browse the repository at this point in the history
Problem
=======

* If I want to use my own TURN/STUN server, this requires generating
  ephemeral credentials, to avoid compromising long-term credentials, as
  those would be exposed in the source code.

Solution
========

* Generate an ephemeral credential server-side, and provide it to each
  client via socket.io connection

Notes
=====

Tested against a local `coturn` server
  • Loading branch information
Vasili Sviridov authored and vsviridov committed Feb 11, 2023
1 parent 88ee374 commit 6d93d39
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ npm start

to start the tlk server on port 3000. Your tlk instance will be running on http://localhost:3000. Alternatively you can run the application using docker with `docker-compose up`.

### How to self host it

In order to self-host it on your dedicated server, Tlk must be exposed on `https` following [this documentation](./docs/self-hosting.md).

You can also expose it quickly on `https` from your local PC or any host using [ngrok](https://ngrok.com/).

### Using TURN REST API Authentication

If you're using `coturn` - set up `use-auth-secret` and provision a secret either via `static-auth-secret` or via `turnadmin -s`

Set up following environment variables:

* `SHARED_SECRET`: This should match the parameter provided to coturn
* `CUSTOM_STUN_SERVER`: `stun:stun.your.domain.name`
* `CUSTOM_TURN_SERVER`: `turn:stun.your.domain.name`
* `CREDENTIAL_LIFETIME`: How long should the credential be valid for (in seconds)

### LICENSE

<a href="https://github.com/vasanthv/tlk/blob/master/LICENSE">MIT License</a>
25 changes: 24 additions & 1 deletion server/signalling-server.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
/*
Note: This socket connection is used a signalling server as WebRTC does not support discovery of other peers.
Note: This socket connection is used a signalling server as WebRTC does not support discovery of other peers.
Your audio, video & chat messages does not use this socket.
*/
const util = require("util");
const { createHmac } = require("crypto");

const { SHARED_SECRET, CUSTOM_STUN_SERVER, CUSTOM_TURN_SERVER } = process.env
const CREDENTIAL_LIFETIME = parseInt(process.env.CREDENTIAL_LIFETIME, 10) || 3600;

function getTurnCredentials(name, secret = SHARED_SECRET, duration = CREDENTIAL_LIFETIME) {
const timestamp = parseInt(Date.now() / 1000) + duration;
const username = `${timestamp}:${name}`;
const hmac = createHmac("sha1", secret);
hmac.setEncoding('base64')
hmac.write(username);
hmac.end();

const credential = hmac.read();
return { username, credential };
}

const channels = {};
const sockets = {};
Expand All @@ -29,6 +45,13 @@ const signallingServer = (socket) => {
console.log("[" + socket.id + "] join ", config);
const channel = socketHostName + config.channel;

if(SHARED_SECRET && CUSTOM_STUN_SERVER && CUSTOM_TURN_SERVER) {
socket.emit('ice_servers', [
{ urls: CUSTOM_STUN_SERVER },
{ urls: CUSTOM_TURN_SERVER, ...getTurnCredentials(config.channel) }
]);
}

// Already Joined
if (channel in socket.channels) return;

Expand Down
7 changes: 6 additions & 1 deletion www/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ function init() {
});
});

signalingSocket.on("ice_servers", function(data) {
console.log('Received ICE Servers', data);
App.ice_servers = data;
});

signalingSocket.on("disconnect", function () {
for (let peer_id in peerMediaElements) {
document.getElementById("videos").removeChild(peerMediaElements[peer_id].parentNode);
Expand All @@ -99,7 +104,7 @@ function init() {
channel = config.channel;
//console.log('[Join] - connected peers in the channel', JSON.stringify(channel, null, 2));

const peerConnection = new RTCPeerConnection({ iceServers: ICE_SERVERS });
const peerConnection = new RTCPeerConnection({ iceServers: App.ice_servers || ICE_SERVERS });
peers[peer_id] = peerConnection;

peerConnection.onicecandidate = function (event) {
Expand Down

0 comments on commit 6d93d39

Please # to comment.