Separate login from bot installation
Discord OAuth2 lets someone authorize your website to access specific account information. A bot invite is a different use of OAuth2. Start by deciding what the website needs after login.
| Scope | Use | Do you need it for basic login? |
|---|---|---|
| identify | Read the signed-in user’s basic profile | Usually |
| Read the email address when available | Only if the product needs it | |
| guilds | List the user’s servers | For a server-picker or related feature |
| bot / applications.commands | Install a bot or commands | Separate from basic account login |
The examples below illustrate a server-side authorization-code flow. For a framework auth library, use its Discord provider and session handling rather than combining half of this flow with half of another one.
The login flow in five steps
Create a login request
Generate a random state value and save it in the user’s server-side session with a short expiry.Send the user to Discord
Include your client ID, registered redirect URI, requested scopes, and state.Validate the callback
Handle denial, require a code, and compare state with the session value before exchanging anything. Reject missing, expired, or mismatched state and consume it once.Exchange the code on the server
Send the code to Discord’s token endpoint with your client credentials and the same redirect URI.Create your own session
Fetch the user profile, link it to your account record by Discord ID, and issue a secure session cookie.
Register the exact callback address in the Developer Portal. The protocol, host, port, and path matter. See Discord’s OAuth2 reference for the endpoints and supported scopes.
Build the authorization URL
This Node.js fragment assumes session is your framework’s server-side session. Save it before redirecting the browser. Use HTTPS in production.
Validate required environment variables when the application starts. The non-null assertions here keep the fragment short; they are not runtime validation.
Protect the session after login
- Use Secure, HttpOnly cookies with an appropriate SameSite policy.
- Store only the account information and tokens the feature needs.
- Protect stored refresh tokens and update them when Discord returns a replacement.
- Recheck server-management permissions before changing bot settings.
- Never log authorization codes, access tokens, refresh tokens, or client secrets.
login is not authorization
Knowing who someone is does not grant access to every server.
Verify that the signed-in user can manage the selected server before reading or updating its private configuration. Do this on the backend, even if the dashboard hides the controls.
Make failures understandable
A redirect mismatch usually means the configured callback addresses differ. An invalid grant can mean an expired or reused code. A state mismatch should end the attempt and let the user start again.
Handle token expiry and revoked access without looping through failed requests. If continued Discord API access is unnecessary, avoid retaining its tokens after creating your own session.