Discord OAuth2 Authentication: Complete Implementation Guide
A production‑ready walkthrough for implementing "Login with Discord": app setup, building the authorization URL, securely exchanging codes for tokens, fetching user data, integrating with NextAuth, and avoiding common errors. This post focuses on the Authorization Code flow for server‑rendered web apps.
Table of Contents
Overview: Login vs Add‑to‑Server
Login with Discord (User OAuth2)
- Scopes like identify, email, guilds.
- Users authenticate and your app fetches their profile.
- Best for dashboards, portals, and account linking.
Add to Server (Bot Authorization)
- Scopes bot and often applications.commands.
- Requires a permissions integer; optional guild_id & disable_guild_select.
- Separate from user login. Only include if onboarding a bot.
Developer Portal Setup
- Open the Discord Developer Portal and create an application.
- Under OAuth2 → Redirects, add your callback URL exactly (dev and prod). Example:
http://localhost:3000/api/auth/callback/discord
or your domain. - Copy your Client ID and generate a Client Secret. Keep the secret server‑side only.
Exchange Code for Tokens
After callback, exchange the code
for an access token at Discord's token endpoint.
Keep the client secret server‑side. Do not perform token exchange in the browser for web apps.
Fetch the Current User
Use the access token to call /users/@me
and optionally /users/@me/guilds
if you requested guilds
.
Refresh & Revoke Tokens
Refresh
To refresh, POST to the token endpoint with the refresh token.
Revoke
To revoke, POST to the revoke endpoint with the token you want to invalidate.
Note: Some libraries handle refresh and revoke for you. For public SPA/native apps, prefer a backend for token exchange/storage.
NextAuth Integration (Next.js)
If you are on Next.js, next-auth
has a Discord provider that wires up the flow and sessions.
Sign‑in path defaults to /api/auth/signin
; callback defaults to /api/auth/callback/discord
. Align your Redirect in the Developer Portal accordingly.
Common Errors & Fixes
Authorization Phase
- invalid_redirect_uri: Redirect must match exactly, including protocol, hostname, path, and trailing slash.
- state mismatch: Generate a CSRF state, store it (cookie/session), and verify on callback.
Token/User Phase
- invalid_grant: The code is expired or already used; ensure single use and correct redirect URI.
- 401 Unauthorized: Missing/invalid Bearer token; check token type and header.
Security Notes
- Keep client secrets off the client; exchange tokens on the server.
- Request minimal scopes; explain why you need each.
- Handle 429s per Discord Rate Limits.
Authenticate users, then grow faster
List your bot on Rank.top for discovery, analytics, and passive vote revenue. When you need more reach, add tasteful ads.