OAuth2 & installation
Status
Stable· Last verified 2026-07-11 · APIv10· Sources OAuth2, User-installable app tutorial
OAuth2 is how apps get authorized and installed, and how you act on behalf of a user. It is orthogonal to webhooks/bots/interactions — it’s the front door.
In this section
Section titled “In this section”| Page | What it covers |
|---|---|
| This overview | The two things OAuth2 does, common scopes, installation contexts |
| Authorization-code flow | The server-side “Login with Discord” flow, with token refresh, revocation, and error handling |
| Scopes catalogue | Every documented scope, its grant, and its access tier |
| Other grants | Client-credentials, implicit, and the verified PKCE status |
| Linked Roles | Role connection metadata for role gating |
Runnable examples:
oauth2-login
(authorization-code flow + refresh/revoke) and
oauth2-linked-roles
(role connection metadata) — both with unit tests you can run without secrets.
Two things OAuth2 does
Section titled “Two things OAuth2 does”- Authorize a user — “Login with Discord”: the user grants your app scopes, and you receive tokens to call the API as/for them (e.g. read their profile or guild list).
- Install your app — add the app (and optionally its bot) to a server or to a user, granting the scopes your app needs to function.
Scopes (request the minimum)
Section titled “Scopes (request the minimum)”Common scopes:
| Scope | Grants |
|---|---|
identify |
Basic profile (id, username, avatar) — not email |
email |
The user’s email address |
guilds |
List of guilds the user is in |
guilds.join |
Add the user to a guild (with a bot present) |
applications.commands |
Install your app’s commands (required for user-installs) |
bot |
Add a bot user to a guild (guild-install) |
connections |
The user’s linked accounts |
Ask only for what a feature needs. email and guilds are sensitive; bot
should pair with a least-privilege permission bitfield, never Administrator.
The authorization-code flow (server-side)
Section titled “The authorization-code flow (server-side)”1. Send the user to /oauth2/authorize?client_id=…&scope=…&redirect_uri=…&response_type=code&state=…2. User approves → Discord redirects to your redirect_uri with ?code=…&state=…3. Your SERVER exchanges the code at /oauth2/token (client_id + client_secret) → access_token (+ refresh_token)4. Call the API with Authorization: Bearer <access_token>5. Refresh with the refresh_token before expiry- The code→token exchange uses your
client_secretand must happen server-side — never expose the secret to a browser or mobile app. - Always send and validate a
stateparameter to prevent CSRF.
Installation contexts (user-install vs guild-install)
Section titled “Installation contexts (user-install vs guild-install)”Modern apps declare where they can be installed:
| Context | Value | Meaning | Default scope |
|---|---|---|---|
| Guild install | GUILD_INSTALL (0) |
Added to a specific server; its members use it there | applications.commands + often bot |
| User install | USER_INSTALL (1) |
Installed to a user; commands follow them across servers and DMs | applications.commands |
A user-installed app’s commands work even in servers where the app isn’t a member — a big shift from the classic “add the bot to the server” model. See the user-installable app tutorial.
Knowing which context an interaction came from
Section titled “Knowing which context an interaction came from”Interactions include authorizing_integration_owners (and the interaction
context), telling you which install(s) apply:
- For a user install, the key is
"1"and the value is the ID of the user who authorized the app. - For a guild install, the key is
"0"and the value is the guild ID.
Use this to tailor behavior and to enforce that a command runs only where it should.
Common mistakes
Section titled “Common mistakes”- Exposing
client_secretin front-end code — it belongs only on your server. - Requesting
bot+ Administrator for convenience — request a minimal permission bitfield instead. - Assuming a user-installed command has a guild context — it may run in a DM or
a server where your bot isn’t present; check
context/authorizing_integration_owners. - Forgetting
state(CSRF) or not validating theredirect_uri.
- Create the app + secret → Create an app.
- Add commands that respect install context → Interactions.
- Keep the secret safe → Security.