Documentation

SSO

Discord

Add Discord sign-in to VitNode. Create an application, register the redirect URL and wire up the Discord SSO adapter in your API config.

Discord is one of the quickest providers to set up, because nothing waits on a review or a publish step. Create an application, add one redirect URL and copy two values.

Before you begin

Set up the application

Sign in to the Discord Developer Portal

Go to the Discord Developer Portal and sign in with the Discord account that should own the application.

Create a new application

Press New Application, give it the name visitors will see on the authorization screen, and accept the terms.

Add the redirect URL

Open OAuth2 in the left navigation and, under Redirects, press Add Redirect. Paste the URI for the origin you are running and save.

VitNode builds this URI from VITNODE_WEB_URL, so it has to match exactly, with no trailing slash and no locale prefix.

EnvironmentRedirect URL
Development (VITNODE_WEB_URL unset)http://localhost:3000/login/sso/discord
Productionhttps://your-domain.com/login/sso/discord

Add both entries so one application covers local development and your live site.

Invalid OAuth2 redirect_uri

Discord rejects the authorization request outright if the URL is not in this list, before the visitor sees anything. If pressing the button lands you on a Discord error page rather than an authorization prompt, this is why.

Copy the client ID and secret

Still on the OAuth2 page, the Client ID and Client Secret are in the client information block at the top. Discord shows the secret once, so press Reset Secret if it was never revealed or you have lost it.

Set the environment variables

These are server-side variables, so leave them out of clientEnv. That list publishes a value to the browser bundle, and a client secret in the browser bundle is a client secret you have published.

.env
DISCORD_CLIENT_ID=1234567890123456789
DISCORD_CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Add the adapter

Add DiscordSSOApiPlugin to authorization.ssoAdapters in the API's vitnode.api.config.ts (where it lives), next to any adapters you already have. Keep the rest of the config as it is:

src/vitnode.api.config.ts (excerpt)
import { DiscordSSOApiPlugin } from '@vitnode/core/api/adapters/sso/discord'
import { buildApiConfig } from '@vitnode/core/vitnode.config'

export const vitNodeApiConfig = buildApiConfig({
  // ...
  authorization: {
    ssoAdapters: [
      // ...
      DiscordSSOApiPlugin({
        clientId: process.env.DISCORD_CLIENT_ID,
        clientSecret: process.env.DISCORD_CLIENT_SECRET,
      }),
    ],
  },
})

No authorization block yet? Create one with just ssoAdapters, as in the SSO setup. Then restart the dev server, since .env and the API config are only read at start-up.

Check the result

Open /login in a private window and press the Discord button under Continue with. You should see Discord's "connect to" authorization prompt listing your username and email, get bounced back to /login/sso/discord?code=...&state=..., and land on the front page signed in.

What the adapter asks Discord for

Useful when you are debugging an authorization prompt that lists the wrong permissions.

SettingValue
Authorize URLhttps://discord.com/oauth2/authorize
Token URLhttps://discord.com/api/oauth2/token
Profile URLhttps://discord.com/api/users/@me
Scopesidentify email
Provider iddiscord
Fields readid, email, verified, username, avatar

Both scopes are required: identify for the id and username, email for the address the account is created with.

The avatar hash becomes https://cdn.discordapp.com/avatars/{id}/{avatar}.png?size=512, which Connected accounts can import. A member still on Discord's default avatar has none. Discord has no first or last name, and VitNode doesn't guess one from username or global_name, so only the avatar is offered.

Gotchas

An account with no email cannot sign in

The adapter requires email in Discord's profile response and answers 400 when it is absent. That happens if the email scope is dropped, or if the Discord account has no address on it. The visitor sees the generic error screen.

Unverified Discord emails are refused

The adapter reads Discord's verified field and answers 400 when it is false, so a Discord account with an unconfirmed address cannot sign in until it confirms the address in Discord. The visitor sees the generic error screen.

A missing key fails on click, not on boot

A DiscordSSOApiPlugin whose clientId is undefined registers happily. The button renders, the provider is listed, and it throws Missing Discord client ID the moment somebody presses it. A button that only raises an error toast is an environment problem, not a portal problem.