Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discord OAuth Code Usage

I'm interested in interfacing with Discord using the Discord API. I would describe their documentation as "sparse," but maybe I'm just not looking in the right places. Most of my information comes from this page:

https://discordapp.com/developers/docs/topics/oauth2

I've already set up my Discord guild and application (and even a bot, which may be unnecessary). My specific plan to is to allow users to give my site permission to add them to a private Discord guild/server. I have a hyperlink on one of my site's pages that references this URL:

https://discordapp.com/api/oauth2/authorize?client_id=[ClientID]&scope=guilds.join&response_type=code&redirect_uri=[RedirectURI]

This part seems to work well. The user approves the request. The user is then sent back to my site with a "code" key-value pair in the query string. I think this code is what is called an "authorization code." So how can I use this authorization code to add the user to my guild? I found this page on the Discord site:

https://discordapp.com/developers/docs/resources/guild#add-guild-member

From that page I can see I need to initiate a PUT to this URL:

https://discordapp.com/api/guilds/{guild.id}/members/{user.id}

But I don't know the {user.id}. I only have an authorization code.

It also says, "... provided you have a valid oauth2 access token for the user with the guilds.join scope." I don't have an access token. Again, I only have an authorization code.

So it seems to me I need to somehow exchange this authorization code for an access token and a user ID. Can someone tell me how to do that? I've been experimenting with the following URL, but I don't know what method (GET, POST, etc.) or what parameters to send it:

https://discordapp.com/api/oauth2/token

Because I'd like to understand the intracacies of how this works, I'd prefer to know how to do this with ordinary Web requests (such as HttpWebRequest and WebClient, as opposed to using some OAuth library).

Update

I decided to read (selectively) this RFC:

https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3

I have linked the section that I think is the most appropriate. It seems the correct procedure is to send a POST request to the following URL and parameters:

https://discordapp.com/api/oauth2/token

grant_type=authorization_code&code=[AuthorizationCode]&redirect_uri=[RedirectURI]&client_id=[ClientID]

This also seems to be in accordance with Peter G's answer. Unfortunately, this request fails with a 401 (Unauthorized) error. So I figured this was a dead end. I've tried it several times, but hopefully there's a solution. I received this response body:

{"error": "invalid_client"}

And I received these headers:

Connection: close

Pragma: no-cache

Strict-Transport-Security: max-age=31536000; includeSubDomains

Alt-Svc: clear

CF-RAY: [RedactedJustInCase]

Content-Length: 27

Cache-Control: no-store

Content-Type: application/json

Date: Fri, 07 Apr 2017 01:12:19 GMT

Set-Cookie: __cfduid=[RedactedJustInCase]; expires=Sat, 07-Apr-18 01:12:19 GMT; path=/; domain=.discordapp.com; HttpOnly

Server: cloudflare-nginx

Via: 1.1 google

like image 424
user1325179 Avatar asked Apr 06 '17 16:04

user1325179


1 Answers

You're almost there as far as getting the OAuth token is concerned. You just need to use the other URL listed on the documentation you linked, https://discordapp.com/api/oauth2/token. POST to it with the following parameters: https://discordapp.com/api/oauth2/token?client_id=[ClientID]&grant_type=authorization_code&code=[AuthorizationCode]&redirect_uri=[RedirectURI]&client_secret=[Secret] where the AuthorizationCode is the return from the first URL and the Secret is the client secret you got when first registering your app.

That should get you the client token back (as well as how long it will take for the token to expire) in the response body. As for getting the User object, you need to add scope identify to the first request so you can use the token to call https://discordapp.com/developers/docs/resources/user#get-current-user (in case the link breaks, it's GET users/@me). That API will return the User object in JSON form.

Finally, you can add the user by PUT-ing to https://discordapp.com/api/guilds/[guild.id]/members/[user.id] using the user object you just got.

When using the APIs after getting the client token (the ones to get the user object and put the user in the guild), you need to put the token in the HTTP request under the authorization header using the Bearer auth scheme. Basically, that means the header should be set to "Bearer TOKEN_HERE". You should also use content-type "application/x-www-form-urlencoded" if you weren't already using it.

If there's anything you don't understand here, I strongly suggest reading about oauth from the source RFC (don't worry, these two sections are short): getting an auth code, getting a token, authenticating with Bearer scheme. Them's the breaks when you don't use a library.

like image 55
Peter G Avatar answered Oct 23 '22 07:10

Peter G