Skip to content

Security: nodecg/docs

Security

docs/security.md

id title sidebar_label
security
Security & Authentication
Security & Authentication

Is NodeCG secure by default? {#security}

No. By default, NodeCG has no authorization or authentication of any kind. To enable basic authentication, see the How do I enable login security? section.

Do not put an unsecured NodeCG instance on the internet or a public network. Unsecured instances should only be used for local development and on trusted LANs.

What levels of authorization does NodeCG have? {#authorization}

NodeCG has a fairly naive permissions model. There are only two permission levels:

  1. Completely unauthorized, with no access to anything
  2. Completely authorized, with full access to everything

This is something we want to improve in the future, but right now this is how things are in NodeCG.

"Full access to everything" includes:

  • Read/write access to every Replicant in every bundle

  • Read/write access to every message in every bundle

  • Read access to the full config of every bundle

    • Your bundle configs may include sensitive API keys and passwords. Every user of your NodeCG deployment will have full access to these config values.

Therefore, untrusted users must never be given any degree of authorization in your NodeCG instance. They must never be allowed to successfully authenticate with the socket server. If they do, they will have full control over your entire NodeCG instance.

How are users authorized? {#authorization-method}

NodeCG has two ways of authorizing a user:

  1. Reading the value of their socketToken cookie.
  2. Reading the value of their key URL query parameter.
    • This is why the "COPY URL" buttons on the "Graphics" tab of the dashboard include a ?key=YOUR_KEY at the end of them. It is necessary for the pages to load successfully in OBS.

Anyone who gets sent a link which includes a key will have full authorization and access to your NodeCG instance. Treat these links with the same secrecy as you would a password, because that's essentially what they are.

What do I do if one of my keys got leaked? {#leak}

  1. Have the owner of the leaked key navigate to the "Settings" tab on the Dashboard.
  2. Click "RESET KEY", and accept the confirmation dialog.

If you are unable to reach the owner of the leaked key:

  1. Shut down your NodeCG instance.
  2. Locate the nodecg/db/nodecg.sqlite3 file.
  3. Open this file using any tool that can open an edit SQLite3 databases, such as DB Browser.
  4. Open the api_key table and delete the row which contains the leaked key.
  5. Restart your NodeCG instance.

In an emergency, you may want to completely delete your database file. The consequences of doing this are that all users will need to log in again and all persisted Replicant values will be lost.

How do I enable login security? {#enable}

NodeCG has support for four authentication providers:

You may have multiple authentication providers enabled simultaneously.

Local Auth {#local-auth}

Configure your nodecg/cfg/nodecg.json as such:

{
    "login": {
        "enabled": true,
        "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
        "local": {
            "enabled": true,
            "allowedUsers": [
                {
                    "username": "example1",
                    "password": "password_example"
                },
                {
                    "username": "example2",
                    "password": "anotherExample-password1234"
                }
            ]
        }
    }
}

Local authentication also support password hashing by using HMAC. In order to use a password hash, fill the password property with the format <type>:<hash> where <type> is the type (SHA-256, RIPEMD, Whirlpool, ...) and <hash> a valid password hash.

For generating a valid password hash, you must use sessionSecret as secret key. If you're looking for a HMAC hash generator, you can use tools like wtools.io for example.

Currently, only native Node.js algorithms are supported.

Example:

{
    "login": {
        "enabled": true,
        "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
        "local": {
            "enabled": true,
            "allowedUsers": [
                {
                    "username": "admin",
                    "password": "sha256:ac679e332d4eee340b74eb0581225686f2736d58df7ea30c87a0d2cd5bfd1329"
                },
                {
                    "username": "other_admin",
                    "password": "ripemd:6f00f0c4c18fb563921b689876e98b61"
                }
            ]
        }
    }
}

Twitch Auth {#twitch-auth}

  1. Create a new application on your Twitch Developer Dashboard
  2. Give it whatever values you want for Name, Category, and Other Details
  3. Set the OAuth Redirect URL to https://YOUR_DEPLOYMENT_URL/login/auth/twitch.
    • If you're testing locally, use http://localhost:9090/login/auth/twitch
  4. Save your Client ID for the next step
  5. Click "New Secret", and save your client secret for the next step
  6. Configure your nodecg/cfg/nodecg.json as such:
{
    "login": {
        "enabled": true,
        "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
        "twitch": {
            "enabled": true,
            "clientID": "YOUR_TWITCH_APP_CLIENT_ID",
            "clientSecret": "YOUR_TWITCH_APP_CLIENT_SECRET",
            "scope": "user:read:email",
            "allowedUsernames": [
                "your_twitch_username",
                "other_twitch_username",
                "can_have_as_many_as_you_want"
            ],
            "allowedIds": [
                "your_twitch_id",
                "other_twitch_id",
                "can_have_as_many_as_you_want"
            ]
        }
    }
}

Discord Auth {#discord-auth}

You can use two different kinds of authentication, by user or by server. You can use one of them or both (in which case matching one of them will grant access).

By user {#discord-user}

  1. Create a new application on your Discord Developer Dashboard

  2. Give it whatever value you want for the Name

  3. Click on OAuth2 on the left and Set the OAuth Redirect URL to https://YOUR_DEPLOYMENT_URL/login/auth/discord.

    • If you're testing locally, use http://localhost:9090/login/auth/discord
  4. Use the Client ID and Client Secret from general information for your configuration

  5. Configure your nodecg/cfg/nodecg.json like below

To get a Discord user ID, enable Discord developer mode and then right click on a user to copy it.

{
    "login": {
        "enabled": true,
        "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
        "discord": {
            "enabled": true,
            "clientID": "YOUR_DISCORD_APP_CLIENT_ID",
            "clientSecret": "YOUR_DISCORD_APP_CLIENT_SECRET",
            "scope": "identify",
            "allowedUserIDs": [
                "paste discord user ids you want to allow here",
                "they look like this",
                "159600065017675778",
                "54561421005950976"
            ]
        }
    }
}

By Server (Guild) {#discord-server}

  1. Create a new application on your Discord Developer Dashboard

  2. Give it whatever value you want for the Name

  3. Use the Client ID and Client Secret from general information for your configuration

  4. Click on OAuth2 on the left and Set the OAuth Redirect URL to https://YOUR_DEPLOYMENT_URL/login/auth/discord.

    • If you're testing locally, use http://localhost:9090/login/auth/discord
  5. Configure your nodecg/cfg/nodecg.json like below

Any user in the server will be allowed to use nodecg.

If you want to check for roles and not just server membership, you also need to do the following: 5. Click on Bot on the left, add a bot, then use the token for your configuration 6. Go to https://discord.com/oauth2/authorize?client_id={YOUR_CLIENT_ID_HERE}&scope=bot&permissions=0 (insert your Client ID) and invite the Bot to servers that you want to use for authentication (the bot will always display as offline, this is normal)

To get a Discord server ID, enable Discord developer mode and then right click on a server to copy it. To get a Discord role ID, enable Discord developer mode and then right click on a role to copy it.

{
  "login": {
    "enabled": true,
    "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
    "discord": {
      "enabled": true,
      "clientID": "YOUR_DISCORD_APP_CLIENT_ID",
      "clientSecret": "YOUR_DISCORD_APP_CLIENT_SECRET",
      "scope": "identify guilds",
      "allowedGuilds": [
        // Use this to allow all members to log in
        {
          "guildID": "paste a server id here to allow all members to log in"
        },
        // Use this to restrict log in for certain roles
        {
          "guildID": "paste a server id here to allow members with one of the roles to log in",
          "allowedRoleIDs": [
            "paste role ids you want to allow here",
            "754751725457637546",
            "755012946400378910"
          ],
          "guildBotToken": "paste your Discord BOT token here"
        }
      ]
    }
  }
}

Steam Auth {#steam-auth}

  1. Create/copy your Steam Web API Key
  2. Obtain the SteamID64 string for each of the accounts you wish to allow.
  3. Configure your nodecg/cfg/nodecg.json as such:
{
    "login": {
        "enabled": true,
        "sessionSecret": "Make this a random string, like one from https://randomkeygen.com/",
        "steam": {
            "enabled": true,
            "apiKey": "YOUR_STEAM_WEB_API_KEY",
            "allowedIds": [
                "paste the SteamId64s you want to allow here",
                "they look like this",
                "76561197974943998"
            ]
        }
    }
}

How do I enable HTTPS/SSL encryption? {#ssl}

  1. Create an SSL certificate if you don't already have one.

    • Creating an SSL cert is out of the scope of this tutorial. You may need to do some Googling if you are unfamiliar with this process.
  2. Configure your nodecg/cfg/nodecg.json as such (passphrase is only required if you created your key with one):

  3. Restart NodeCG, and confirm that your instance is accessible via HTTPS.

{
    "ssl": {
        "enabled": true,
        "keyPath": "C:\\example\\path\\your-cert-key.key",
        "certificatePath": "C:\\example\\path\\your-cert.crt",
        "passphrase": "this is my example passphrase"
    }
}

There aren’t any published security advisories