Skip to content

Instantly share code, notes, and snippets.

@Jengas
Last active March 26, 2024 21:40
Show Gist options
  • Star 79 You must be signed in to star a gist
  • Fork 19 You must be signed in to fork a gist
  • Save Jengas/ad128715cb4f73f5cde9c467edf64b00 to your computer and use it in GitHub Desktop.
Save Jengas/ad128715cb4f73f5cde9c467edf64b00 to your computer and use it in GitHub Desktop.
Discord oauth2 example PHP
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
ini_set('max_execution_time', 300); //300 seconds = 5 minutes. In case if your CURL is slow and is loading too much (Can be IPv6 problem)
error_reporting(E_ALL);
define('OAUTH2_CLIENT_ID', '1234567890');
define('OAUTH2_CLIENT_SECRET', 'verysecretclientcode');
$authorizeURL = 'https://discord.com/api/oauth2/authorize';
$tokenURL = 'https://discord.com/api/oauth2/token';
$apiURLBase = 'https://discord.com/api/users/@me';
$revokeURL = 'https://discord.com/api/oauth2/token/revoke';
session_start();
// Start the login process by sending the user to Discord's authorization page
if(get('action') == 'login') {
$params = array(
'client_id' => OAUTH2_CLIENT_ID,
'redirect_uri' => 'https://yoursite.location/ifyouneedit',
'response_type' => 'code',
'scope' => 'identify guilds'
);
// Redirect the user to Discord's authorization page
header('Location: https://discord.com/api/oauth2/authorize' . '?' . http_build_query($params));
die();
}
// When Discord redirects the user back here, there will be a "code" and "state" parameter in the query string
if(get('code')) {
// Exchange the auth code for a token
$token = apiRequest($tokenURL, array(
"grant_type" => "authorization_code",
'client_id' => OAUTH2_CLIENT_ID,
'client_secret' => OAUTH2_CLIENT_SECRET,
'redirect_uri' => 'https://yoursite.location/ifyouneedit',
'code' => get('code')
));
$logout_token = $token->access_token;
$_SESSION['access_token'] = $token->access_token;
header('Location: ' . $_SERVER['PHP_SELF']);
}
if(session('access_token')) {
$user = apiRequest($apiURLBase);
echo '<h3>Logged In</h3>';
echo '<h4>Welcome, ' . $user->username . '</h4>';
echo '<pre>';
print_r($user);
echo '</pre>';
} else {
echo '<h3>Not logged in</h3>';
echo '<p><a href="?action=login">Log In</a></p>';
}
if(get('action') == 'logout') {
// This should logout you
logout($revokeURL, array(
'token' => session('access_token'),
'token_type_hint' => 'access_token',
'client_id' => OAUTH2_CLIENT_ID,
'client_secret' => OAUTH2_CLIENT_SECRET,
));
unset($_SESSION['access_token']);
header('Location: ' . $_SERVER['PHP_SELF']);
die();
}
function apiRequest($url, $post=FALSE, $headers=array()) {
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
if($post)
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$headers[] = 'Accept: application/json';
if(session('access_token'))
$headers[] = 'Authorization: Bearer ' . session('access_token');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response);
}
function logout($url, $data=array()) {
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_POST => TRUE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'),
CURLOPT_POSTFIELDS => http_build_query($data),
));
$response = curl_exec($ch);
return json_decode($response);
}
function get($key, $default=NULL) {
return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}
function session($key, $default=NULL) {
return array_key_exists($key, $_SESSION) ? $_SESSION[$key] : $default;
}
?>
@javisaf
Copy link

javisaf commented Jan 8, 2021

Thank you so much!!

You saved my day :)

@GabrielDFort
Copy link

How can I get a user's guilds?

@The-MG
Copy link

The-MG commented Feb 16, 2021

How can I get a user's guilds?

That's what I'm wondering lmao

@joramkempf
Copy link

@MG-PlaysMG

You have to make a request.
You can find that in the Discord Dev Portal.
https://discord.com/developers/docs/resources/user#get-current-user-guilds

Copy link

ghost commented Mar 15, 2021

You need to edit the 28 line to
header('Location: https://discord.com/api/oauth2/authorize' . '?' . http_build_query($params));
Because it's no longer discordapp.com but discord 👍

@Jengas
Copy link
Author

Jengas commented Mar 15, 2021

You need to edit the 28 line to
header('Location: https://discord.com/api/oauth2/authorize' . '?' . http_build_query($params));
Because it's no longer discordapp.com but discord 👍

Fixed

@chrisindfw
Copy link

Has anyone found a way to get the token revoke to work? I can destroy the session but I was curious about the revoke itself from the 405 error.

@brenoepics
Copy link

i was getting Trying to get property 'access_token' of non-object. my problem is: i don't have a ssl auto assigned, i'm using cloudflare so my request doesn't worked, i've fixed it adding curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); later of curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); and sorry my bad english i'm brazilian, good luck to everyone <3

@malun22
Copy link

malun22 commented Apr 19, 2021

Revoking the token requires a different curl operation.

Keep in mind, that in RFC 7009 it says:

Implementations MUST support the revocation of refresh tokens and
SHOULD support the revocation of access tokens (see Implementation
Note).

Here is a working function to revoke the token at this date:

$revokeURL = 'https://discordapp.com/api/oauth2/token/revoke';

if(get('action') == 'logout') {
    logout($revokeURL, array(
        'token' => session('access_token'),
        'token_type_hint' => 'access_token',
        'client_id' => OAUTH2_CLIENT_ID,
        'client_secret' => OAUTH2_CLIENT_SECRET,
      ));
    unset($_SESSION['access_token']);
    header('Location: ' . $_SERVER['PHP_SELF']);
    die();
}

function logout($url, $data=array()) {
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
        CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'),
        CURLOPT_POSTFIELDS => http_build_query($data),
    ));
    $response = curl_exec($ch);
    return json_decode($response);
}

@TymianekPL
Copy link

I want to add role to verified users, how to?

@Chaps06TV
Copy link

i was getting Trying to get property 'access_token' of non-object. my problem is: i don't have a ssl auto assigned, i'm using cloudflare so my request doesn't worked, i've fixed it adding curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); later of curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); and sorry my bad english i'm brazilian, good luck to everyone <3

You saved my day!! I've been debugging for 2 days. Thanks!

@frankalvarezdev
Copy link

If you want to get the user just change the scopes, as follows: 'scope' => 'identify guilds' to 'scope' => 'identify guilds email'

Documentation: https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes

Get avatar URL:
$avatar = "https://cdn.discordapp.com/avatars/" . $user->id . "/" . $user->avatar . ".png";

@Anamika-priya1
Copy link

Overall it's good.But I am not getting user info.
my error is:-stdClass Object
(
[message] => 401: Unauthorized
[code] => 0
)
plz help me.

@Jacobinoo
Copy link

Everything is fine except for token refresh. I think the tokens aren't valid after 7 days... Can someone help me find a solution when it comes to token refreshing?

@alex-authlab
Copy link

How to send message, anyone ?

@LordDougall
Copy link

Is it possible to parse this data to a google sheets doc or something similar?

Proper information is displayed, love it thank you, my next obstacle is working with this data. Any insight appreciated!

Thanks again, saved me some serious time

@pietroconta
Copy link

Please, can someone help me? i am 5 days trying to develop a discord access system with oauth2. https://stackoverflow.com/questions/68879995/discord-oauth2-with-php

@pietroconta
Copy link

È possibile analizzare questi dati in un documento di fogli di Google o qualcosa di simile?

Vengono visualizzate le informazioni corrette, lo adoro grazie, il mio prossimo ostacolo è lavorare con questi dati. Qualsiasi intuizione apprezzato!

Grazie ancora, mi hai risparmiato un po' di tempo serio

can you help me? https://stackoverflow.com/questions/68879995/discord-oauth2-with-php

I can't see the data and when I log in and I am redirected, the message remains: Not logged in
Log In

@Jengas
Copy link
Author

Jengas commented Aug 22, 2021

Revoking the token requires a different curl operation.

Keep in mind, that in RFC 7009 it says:

Implementations MUST support the revocation of refresh tokens and
SHOULD support the revocation of access tokens (see Implementation
Note).

Here is a working function to revoke the token at this date:

$revokeURL = 'https://discordapp.com/api/oauth2/token/revoke';

if(get('action') == 'logout') {
    logout($revokeURL, array(
        'token' => session('access_token'),
        'token_type_hint' => 'access_token',
        'client_id' => OAUTH2_CLIENT_ID,
        'client_secret' => OAUTH2_CLIENT_SECRET,
      ));
    unset($_SESSION['access_token']);
    header('Location: ' . $_SERVER['PHP_SELF']);
    die();
}

function logout($url, $data=array()) {
    $ch = curl_init($url);
    curl_setopt_array($ch, array(
        CURLOPT_POST => TRUE,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
        CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded'),
        CURLOPT_POSTFIELDS => http_build_query($data),
    ));
    $response = curl_exec($ch);
    return json_decode($response);
}

Added this to code. Token revocation should work

@Jacobinoo
Copy link

Jacobinoo commented Aug 22, 2021

@Jengas Thank you so much for the token revocation solution! By the way is there anything we can do about token refreshing?

@ThePureCC
Copy link

How do you invite the user who logged in to a server? I've seen other people done it where after the authorization the user automatically joined the specified server(the one where the bot is in). How does that work?

@TeemoCell
Copy link

i was getting Trying to get property 'access_token' of non-object. my problem is: i don't have a ssl auto assigned, i'm using cloudflare so my request doesn't worked, i've fixed it adding curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); later of curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); and sorry my bad english i'm brazilian, good luck to everyone <3

Yeah, this one fixed it for me.

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

@TeemoCell
Copy link

how do I get the person unable to access the page without logging in?

What do you mean?

@laGameTV
Copy link

laGameTV commented Feb 2, 2022

how do I get the person unable to access the page without logging in?

check if the user is logged in. if not die() and return to the login page

@zImSkillz
Copy link

zImSkillz commented Mar 7, 2022

I log in with Discord, but it still doesn't show logged in
EDIT: FIXED

@Zekarant
Copy link

I log in with Discord, but it still doesn't show logged in EDIT: FIXED

Hi bro,
can you explain how you did it please? I would like the user to stay logged in too if possible.And also I have "you are being rate limit" after many f5 is it normal? why i would like to know how to stay connected

@Kryd0s
Copy link

Kryd0s commented Sep 11, 2022

Logout doesn't work unless you move
session_start();
from line 28 up to 15 (above the logout part). I also recommend adding something like
echo '<p><a href="?action=logout">Log out</a></p>"';
at line 72 so you don't have to type "?action=logout" to the URL manually.

Helpful guide to getting started though. Thanks for sharing.

@aidanH39
Copy link

aidanH39 commented Sep 18, 2022

Logout doesn't work unless you move session_start(); from line 28 up to 15 (above the logout part). I also recommend adding something like echo '<p><a href="?action=logout">Log out</a></p>"'; at line 72 so you don't have to type "?action=logout" to the URL manually.

Helpful guide to getting started though. Thanks for sharing.

That only works because your removing the session. What means login will be removed upon refresh as it’s not saved.

if I remember correctly it’s something to do with the end point he’s using to logout. Might have to do a little bit of fiddling with that.
You could also try just setting $_SESSION['access_token'] to null

@Shinsekai7
Copy link

the logout action is written twice at line 16 and line 79
the one at line 16 should be removed

@SirObby
Copy link

SirObby commented Jan 20, 2023

FastCGI sent in stderr: "PHP message: PHP Warning: Undefined property: stdClass::$access_token in /home/sir/dev/php-esports/api/redirect.php on line 17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment