@l7mp/stunner-auth-lib
Version:
STUN/TURN credentials generation for STUNner
249 lines (200 loc) • 10.3 kB
Markdown
# /stunner-auth-lib
A library to generate ICE configuration and TURN credentials for the [STUNner Kubernetes ingress
gateway for WebRTC](https://github.com/l7mp/stunner).
```javascript
const auth = require('/stunner-auth-lib');
var credentials = auth.getStunnerCredentials({
auth_type: 'longterm',
secret: 'my-shared-secret',
duration: 24*60*60, // credentials valid for one day
});
```
## Installation
Install from NPM.
```console
npm install /stunner-auth-lib
```
## Usage
<!-- This library simplifies generating STUN/TURN credentials and ICE server configuration for accessing -->
<!-- the [STUNner Kubernetes ingress gateway for WebRTC ](https://github.com/l7mp/stunner) from WebRTC -->
<!-- clients. -->
The intended use is to ease the generation of STUN/TURN credentials and ICE server configuration
stanza in the WebRTC application server. The application server can send these back to the WebRTC
clients during the WebSocket/JSON call setup process. Clients can then use the STUN/TURN
credentials and ICE server configuration received from the application server to authenticate with
STUNner, in order to reach the WebRTC media plane deployed into Kubernetes behind STUNner.
The library will automatically parse the current STUNner configuration from the Kubernetes control
plane if available. Otherwise, it falls back to taking configuration from environment variables.

### Configuration
The library depends on a valid STUNner configuration for generating STUN/TURN credentials, which is
typically generated by the [STUNner Kubernetes Gateway
Operator](https://github.com/l7mp/stunner-gateway-operator). The STUNner configuration is rendered
into a [Kubernetes
ConfigMap](https://github.com/l7mp/stunner-gateway-operator/README.md#configure-the-operator),
which is then picked up by the [STUNner dataplane](https://github.com/l7mp/stunner) to ingest
WebRTC media into the Kubernetes cluster. Suppose that this ConfigMap is named `stunnerd-config`
(this is the default name). The below Kubernetes pod template snippet shows how to map this
configuration into your WebRTC application server.
``` yaml
...
spec:
containers:
- name: <my-application-server>
image: <my-application-server-image>
...
env:
- name: STUNNER_CONFIG_FILENAME
value: "/etc/stunnerd/stunnerd.conf"
volumeMounts:
- name: stunnerd-config-volume
mountPath: /etc/stunnerd
readOnly: true
...
volumes:
- name: stunnerd-config-volume
configMap:
name: stunnerd-config
...
```
From this point, the STUNner configuration, as actually existing in the `stunnerd-config`
ConfigMap, will be mapped into the application server pod's filesystem under the path
`/etc/stunnerd/stunnerd.conf` and the full path will be available in the `STUNNER_CONFIG_FILENAME`
environment variable. The library will pick up this configuration and use it to generate the
STUN/TURN credentials and full ICE server configurations necessary to reach STUNner.
Every time you change the STUNner configuration through the [Kubernetes Gateway
API](https://github.com/l7mp/stunner-gateway-operator/README.md#configure-the-operator), the new
configuration will be immediately mapped into the filesystem of your application server. When
called, the library will re-parse the active configuration from the filesystem and the new settings
will immediately take effect: new client requests will receive up-to-date STUN/TURN
credentials.
If no valid configuration file is found, the library falls back to the [standalone
mode](README.md#fallback-to-standalone-mode).
### Generating ICE configuration
The recommended usage is generating the [ICE
configuration](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) along with the
STUNner credentials in a single step and sending it back the WebRTC clients during call setup.
* Generate a full [ICE configuration
object](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) on
the [WebRTC application server](https://bloggeek.me/webrtc-server).
```javascript
const auth = require('/stunner-auth-lib');
...
var ICE_config = auth.getIceConfig();
console.log(ICE_config);
```
Output:
```javascript
{
iceServers: [
{
url: 'turn:1.2.3.4:3478?transport=udp',
username: 'my-user',
credential: 'my-password'
}
],
iceTransportPolicy: 'relay'
}
```
* Send the generated ICE configuration back to the clients during the WebSocket/JSON call setup process
(e.g., during user registration) and use this configuration in the clients to initialize the WebRTC
[`PeerConnection`](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection).
```javascript
var ICE_config = ...; // read ICE configuration from the WebSocket/JSON connection
var pc = new RTCPeerConnection(ICE_config);
```
You can override the path to the STUNner configuration file (and other options) when calling the
function.
```javascript
var ICE_config = auth.getIceConfig({config_file: <MY_STUNNER_CONFIG_FILENAME>});
```
### Generating STUN/TURN credentials
Alternatively, you can simply generate a new STUN/TURN long-term credentials that you can use for
authenticating with STUNner.
```javascript
var cred = auth.getStunnerCredentials({
duration: 24 * 60 * 60, // lifetime the longterm credential is effective
});
console.log(`STUNner credentials: ${cred.username} / ${cred.credential}`);
```
Output:
```
STUNner credentials: 1652118264 / nRU+Iz2ENeP2Y3sDXzSRsFRDs8s=
```
### Fallback to standalone mode
Some may favor running STUNner in the [standalone mode](https://github.com/l7mp/stunner) in order
to be able to manually customize the STUNner dataplane instead of relying on the operator to render
the configuration. The library automatically falls back to using the standalone mode when no
configuration file is available under the path specified by the `STUNNER_CONFIG_FILENAME`
environment variable. For this, the application server needs to have access to the following
environment variables.
* `STUNNER_PUBLIC_ADDR` (no default, must be
[customized](https://github.com/l7mp/stunner#learning-the-external-ip-and-port)): STUNner public
IP address.
* `STUNNER_PUBLIC_PORT` (default: 3478): STUNner public port.
* `STUNNER_REALM` (default: `stunner.l7mp.io`): STUN/TURN realm.
* `STUNNER_AUTH_TYPE` (default: `plaintext`): [STUNner authentication
mode]((https://github.com/l7mp/stunner/tree/main/doc/AUTH.md)); either `plaintext` or `longterm`.
* `STUNNER_USERNAME` (default: `user`):
[username](https://www.rfc-editor.org/rfc/rfc8489.html#section-14.3) for `plaintext`
authentication.
* `STUNNER_PASSWORD` (default: `pass`): password for `plaintext` authentication.
* `STUNNER_SHARED_SECRET` (default: `secret`): the shared secret for `longterm` authentication.
For most configuration parameters the library specifies sane defaults, which can be overridden by
the environment variables (i.e., the STUNner configuration), which can in turn be further
overridden in the function arguments specified on the library calls.
The below code will generate a full [ICE configuration
object](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer) in the fallback mode using
the specified overrides.
```javascript
const auth = require('/stunner-auth-lib');
...
var ICE_config = auth.getIceConfig({
address: '1.2.3.4', // ovveride STUNNER_PUBLIC_ADDR
port: 3478, // ovveride STUNNER_PUBLIC_PORT
auth_type: 'plaintext', // override STUNNER_AUTH_TYPE
username: 'my-user', // override STUNNER_USERNAME
password: 'my-password', // override STUNNER_PASSWORD
ice_transport_policy: 'relay', // override STUNNER_ICE_TRANSPORT_POLICY
});
console.log(ICE_config);
```
The below will generate a new set of STUN/TURN long-term credentials, again using manual overrides.
```javascript
var cred = auth.getStunnerCredentials({
auth_type: 'longterm', // override STUNNER_AUTH_TYPE
secret: 'my-secret', // override STUNNER_SHARED_SECRET
duration: 24 * 60 * 60, // lifetime the longterm credential is effective
});
console.log(`STUNner credentials: ${cred.username} / ${cred.credential}`);
```
Output:
```
STUNner credentials: 1652118264 / nRU+Iz2ENeP2Y3sDXzSRsFRDs8s=
```
Note that all manual overrides are available in the default mode as well.
### Caveats
* In order for the library to be able to read the STUNner configuration, the corresponding
ConfigMap (i.e., `stunnerd-config`) and the application server must live in the same Kubernetes
namespace (Kubernetes does not allow a ConfigMap to be mapped into a pod that exists in a
different namespace). See the [STUNner
examples](https://github.com/l7mp/stunner/examples/README.md) on how to configure the [STUNner
Kubernetes Gateway Operator](https://github.com/l7mp/stunner-gateway-operator) to render the
configuration into an arbitrary namespace from where your application server can pick it up.
* If you change the STUNner credentials from the Kubernetes Gateway API then active clients, which
have already received an ICE configuration that is now being rendered invalid by your change,
will need to go through the authentication process (receive a new ICE configuration, re-request
TURN permissions again from STUNner, etc.) again. Otherwise, they will time out on the next TURN
permission refresh cycle. Currently it is the responsibility of the application server to
orchestrate this process. As a rule of thumb, try to avoid resetting the authentication settings
when active users are authenticated with STUNner.
## Help
STUNner development is coordinated in Discord, send
[us](https://github.com/l7mp/stunner/blob/main/AUTHORS) an email to ask an invitation.
## License
Copyright 2021-2022 by its authors. Some rights reserved. See
[AUTHORS](https://github.com/l7mp/stunner/blob/main/AUTHORS).
MIT License - see [LICENSE](/LICENSE) for full text.
## Acknowledgments
Initial code adopted from
[/turn-credentials](https://www.npmjs.com/package/@rojo2/turn-credentials).