Skip to content

Discord (OIDC)

This guide walks through running DiscoPanel with Discord as an OIDC identity provider. Discord supports OpenID Connect natively — no IdP container is needed.

  • Docker and Docker Compose
  • A Discord account
  1. Go to the Discord Developer Portal — Applications

  2. Click New Application, give it a name, and save

  3. In the left sidebar, click OAuth2

  4. Under Redirects, click Add Redirect and enter http://localhost:8080/api/v1/auth/oidc/callback

    • For production: use your public URL with HTTPS, e.g. https://panel.example.com/api/v1/auth/oidc/callback
  5. Copy the Client ID and Client Secret (click “Reset Secret” if you don’t have one yet)

Paste your Client ID and Client Secret into the compose file, then start the stack:

Terminal window
cd oidc/discord
docker compose up -d
oidc/discord/docker-compose.yaml
# DiscoPanel + Discord (OIDC)
#
# This is a complete docker-compose with OIDC authentication pre-configured using Discord as the identity provider.
#
# Unlike Keycloak/Authelia examples, Discord is an external provider - no IdP container needed.
#
# PREREQUISITES:
# 1. Go to https://discord.com/developers/applications
# 2. Create or select an application
# 3. Go to "OAuth2" in the left sidebar
# 4. Copy the Client ID and Client Secret into the environment variables below
# 5. Under "Redirects", add: http://localhost:8080/api/v1/auth/oidc/callback
#
# RESTRICTING ACCESS:
# By default, anyone with a Discord account can log in.
# To restrict login to members of a specific Discord server, see the
# "Guild restriction" and "Role mapping" sections below.
services:
discopanel:
build:
context: ../../
dockerfile: docker/Dockerfile.discopanel
#image: nickheyer/discopanel:dev
container_name: discopanel
restart: unless-stopped
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /tmp/discopanel:/app/data
environment:
- DISCOPANEL_DATA_DIR=/app/data
- DISCOPANEL_HOST_DATA_PATH=/tmp/discopanel
- TZ=UTC
# ------------------------------------ AUTH CONFIG STARTS HERE FOR DISCOPANEL + DISCORD ------------------------------------
- DISCOPANEL_AUTH_LOCAL_ENABLED=true
- DISCOPANEL_AUTH_OIDC_ENABLED=true
# DISCORD OIDC ISSUER - DO NOT CHANGE
- DISCOPANEL_AUTH_OIDC_ISSUER_URI=https://discord.com
# PASTE YOUR DISCORD OAUTH CLIENT ID HERE (from Discord Developer Portal)
- DISCOPANEL_AUTH_OIDC_CLIENT_ID=REPLACE_ME
# PASTE YOUR DISCORD OAUTH CLIENT SECRET HERE (from Discord Developer Portal)
- DISCOPANEL_AUTH_OIDC_CLIENT_SECRET=REPLACE_ME
# Discord requires "openid", "identify", and "email" for basic OIDC login.
# Add "guilds" if you want to restrict access to a specific server (see below).
# Add "guilds.members.read" if you also want to map Discord server roles.
- DISCOPANEL_AUTH_OIDC_SCOPES=openid,identify,email
# THIS MUST MATCH EXACTLY WHAT YOU ENTERED IN DISCORD DEVELOPER PORTAL UNDER "Redirects"
# FOR PRODUCTION: change to your public domain (ie: https://mypanel.com/api/v1/auth/oidc/callback)
- DISCOPANEL_AUTH_OIDC_REDIRECT_URL=http://localhost:8080/api/v1/auth/oidc/callback
# Leave empty to skip automatic role mapping - users get default roles and can be promoted manually.
- DISCOPANEL_AUTH_OIDC_ROLE_CLAIM=
# ------------------------------------ GUILD RESTRICTION (OPTIONAL) ------------------------------------
#
# OPTION A: Restrict to members of a specific Discord server.
# 1. Add "guilds" to SCOPES above → openid,identify,email,guilds
# 2. Uncomment the lines below, replacing YOUR_GUILD_ID with your server's ID
# (enable Developer Mode in Discord, right-click the server → Copy Server ID)
#
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_URL=https://discord.com/api/users/@me/guilds
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_KEY=#.id
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_NAME=guilds
# - DISCOPANEL_AUTH_OIDC_REQUIRED_CLAIM=guilds
# - DISCOPANEL_AUTH_OIDC_REQUIRED_VALUES=YOUR_GUILD_ID
#
# ------------------------------------ ROLE MAPPING (OPTIONAL) ------------------------------------
#
# OPTION B: Restrict to a guild AND map Discord server roles to DiscoPanel roles.
# 1. Add "guilds.members.read" to SCOPES above → openid,identify,email,guilds.members.read
# 2. Install your Discord application in the server (OAuth2 → URL Generator → select "bot" scope → invite)
# 3. Set EXTRA_CLAIMS_URL to the guild member endpoint with your server ID:
#
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_URL=https://discord.com/api/users/@me/guilds/YOUR_GUILD_ID/member
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_KEY=roles
# - DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_NAME=discord_roles
# - DISCOPANEL_AUTH_OIDC_ROLE_CLAIM=discord_roles
# - DISCOPANEL_AUTH_OIDC_ROLE_MAPPING={"DISCORD_ROLE_ID":"admin","OTHER_ROLE_ID":"moderator"}
# - DISCOPANEL_AUTH_OIDC_REJECT_UNMAPPED=true
#
# This also restricts access to guild members — non-members get a 403 from Discord's API.
# To find role IDs: Server Settings → Roles → right-click a role → Copy Role ID
VariablePurpose
DISCOPANEL_AUTH_OIDC_ENABLEDEnables OIDC authentication
DISCOPANEL_AUTH_OIDC_ISSUER_URIAlways https://discord.com — do not change
DISCOPANEL_AUTH_OIDC_CLIENT_IDYour Application ID from the Discord Developer Portal
DISCOPANEL_AUTH_OIDC_CLIENT_SECRETYour Client Secret from the Discord Developer Portal
DISCOPANEL_AUTH_OIDC_REDIRECT_URLThe callback URL — must match exactly what you entered under Redirects
DISCOPANEL_AUTH_OIDC_SCOPESMust include openid, identify, and email. Add guilds or guilds.members.read for server restrictions

Discord’s OIDC tokens don’t include server membership data, but the access token can fetch it from Discord’s API. DiscoPanel supports this through the extra claims mechanism — a generic feature that fetches additional user data from a provider endpoint during login.

Add guilds to your scopes and configure the extra claims to pull guild membership:

- DISCOPANEL_AUTH_OIDC_SCOPES=openid,identify,email,guilds
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_URL=https://discord.com/api/users/@me/guilds
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_KEY=#.id
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_NAME=guilds
- DISCOPANEL_AUTH_OIDC_REQUIRED_CLAIM=guilds
- DISCOPANEL_AUTH_OIDC_REQUIRED_VALUES=YOUR_GUILD_ID

Replace YOUR_GUILD_ID with your Discord server’s ID. To find it: enable Developer Mode in Discord settings, then right-click the server name and select Copy Server ID.

EXTRA_CLAIMS_KEY is a gjson path#.id extracts the id field from each object in the array. The result is stored as the guilds claim, and REQUIRED_CLAIM + REQUIRED_VALUES gate login on whether the guild ID is present.

Users who aren’t in the server will be turned away at login.

If you want login restricted to a server and want Discord roles to translate to DiscoPanel roles, use the guild member endpoint instead. This requires:

  1. Adding guilds.members.read to your scopes
  2. Installing your Discord application in the server (OAuth2 → URL Generator → select bot → use the invite link)
- DISCOPANEL_AUTH_OIDC_SCOPES=openid,identify,email,guilds.members.read
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_URL=https://discord.com/api/users/@me/guilds/YOUR_GUILD_ID/member
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_KEY=roles
- DISCOPANEL_AUTH_OIDC_EXTRA_CLAIMS_NAME=discord_roles
- DISCOPANEL_AUTH_OIDC_ROLE_CLAIM=discord_roles
- DISCOPANEL_AUTH_OIDC_ROLE_MAPPING={"DISCORD_ROLE_ID":"admin","OTHER_ROLE_ID":"moderator"}
- DISCOPANEL_AUTH_OIDC_REJECT_UNMAPPED=true

EXTRA_CLAIMS_KEY=roles pulls the roles array from the member response and stores it as the discord_roles claim. The role mapping then translates Discord role IDs to DiscoPanel roles. REJECT_UNMAPPED=true means users whose Discord roles don’t match any mapping entry are denied login.

Non-members are also rejected — Discord’s API returns a 403 for users who aren’t in the guild.

To find role IDs: go to Server Settings → Roles, right-click a role, and select Copy Role ID (requires Developer Mode).

ServiceURLLogin
DiscoPanelhttp://localhost:8080Log in via Discord
  • Update the redirect URI: change localhost:8080 to your public domain in both the compose file and the Discord Developer Portal
  • HTTPS: Discord allows http://localhost for development, but production deployments should use HTTPS
  • Disable local auth (optional): set DISCOPANEL_AUTH_LOCAL_ENABLED=false if you want OIDC-only login