I have a webpage that uses peerjs to create a WebRTC connection. It works fine when using their cloud server.
I then use coturn as the iceServer. This works fine when setting static user credentials in the turnserver.conf like this:
user=testuser:userpass123
But now I want to use the coturn-credential-api to generate credentials for the coturn server to prevent abuse.
The relevant client-side JS looks like this:
function getId() {
var myName = getById("myId").value.toLowerCase();
const params = {
username: myName,
key: "SwPBy4UApcrPQEfBC6lRltkg",
};
const options = {
method: "POST",
body: new URLSearchParams(params)
};
fetch("https://example.com/creds/", options)
.then((response) => response.json())
.then((data) => {
console.log(data);
peer = new Peer(myName, {
host: "eulawiki.org",
port: 8999,
key:params.key,
secure: true,
path: "/myapp",
config: {
iceServers: [
{
urls: "stun:example.com:3478", // Replace with your TURN server URL
},
{
urls: "turn:example.com:3478?transport=upd", // Replace with your TURN server URL
username: data.username, // Replace with your TURN username
credential: data.password // Replace with your TURN credential
},
{
urls: "turn:example.com:3478?transport=tcp", // Replace with your TURN server URL
username: data.username, // Replace with your TURN username
credential: data.password // Replace with your TURN credential
},
{
urls: "turn:example.com:5349?transport=upd", // Replace with your TURN server URL
username: data.username, // Replace with your TURN username
credential: data.password // Replace with your TURN credential
},
{
urls: "turn:example.com:5349?transport=tcp", // Replace with your TURN server URL
username: data.username, // Replace with your TURN username
credential: data.password // Replace with your TURN credential
}
]
}
});
Relevant lines of turnserver.conf are:
listening-port=3478
tls-listening-port=5349
use-auth-secret
static-auth-secret=mySecret
cert=/etc/turnserver/fullchain.pem
pkey=/etc/turnserver/privkey.pem
“mySecret” here matches this line: define('TURN_AUTH_SECRET', "__SECRET__");
in the credentials API config.inc.php file
With the iceServers defined like that (ie, trying to connect to my coturn server), a user can authenticate and log on to the server. The response data from the fetch is correct:
{
"username": "1735261606:jim",
"password": "iJCfRJe/cbbYi4vayBfh7F6Uwgw=",
"ttl": 1735261606
}
But when you attempt to connect to another peer using peerjs’
var conn = peer.connect(getById("peerId").value.toLowerCase(), {
reliable: true
});
I get the following error in Chrome:
Uncaught InvalidAccessError: Failed to construct 'RTCPeerConnection': Both username and credential are required when the URL scheme is "turn" or "turns"
and a similar one in Firefox:
Uncaught DOMException: RTCPeerConnection constructor passed invalid RTCConfiguration - missing username:
This isn’t a firewall or connectivity issue – Trickle Ice works as expected using either port 3478 or 5349 to test the coturn server. I can see in the peerjs server when the clients connect with their correct IDs. The only place where it breaks is when I specify the coturn server as the iceServer and try to use the REST API – if I leave the static credentials it connects fine