dfx 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitmodules +3 -0
- package/.prettierrc.json +4 -0
- package/DiscordREST/types.ts +5 -0
- package/DiscordWS/index.ts +0 -0
- package/WS/index.ts +122 -0
- package/discord-api-docs/.eslintrc.json +10 -0
- package/discord-api-docs/.gitattributes +11 -0
- package/discord-api-docs/.github/ISSUE_TEMPLATE/api-bug-report.yml +49 -0
- package/discord-api-docs/.github/ISSUE_TEMPLATE/config.yml +20 -0
- package/discord-api-docs/.github/ISSUE_TEMPLATE/developer-site-bug-report.yml +49 -0
- package/discord-api-docs/.github/ISSUE_TEMPLATE/message-components-bug-report.yml +49 -0
- package/discord-api-docs/.github/ISSUE_TEMPLATE/slash-command-bug-report.yml +49 -0
- package/discord-api-docs/.github/workflows/test.yaml +45 -0
- package/discord-api-docs/.prettierignore +1 -0
- package/discord-api-docs/.prettierrc.json +15 -0
- package/discord-api-docs/CODE_OF_CONDUCT.md +75 -0
- package/discord-api-docs/CONTRIBUTING.md +16 -0
- package/discord-api-docs/README.md +35 -0
- package/discord-api-docs/ci/checkLinks.ts +177 -0
- package/discord-api-docs/docs/Change_Log.md +474 -0
- package/discord-api-docs/docs/Intro.md +48 -0
- package/discord-api-docs/docs/Legal.md +154 -0
- package/discord-api-docs/docs/Policy.md +81 -0
- package/discord-api-docs/docs/Reference.md +476 -0
- package/discord-api-docs/docs/Store_Distribution_Agreement.md +179 -0
- package/discord-api-docs/docs/dispatch/Branches_and_Builds.md +654 -0
- package/discord-api-docs/docs/dispatch/Dispatch_and_You.md +17 -0
- package/discord-api-docs/docs/dispatch/Error_Codes.md +26 -0
- package/discord-api-docs/docs/dispatch/Field_Values.md +48 -0
- package/discord-api-docs/docs/dispatch/List_of_Commands.md +315 -0
- package/discord-api-docs/docs/game_and_server_management/Alpha_and_Beta_Testing.md +52 -0
- package/discord-api-docs/docs/game_and_server_management/How_to_Get_Your_Game_on_Discord.md +110 -0
- package/discord-api-docs/docs/game_and_server_management/Special_Channels.md +38 -0
- package/discord-api-docs/docs/game_sdk/Achievements.md +405 -0
- package/discord-api-docs/docs/game_sdk/Activities.md +561 -0
- package/discord-api-docs/docs/game_sdk/Applications.md +237 -0
- package/discord-api-docs/docs/game_sdk/Discord.md +443 -0
- package/discord-api-docs/docs/game_sdk/Discord_Voice.md +289 -0
- package/discord-api-docs/docs/game_sdk/Images.md +196 -0
- package/discord-api-docs/docs/game_sdk/Lobbies.md +1639 -0
- package/discord-api-docs/docs/game_sdk/Networking.md +377 -0
- package/discord-api-docs/docs/game_sdk/Overlay.md +195 -0
- package/discord-api-docs/docs/game_sdk/Relationships.md +234 -0
- package/discord-api-docs/docs/game_sdk/SDK_Starter_Guide.md +310 -0
- package/discord-api-docs/docs/game_sdk/Storage.md +312 -0
- package/discord-api-docs/docs/game_sdk/Store.md +555 -0
- package/discord-api-docs/docs/game_sdk/Users.md +178 -0
- package/discord-api-docs/docs/interactions/Application_Commands.md +1069 -0
- package/discord-api-docs/docs/interactions/Message_Components.md +454 -0
- package/discord-api-docs/docs/interactions/Receiving_and_Responding.md +372 -0
- package/discord-api-docs/docs/interactions/Slash_Commands.md +3 -0
- package/discord-api-docs/docs/resources/Application.md +82 -0
- package/discord-api-docs/docs/resources/Audit_Log.md +223 -0
- package/discord-api-docs/docs/resources/Channel.md +1267 -0
- package/discord-api-docs/docs/resources/Emoji.md +122 -0
- package/discord-api-docs/docs/resources/Guild.md +1157 -0
- package/discord-api-docs/docs/resources/Guild_Scheduled_Event.md +273 -0
- package/discord-api-docs/docs/resources/Guild_Template.md +148 -0
- package/discord-api-docs/docs/resources/Invite.md +150 -0
- package/discord-api-docs/docs/resources/Stage_Instance.md +106 -0
- package/discord-api-docs/docs/resources/Sticker.md +164 -0
- package/discord-api-docs/docs/resources/User.md +205 -0
- package/discord-api-docs/docs/resources/Voice.md +55 -0
- package/discord-api-docs/docs/resources/Webhook.md +281 -0
- package/discord-api-docs/docs/rich_presence/Best_Practices.md +88 -0
- package/discord-api-docs/docs/rich_presence/FAQ.md +45 -0
- package/discord-api-docs/docs/rich_presence/How_To.md +302 -0
- package/discord-api-docs/docs/rich_presence/Launch_Checklist.md +46 -0
- package/discord-api-docs/docs/topics/Certified_Devices.md +200 -0
- package/discord-api-docs/docs/topics/Community_Resources.md +98 -0
- package/discord-api-docs/docs/topics/Gateway.md +1600 -0
- package/discord-api-docs/docs/topics/OAuth2.md +427 -0
- package/discord-api-docs/docs/topics/Opcodes_and_Status_Codes.md +306 -0
- package/discord-api-docs/docs/topics/Permissions.md +229 -0
- package/discord-api-docs/docs/topics/RPC.md +1597 -0
- package/discord-api-docs/docs/topics/Rate_Limits.md +126 -0
- package/discord-api-docs/docs/topics/Teams.md +80 -0
- package/discord-api-docs/docs/topics/Threads.md +163 -0
- package/discord-api-docs/docs/topics/Voice_Connections.md +282 -0
- package/discord-api-docs/images/API_center.gif +0 -0
- package/discord-api-docs/images/ask-to-join.gif +0 -0
- package/discord-api-docs/images/available-published.png +0 -0
- package/discord-api-docs/images/button-styles.png +0 -0
- package/discord-api-docs/images/certified-device.png +0 -0
- package/discord-api-docs/images/command-with-groups-subcommands-parameters.png +0 -0
- package/discord-api-docs/images/command-with-groups-subcommands.png +0 -0
- package/discord-api-docs/images/command.png +0 -0
- package/discord-api-docs/images/cpp-files-sdk.png +0 -0
- package/discord-api-docs/images/create-store-channel.png +0 -0
- package/discord-api-docs/images/deferred-example.png +0 -0
- package/discord-api-docs/images/desktop-select.png +0 -0
- package/discord-api-docs/images/game-overlay-sdk-invite.gif +0 -0
- package/discord-api-docs/images/game-overlay-sdk-voice-settings.png +0 -0
- package/discord-api-docs/images/game-overlay-sdk-voice-widget.png +0 -0
- package/discord-api-docs/images/gift-code-creation.png +0 -0
- package/discord-api-docs/images/lib-linked-sdk.png +0 -0
- package/discord-api-docs/images/message-command.png +0 -0
- package/discord-api-docs/images/mobile-select.png +0 -0
- package/discord-api-docs/images/previous-new-server-background.png +0 -0
- package/discord-api-docs/images/rp-actionable.png +0 -0
- package/discord-api-docs/images/rp-all-fields.png +0 -0
- package/discord-api-docs/images/rp-bad-art.png +0 -0
- package/discord-api-docs/images/rp-good-art.png +0 -0
- package/discord-api-docs/images/rp-legend.png +0 -0
- package/discord-api-docs/images/rp-long-strings.png +0 -0
- package/discord-api-docs/images/rp-non-actionable.png +0 -0
- package/discord-api-docs/images/rp-not-all-fields.png +0 -0
- package/discord-api-docs/images/rp-profile-example-1.png +0 -0
- package/discord-api-docs/images/rp-profile-example-2.png +0 -0
- package/discord-api-docs/images/rp-short-strings.png +0 -0
- package/discord-api-docs/images/server-banner-example.png +0 -0
- package/discord-api-docs/images/server-banner-margin-top.png +0 -0
- package/discord-api-docs/images/sku-management.png +0 -0
- package/discord-api-docs/images/snowflake.png +0 -0
- package/discord-api-docs/images/snowflake_original_size.png +0 -0
- package/discord-api-docs/images/spectate.gif +0 -0
- package/discord-api-docs/images/team-2fa.png +0 -0
- package/discord-api-docs/images/team-make-app.png +0 -0
- package/discord-api-docs/images/team-page.png +0 -0
- package/discord-api-docs/images/transfer-app-to-team.png +0 -0
- package/discord-api-docs/images/user-command.png +0 -0
- package/discord-api-docs/package-lock.json +3186 -0
- package/discord-api-docs/package.json +38 -0
- package/discord-api-docs/tsconfig.eslint.json +4 -0
- package/discord-api-docs/tsconfig.json +19 -0
- package/mod.js +14 -0
- package/mod.ts +24 -0
- package/package.json +28 -0
- package/tsconfig.json +24 -0
- package/types.ts +5334 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
# OAuth2
|
|
2
|
+
|
|
3
|
+
OAuth2 enables application developers to build applications that utilize authentication and data from the Discord API. Within Discord, there are multiple types of OAuth2 authentication. We support the authorization code grant, the implicit grant, client credentials, and some modified special-for-Discord flows for Bots and Webhooks.
|
|
4
|
+
|
|
5
|
+
## Shared Resources
|
|
6
|
+
|
|
7
|
+
The first step in implementing OAuth2 is [registering a developer application](#APPLICATIONS) and retrieving your client ID and client secret. Most people who will be implementing OAuth2 will want to find and utilize a library in the language of their choice. For those implementing OAuth2 from scratch, please see [RFC 6749](https://tools.ietf.org/html/rfc6749) for details. After you create your application with Discord, make sure that you have your `client_id` and `client_secret` handy. The next step is to figure out which OAuth2 flow is right for your purposes.
|
|
8
|
+
|
|
9
|
+
###### OAuth2 URLs
|
|
10
|
+
|
|
11
|
+
| URL | Description |
|
|
12
|
+
| ------------------------------------------- | ----------------------------------------------------------- |
|
|
13
|
+
| https://discord.com/api/oauth2/authorize | Base authorization URL |
|
|
14
|
+
| https://discord.com/api/oauth2/token | Token URL |
|
|
15
|
+
| https://discord.com/api/oauth2/token/revoke | [Token Revocation](https://tools.ietf.org/html/rfc7009) URL |
|
|
16
|
+
|
|
17
|
+
> warn
|
|
18
|
+
> In accordance with the relevant RFCs, the token and token revocation URLs will **only** accept a content type of `application/x-www-form-urlencoded`. JSON content is not permitted and will return an error.
|
|
19
|
+
|
|
20
|
+
###### OAuth2 Scopes
|
|
21
|
+
|
|
22
|
+
These are a list of all the OAuth2 scopes that Discord supports. Some scopes require approval from Discord to use. Requesting them from a user without approval from Discord may cause errors or undocumented behavior in the OAuth2 flow.
|
|
23
|
+
|
|
24
|
+
| Name | Description |
|
|
25
|
+
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| activities.read | allows your app to fetch data from a user's "Now Playing/Recently Played" list - requires Discord approval |
|
|
27
|
+
| activities.write | allows your app to update a user's activity - requires Discord approval (NOT REQUIRED FOR [GAMESDK ACTIVITY MANAGER](#DOCS_GAME_SDK_ACTIVITIES/)) |
|
|
28
|
+
| applications.builds.read | allows your app to read build data for a user's applications |
|
|
29
|
+
| applications.builds.upload | allows your app to upload/update builds for a user's applications - requires Discord approval |
|
|
30
|
+
| applications.commands | allows your app to use [commands](#DOCS_INTERACTIONS_APPLICATION_COMMANDS/) in a guild |
|
|
31
|
+
| applications.commands.update | allows your app to update its [commands](#DOCS_INTERACTIONS_APPLICATION_COMMANDS/) via this bearer token - [client credentials grant](#DOCS_TOPICS_OAUTH2/client-credentials-grant) only |
|
|
32
|
+
| applications.entitlements | allows your app to read entitlements for a user's applications |
|
|
33
|
+
| applications.store.update | allows your app to read and update store data (SKUs, store listings, achievements, etc.) for a user's applications |
|
|
34
|
+
| bot | for oauth2 bots, this puts the bot in the user's selected guild by default |
|
|
35
|
+
| connections | allows [/users/@me/connections](#DOCS_RESOURCES_USER/get-user-connections) to return linked third-party accounts |
|
|
36
|
+
| email | enables [/users/@me](#DOCS_RESOURCES_USER/get-current-user) to return an `email` |
|
|
37
|
+
| gdm.join | allows your app to [join users to a group dm](#DOCS_RESOURCES_CHANNEL/group-dm-add-recipient) |
|
|
38
|
+
| guilds | allows [/users/@me/guilds](#DOCS_RESOURCES_USER/get-current-user-guilds) to return basic information about all of a user's guilds |
|
|
39
|
+
| guilds.join | allows [/guilds/{guild.id}/members/{user.id}](#DOCS_RESOURCES_GUILD/add-guild-member) to be used for joining users to a guild |
|
|
40
|
+
| guilds.members.read | allows [/users/@me/guilds/{guild.id}/member](#DOCS_RESOURCES_USER/get-current-user-guild-member) to return a user's member information in a guild |
|
|
41
|
+
| identify | allows [/users/@me](#DOCS_RESOURCES_USER/get-current-user) without `email` |
|
|
42
|
+
| messages.read | for local rpc server api access, this allows you to read messages from all client channels (otherwise restricted to channels/guilds your app creates) |
|
|
43
|
+
| relationships.read | allows your app to know a user's friends and implicit relationships - requires Discord approval |
|
|
44
|
+
| rpc | for local rpc server access, this allows you to control a user's local Discord client - requires Discord approval |
|
|
45
|
+
| rpc.activities.write | for local rpc server access, this allows you to update a user's activity - requires Discord approval |
|
|
46
|
+
| rpc.notifications.read | for local rpc server access, this allows you to receive notifications pushed out to the user - requires Discord approval |
|
|
47
|
+
| rpc.voice.read | for local rpc server access, this allows you to read a user's voice settings and listen for voice events - requires Discord approval |
|
|
48
|
+
| rpc.voice.write | for local rpc server access, this allows you to update a user's voice settings - requires Discord approval |
|
|
49
|
+
| webhook.incoming | this generates a webhook that is returned in the oauth token response for authorization code grants |
|
|
50
|
+
|
|
51
|
+
> info
|
|
52
|
+
> `guilds.join` and `bot` require you to have a bot account linked to your application. Also, in order to add a user to a guild, your bot has to already belong to that guild.
|
|
53
|
+
|
|
54
|
+
## State and Security
|
|
55
|
+
|
|
56
|
+
Before we dive into the semantics of the different OAuth2 grants, we should stop and discuss security, specifically the use of the `state` parameter. [Cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery), or CSRF, and [Clickjacking](https://en.wikipedia.org/wiki/Clickjacking) are security vulnerabilities that must be addressed by individuals implementing OAuth. This is typically accomplished using the `state` parameter. `state` is sent in the authorization request and returned back in the response and should be a value that binds the user's request to their authenticated state. For example, `state` could be a hash of the user's session cookie, or some other nonce that can be linked to the user's session.
|
|
57
|
+
|
|
58
|
+
When a user begins an authorization flow on the client, a `state` is generated that is unique to that user's request. This value is stored somewhere only accessible to the client and the user, i.e. protected by the [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy). When the user is redirected, the `state` parameter is returned. The client validates the request by checking that the `state` returned matches the stored value. If they match, it is a valid authorization request. If they do not match, it's possible that someone intercepted the request or otherwise falsely authorized themselves to another user's resources, and the request should be denied.
|
|
59
|
+
|
|
60
|
+
While Discord does not require the use of the `state` parameter, we support it and highly recommend that you implement it for the security of your own applications and data.
|
|
61
|
+
|
|
62
|
+
## Authorization Code Grant
|
|
63
|
+
|
|
64
|
+
The authorization code grant is what most developers will recognize as "standard OAuth2" and involves retrieving an access code and exchanging it for a user's access token. It allows the authorization server to act as an intermediary between the client and the resource owner, so the resource owner's credentials are never shared directly with the client.
|
|
65
|
+
|
|
66
|
+
###### Authorization URL Example
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
https://discord.com/api/oauth2/authorize?response_type=code&client_id=157730590492196864&scope=identify%20guilds.join&state=15773059ghq9183habn&redirect_uri=https%3A%2F%2Fnicememe.website&prompt=consent
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`client_id` is your application's `client_id`. `scope` is a list of [OAuth2 scopes](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-scopes) separated by url encoded spaces (`%20`). `redirect_uri` is whatever URL you registered when creating your application, url-encoded. `state` is the unique string mentioned in [State and Security](#DOCS_TOPICS_OAUTH2/state-and-security).
|
|
73
|
+
|
|
74
|
+
When someone navigates to this URL, they will be prompted to authorize your application for the requested scopes. On acceptance, they will be redirected to your `redirect_uri`, which will contain an additional querystring parameter, `code`. `state` will also be returned if previously sent, and should be validated at this point.
|
|
75
|
+
|
|
76
|
+
`prompt` controls how the authorization flow handles existing authorizations. If a user has previously authorized your application with the requested scopes and prompt is set to `consent`, it will request them to reapprove their authorization. If set to `none`, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization. For passthrough scopes, like `bot` and `webhook.incoming`, authorization is always required.
|
|
77
|
+
|
|
78
|
+
###### Redirect URL Example
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
https://nicememe.website/?code=NhhvTDYsFcdgNLnnLijcl7Ku7bEEeee&state=15773059ghq9183habn
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`code` is now exchanged for the user's access token by making a `POST` request to the [token URL](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-urls) with the following parameters:
|
|
85
|
+
|
|
86
|
+
- `client_id` - your application's client id
|
|
87
|
+
- `client_secret` - your application's client secret
|
|
88
|
+
- `grant_type` - must be set to `authorization_code`
|
|
89
|
+
- `code` - the code from the querystring
|
|
90
|
+
- `redirect_uri` - your `redirect_uri`
|
|
91
|
+
|
|
92
|
+
###### Access Token Exchange Example
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import requests
|
|
96
|
+
|
|
97
|
+
API_ENDPOINT = 'https://discord.com/api/v8'
|
|
98
|
+
CLIENT_ID = '332269999912132097'
|
|
99
|
+
CLIENT_SECRET = '937it3ow87i4ery69876wqire'
|
|
100
|
+
REDIRECT_URI = 'https://nicememe.website'
|
|
101
|
+
|
|
102
|
+
def exchange_code(code):
|
|
103
|
+
data = {
|
|
104
|
+
'client_id': CLIENT_ID,
|
|
105
|
+
'client_secret': CLIENT_SECRET,
|
|
106
|
+
'grant_type': 'authorization_code',
|
|
107
|
+
'code': code,
|
|
108
|
+
'redirect_uri': REDIRECT_URI
|
|
109
|
+
}
|
|
110
|
+
headers = {
|
|
111
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
112
|
+
}
|
|
113
|
+
r = requests.post('%s/oauth2/token' % API_ENDPOINT, data=data, headers=headers)
|
|
114
|
+
r.raise_for_status()
|
|
115
|
+
return r.json()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
You can also pass your `client_id` and `client_secret` as basic authentication with `client_id` as the username and `client_secret` as the password. In response, you will receive:
|
|
119
|
+
|
|
120
|
+
###### Access Token Response
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"access_token": "6qrZcUqja7812RVdnEKjpzOL4CvHBFG",
|
|
125
|
+
"token_type": "Bearer",
|
|
126
|
+
"expires_in": 604800,
|
|
127
|
+
"refresh_token": "D43f5y0ahjqew82jZ4NViEr2YafMKhue",
|
|
128
|
+
"scope": "identify"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Having the user's access token allows your application to make certain requests to the API on their behalf, restricted to whatever scopes were requested. `expires_in` is how long, in seconds, until the returned access token expires, allowing you to anticipate the expiration and refresh the token. To refresh, make another `POST` request to the [token URL](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-urls) with the following parameters:
|
|
133
|
+
|
|
134
|
+
- `client_id` - your application's client id
|
|
135
|
+
- `client_secret` - your application's client secret
|
|
136
|
+
- `grant_type` - must be set to `refresh_token`
|
|
137
|
+
- `refresh_token` - the user's refresh token
|
|
138
|
+
|
|
139
|
+
###### Refresh Token Exchange Example
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
import requests
|
|
143
|
+
|
|
144
|
+
API_ENDPOINT = 'https://discord.com/api/v8'
|
|
145
|
+
CLIENT_ID = '332269999912132097'
|
|
146
|
+
CLIENT_SECRET = '937it3ow87i4ery69876wqire'
|
|
147
|
+
REDIRECT_URI = 'https://nicememe.website'
|
|
148
|
+
|
|
149
|
+
def refresh_token(refresh_token):
|
|
150
|
+
data = {
|
|
151
|
+
'client_id': CLIENT_ID,
|
|
152
|
+
'client_secret': CLIENT_SECRET,
|
|
153
|
+
'grant_type': 'refresh_token',
|
|
154
|
+
'refresh_token': refresh_token
|
|
155
|
+
}
|
|
156
|
+
headers = {
|
|
157
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
158
|
+
}
|
|
159
|
+
r = requests.post('%s/oauth2/token' % API_ENDPOINT, data=data, headers=headers)
|
|
160
|
+
r.raise_for_status()
|
|
161
|
+
return r.json()
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Boom; fresh [access token response](#DOCS_TOPICS_OAUTH2/authorization-code-grant-access-token-response)!
|
|
165
|
+
|
|
166
|
+
## Implicit Grant
|
|
167
|
+
|
|
168
|
+
The implicit OAuth2 grant is a simplified flow optimized for in-browser clients. Instead of issuing the client an authorization code to be exchanged for an access token, the client is directly issued an access token. The URL is formatted as follows:
|
|
169
|
+
|
|
170
|
+
###### Authorization URL Example
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
https://discord.com/api/oauth2/authorize?response_type=token&client_id=290926444748734499&state=15773059ghq9183habn&scope=identify
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
On redirect, your redirect URI will contain additional **URI fragments**: `access_token`, `token_type`, `expires_in`, `scope`, and [`state`](#DOCS_TOPICS_OAUTH2/state-and-security)(if specified). **These are not querystring parameters.** Be mindful of the "#" character:
|
|
177
|
+
|
|
178
|
+
###### Redirect URL Example
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
https://findingfakeurlsisprettyhard.tv/#access_token=RTfP0OK99U3kbRtHOoKLmJbOn45PjL&token_type=Bearer&expires_in=604800&scope=identify&state=15773059ghq9183habn
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
There are tradeoffs in using the implicit grant flow. It is both quicker and easier to implement, but rather than exchanging a code and getting a token returned in a secure HTTP body, the access token is returned in the URI fragment, which makes it possibly exposed to unauthorized parties. **You also are not returned a refresh token, so the user must explicitly re-authorize once their token expires.**
|
|
185
|
+
|
|
186
|
+
## Client Credentials Grant
|
|
187
|
+
|
|
188
|
+
The client credential flow is a quick and easy way for bot developers to get their own bearer tokens for testing purposes. By making a `POST` request to the [token URL](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-urls) with a grant type of `client_credentials`, using Basic authentication with your client id as the username and your client secret as the password, you will be returned an access token for the bot owner. Therefore, always be super-extra-very-we-are-not-kidding-like-really-be-secure-make-sure-your-info-is-not-in-your-source-code careful with your `client_id` and `client_secret`. We don't take kindly to imposters around these parts.
|
|
189
|
+
|
|
190
|
+
You can specify scopes with the `scope` parameter, which is a list of [OAuth2 scopes](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-scopes) separated by spaces:
|
|
191
|
+
|
|
192
|
+
> info
|
|
193
|
+
> Team applications are limited to the `identify` and `applications.commands.update` scope, because teams are not bound to a specific user.
|
|
194
|
+
|
|
195
|
+
###### Client Credentials Token Request Example
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import base64
|
|
199
|
+
import requests
|
|
200
|
+
|
|
201
|
+
API_ENDPOINT = 'https://discord.com/api/v8'
|
|
202
|
+
CLIENT_ID = '332269999912132097'
|
|
203
|
+
CLIENT_SECRET = '937it3ow87i4ery69876wqire'
|
|
204
|
+
|
|
205
|
+
def get_token():
|
|
206
|
+
data = {
|
|
207
|
+
'grant_type': 'client_credentials',
|
|
208
|
+
'scope': 'identify connections'
|
|
209
|
+
}
|
|
210
|
+
headers = {
|
|
211
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
212
|
+
}
|
|
213
|
+
r = requests.post('%s/oauth2/token' % API_ENDPOINT, data=data, headers=headers, auth=(CLIENT_ID, CLIENT_SECRET))
|
|
214
|
+
r.raise_for_status()
|
|
215
|
+
return r.json()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
In return, you will receive an access token (without a refresh token):
|
|
219
|
+
|
|
220
|
+
###### Client Credentials Access Token Response
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{
|
|
224
|
+
"access_token": "6qrZcUqja7812RVdnEKjpzOL4CvHBFG",
|
|
225
|
+
"token_type": "Bearer",
|
|
226
|
+
"expires_in": 604800,
|
|
227
|
+
"scope": "identify connections"
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Bots
|
|
232
|
+
|
|
233
|
+
So, what are bot accounts?
|
|
234
|
+
|
|
235
|
+
### Bot vs User Accounts
|
|
236
|
+
|
|
237
|
+
Discord's API provides a separate type of user account dedicated to automation, called a bot account. Bot accounts can be created through the [applications page](#APPLICATIONS), and are authenticated using a token (rather than a username and password). Unlike the normal OAuth2 flow, bot accounts have full access to all API routes without using bearer tokens, and can connect to the [Real Time Gateway](#DOCS_TOPICS_GATEWAY/gateways). Automating normal user accounts (generally called "self-bots") outside of the OAuth2/bot API is forbidden, and can result in account termination if found.
|
|
238
|
+
|
|
239
|
+
Bot accounts have a few differences in comparison to normal user accounts, namely:
|
|
240
|
+
|
|
241
|
+
1. Bots are added to guilds through the OAuth2 API, and cannot accept normal invites.
|
|
242
|
+
2. Bots cannot have friends, nor be added to or join Group DMs.
|
|
243
|
+
3. Verified bots do not have a maximum number of Guilds.
|
|
244
|
+
4. Bots have an entirely separate set of [Rate Limits](#DOCS_TOPICS_RATE_LIMITS/rate-limits).
|
|
245
|
+
|
|
246
|
+
### Bot Authorization Flow
|
|
247
|
+
|
|
248
|
+
Bot authorization is a special server-less and callback-less OAuth2 flow that makes it easy for users to add bots to guilds. The URL you create looks similar to what we use for full stack implementation:
|
|
249
|
+
|
|
250
|
+
###### Bot Auth Parameters
|
|
251
|
+
|
|
252
|
+
| name | description |
|
|
253
|
+
| -------------------- | --------------------------------------------------------------------- |
|
|
254
|
+
| client_id | your app's client id |
|
|
255
|
+
| scope | needs to include `bot` for the bot flow |
|
|
256
|
+
| permissions | the [permissions](#DOCS_TOPICS_PERMISSIONS/) you're requesting |
|
|
257
|
+
| guild_id | pre-fills the dropdown picker with a guild for the user |
|
|
258
|
+
| disable_guild_select | `true` or `false`—disallows the user from changing the guild dropdown |
|
|
259
|
+
|
|
260
|
+
###### URL Example
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
https://discord.com/api/oauth2/authorize?client_id=157730590492196864&scope=bot&permissions=1
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
In the case of bots, the `scope` parameter should be set to `bot`. There's also a new parameter, `permissions`, which is an integer corresponding to the [permission calculations](#DOCS_TOPICS_PERMISSIONS/permissions-bitwise-permission-flags) for the bot. You'll also notice the absence of `response_type` and `redirect_uri`. Bot authorization does not require these parameters because there is no need to retrieve the user's access token.
|
|
267
|
+
|
|
268
|
+
When the user navigates to this page, they'll be prompted to add the bot to a guild in which they have proper permissions. On acceptance, the bot will be added. Super easy!
|
|
269
|
+
|
|
270
|
+
If you happen to already know the ID of the guild the user will add your bot to, you can provide this ID in the URL as a `guild_id=GUILD_ID` parameter.
|
|
271
|
+
When the authorization page loads, that guild will be preselected in the dialog if that user has permission to add the bot to that guild. You can use this in conjunction with the parameter `disable_guild_select=true` to disallow the user from picking a different guild.
|
|
272
|
+
|
|
273
|
+
If your bot is super specific to your private clubhouse, or you just don't like sharing, you can leave the `Public Bot` option unchecked in your application's settings. If unchecked, only you can add the bot to guilds. If marked as public, anyone with your bot's URL can add it to guilds in which they have proper permissions.
|
|
274
|
+
|
|
275
|
+
### Advanced Bot Authorization
|
|
276
|
+
|
|
277
|
+
Devs can extend the bot authorization functionality. You can request additional scopes outside of `bot`, which will prompt a continuation into a complete [authorization code grant flow](#DOCS_TOPICS_OAUTH2/authorization-code-grant) and add the ability to request the user's access token. If you request any scopes outside of `bot`, `response_type` is again mandatory; we will also automatically redirect the user to the first URI in your application's registered list unless `redirect_uri` is specified.
|
|
278
|
+
|
|
279
|
+
When receiving the access code on redirect, there will be additional querystring parameters of `guild_id` and `permissions`. The `guild_id` parameter should only be used as a hint as to the relationship between your bot and a guild. To be sure of the relationship between your bot and the guild, consider requiring the Oauth2 code grant in your bot's settings. Enabling it requires anyone adding your bot to a server to go through a full OAuth2 [authorization code grant flow](#DOCS_TOPICS_OAUTH2/authorization-code-grant). When you retrieve the user's access token, you'll also receive information about the guild to which your bot was added:
|
|
280
|
+
|
|
281
|
+
###### Extended Bot Authorization Access Token Example
|
|
282
|
+
|
|
283
|
+
```json
|
|
284
|
+
{
|
|
285
|
+
"token_type": "Bearer",
|
|
286
|
+
"guild": {
|
|
287
|
+
"mfa_level": 0,
|
|
288
|
+
"emojis": [],
|
|
289
|
+
"application_id": null,
|
|
290
|
+
"name": "SomeTest",
|
|
291
|
+
"roles": [
|
|
292
|
+
{
|
|
293
|
+
"hoist": false,
|
|
294
|
+
"name": "@everyone",
|
|
295
|
+
"mentionable": false,
|
|
296
|
+
"color": 0,
|
|
297
|
+
"position": 0,
|
|
298
|
+
"id": "290926798626357250",
|
|
299
|
+
"managed": false,
|
|
300
|
+
"permissions": 49794241,
|
|
301
|
+
"permissions_new": "49794241"
|
|
302
|
+
}
|
|
303
|
+
],
|
|
304
|
+
"afk_timeout": 300,
|
|
305
|
+
"system_channel_id": null,
|
|
306
|
+
"widget_channel_id": null,
|
|
307
|
+
"region": "us-east",
|
|
308
|
+
"default_message_notifications": 1,
|
|
309
|
+
"explicit_content_filter": 0,
|
|
310
|
+
"splash": null,
|
|
311
|
+
"features": [],
|
|
312
|
+
"afk_channel_id": null,
|
|
313
|
+
"widget_enabled": false,
|
|
314
|
+
"verification_level": 0,
|
|
315
|
+
"owner_id": "53908232999183680",
|
|
316
|
+
"id": "2909267986347357250",
|
|
317
|
+
"icon": null,
|
|
318
|
+
"description": null,
|
|
319
|
+
"public_updates_channel_id": null,
|
|
320
|
+
"rules_channel_id": null,
|
|
321
|
+
"max_members": 100000,
|
|
322
|
+
"vanity_url_code": null,
|
|
323
|
+
"premium_subscription_count": 0,
|
|
324
|
+
"premium_tier": 0,
|
|
325
|
+
"preferred_locale": "en-US",
|
|
326
|
+
"system_channel_flags": 0,
|
|
327
|
+
"banner": null,
|
|
328
|
+
"max_presences": null,
|
|
329
|
+
"discovery_splash": null,
|
|
330
|
+
"max_video_channel_users": 25
|
|
331
|
+
},
|
|
332
|
+
"access_token": "zMndOe7jFLXGawdlxMOdNvXjjOce5X",
|
|
333
|
+
"scope": "bot",
|
|
334
|
+
"expires_in": 604800,
|
|
335
|
+
"refresh_token": "mgp8qnvBwJcmadwgCYKyYD5CAzGAX4"
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Two-Factor Authentication Requirement
|
|
340
|
+
|
|
341
|
+
For bots with [elevated permissions](#DOCS_TOPICS_PERMISSIONS/permissions-bitwise-permission-flags) (permissions with a `*` next to them), we enforce two-factor authentication on the owner's account when added to guilds that have server-wide 2FA enabled.
|
|
342
|
+
|
|
343
|
+
## Webhooks
|
|
344
|
+
|
|
345
|
+
Discord's webhook flow is a specialized version of an [authorization code](#DOCS_TOPICS_OAUTH2/authorization-code-grant) implementation. In this case, the `scope` querystring parameter needs to be set to `webhook.incoming`:
|
|
346
|
+
|
|
347
|
+
###### URL Example
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
https://discord.com/api/oauth2/authorize?response_type=code&client_id=157730590492196864&scope=webhook.incoming&state=15773059ghq9183habn&redirect_uri=https%3A%2F%2Fnicememe.website
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
When the user navigates to this URL, they will be prompted to select a channel in which to allow the webhook. When the webhook is [executed](#DOCS_RESOURCES_WEBHOOK/execute-webhook), it will post its message into this channel. On acceptance, the user will be redirected to your `redirect_uri`. The URL will contain the `code` querystring parameter which should be [exchanged for an access token](#DOCS_TOPICS_OAUTH2/authorization-code-grant-access-token-exchange-example). In return, you will receive a slightly modified token response:
|
|
354
|
+
|
|
355
|
+
###### Webhook Token Response Example
|
|
356
|
+
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"token_type": "Bearer",
|
|
360
|
+
"access_token": "GNaVzEtATqdh173tNHEXY9ZYAuhiYxvy",
|
|
361
|
+
"scope": "webhook.incoming",
|
|
362
|
+
"expires_in": 604800,
|
|
363
|
+
"refresh_token": "PvPL7ELyMDc1836457XCDh1Y8jPbRm",
|
|
364
|
+
"webhook": {
|
|
365
|
+
"application_id": "310954232226357250",
|
|
366
|
+
"name": "testwebhook",
|
|
367
|
+
"url": "https://discord.com/api/webhooks/347114750880120863/kKDdjXa1g9tKNs0-_yOwLyALC9gydEWP6gr9sHabuK1vuofjhQDDnlOclJeRIvYK-pj_",
|
|
368
|
+
"channel_id": "345626669224982402",
|
|
369
|
+
"token": "kKDdjXa1g9tKNs0-_yOwLyALC9gydEWP6gr9sHabuK1vuofjhQDDnlOclJeRIvYK-pj_",
|
|
370
|
+
"type": 1,
|
|
371
|
+
"avatar": null,
|
|
372
|
+
"guild_id": "290926792226357250",
|
|
373
|
+
"id": "347114750880120863"
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
From this object, you should store the `webhook.token` and `webhook.id`. See the [execute webhook](#DOCS_RESOURCES_WEBHOOK/execute-webhook) documentation for how to send messages with the webhook.
|
|
379
|
+
|
|
380
|
+
Any user that wishes to add your webhook to their channel will need to go through the full OAuth2 flow. A new webhook is created each time, so you will need to save the token and id. If you wish to send a message to all your webhooks, you'll need to iterate over each stored id:token combination and make `POST` requests to each one. Be mindful of our [Rate Limits](#DOCS_TOPICS_RATE_LIMITS/rate-limits)!
|
|
381
|
+
|
|
382
|
+
## Get Current Bot Application Information % GET /oauth2/applications/@me
|
|
383
|
+
|
|
384
|
+
Returns the bot's [application](#DOCS_RESOURCES_APPLICATION/application-object) object.
|
|
385
|
+
|
|
386
|
+
## Get Current Authorization Information % GET /oauth2/@me
|
|
387
|
+
|
|
388
|
+
Returns info about the current authorization. Requires authentication with a bearer token.
|
|
389
|
+
|
|
390
|
+
###### Response Structure
|
|
391
|
+
|
|
392
|
+
| Field | Type | Description |
|
|
393
|
+
| ----------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
394
|
+
| application | partial [application](#DOCS_RESOURCES_APPLICATION/application-object) object | the current application |
|
|
395
|
+
| scopes | array of strings | the scopes the user has authorized the application for |
|
|
396
|
+
| expires | ISO8601 timestamp | when the access token expires |
|
|
397
|
+
| user? | [user](#DOCS_RESOURCES_USER/user-object) object | the user who has authorized, if the user has authorized with the `identify` scope |
|
|
398
|
+
|
|
399
|
+
###### Example Authorization Information
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"application": {
|
|
404
|
+
"id": "159799960412356608",
|
|
405
|
+
"name": "AIRHORN SOLUTIONS",
|
|
406
|
+
"icon": "f03590d3eb764081d154a66340ea7d6d",
|
|
407
|
+
"description": "",
|
|
408
|
+
"summary": "",
|
|
409
|
+
"hook": true,
|
|
410
|
+
"bot_public": true,
|
|
411
|
+
"bot_require_code_grant": false,
|
|
412
|
+
"verify_key": "c8cde6a3c8c6e49d86af3191287b3ce255872be1fff6dc285bdb420c06a2c3c8"
|
|
413
|
+
},
|
|
414
|
+
"scopes": [
|
|
415
|
+
"guilds.join",
|
|
416
|
+
"identify"
|
|
417
|
+
],
|
|
418
|
+
"expires": "2021-01-23T02:33:17.017000+00:00",
|
|
419
|
+
"user": {
|
|
420
|
+
"id": "268473310986240001",
|
|
421
|
+
"username": "Discord",
|
|
422
|
+
"avatar": "f749bb0cbeeb26ef21eca719337d20f1",
|
|
423
|
+
"discriminator": "0001",
|
|
424
|
+
"public_flags": 131072
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|