I'm trying to create a sign in system using disocrd's oauth2.
This is my code:
<?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', 'XXXXXXXXXXXXXXXXXXXXXX'); //Your client Id
define('OAUTH2_CLIENT_SECRET', 'XXXXXXXXXXXXXXXXXXXXXX'); //Your secret client code
$authorizeURL = 'https://discordapp.com/api/oauth2/authorize';
$tokenURL = 'https://discordapp.com/api/oauth2/token';
$apiURLBase = 'https://discordapp.com/api/users/#me';
session_start();
// Start the login process by sending the user to Discord's authorization page
if(get('action') == 'login') {
// Redirect the user to Discord's authorization page
header('Location: https://discord.com/api/oauth2/authorize?client_id=873917693953191946&redirect_uri=http%3A%2F%2Fbouncerbot.go-atcode.com%2Fauth.php&response_type=code&scope=identify%20email%20connections%20guilds%20gdm.join%20guilds.join%20rpc%20rpc.notifications.read%20rpc.voice.read%20rpc.voice.write');
die();
}
// When Discord redirects the user back here, there will be a "code" and "state" parameter in the query string
if(get('code')) {
$token = apiRequest($tokenURL, array(
"grant_type" => "authorization_code",
'client_id' => 'XXXXXXXXXXXXXXXX', //censored
'client_secret' => 'XXX-XXXXXXXXXXXXXXXXXXX',
'redirect_uri' => 'http://bouncerbot.go-atcode.com/auth.php',
'code' => get('code')
));
$logout_token = $token->access_token;
$_SESSION['access_token'] = $token->access_token;
header('Location: ' . $_SERVER['PHP_SELF']);
}
?><script> console.log(<? echo $user->username?> )</script><?
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>Log In</p>';
}
if(get('action') == 'logout') {
// This must to logout you, but it didn't worked(
$params = array(
'access_token' => $logout_token
);
// Redirect the user to Discord's revoke page
header('Location: https://discordapp.com/api/oauth2/token/revoke' . '?' . http_build_query($params));
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 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;
}
?>
The problem is that when I go to authorize on discord and then discord redirects me back to auth.php, the token is not fetched and therefore remains:
Not logged in Log In
I couldn't figure out the cause of the problem so I asked a question. This is the login page: http://bouncerbot.go-atcode.com/auth.php
1st) Redirection is working fine because you are using
'redirect_uri' => 'http://bouncerbot.go-atcode.com/auth.php',
That's why to redirect to auth.php
2nd) You have to define the same redirection URL on discord application like this:
3rd) Create a code generation page and redirection page, you can either both on same page or you can create both seprate pages.
As I am testing with creating 2 pages
1. The request for code (disocrd.php)
<?php
define('OAUTH2_CLIENT_ID', '882143362046640112');
$redirectURL = 'https://localhost/test_project/disocrd_responce.php';
$params = array(
'client_id' => OAUTH2_CLIENT_ID,
'redirect_uri' => $redirectURL,
'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();
?>
After hit this page, the page will auto-redirect to https://localhost/test_project/disocrd_responce.php with code
2. Generate token by using code (disocrd_responce.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);
$code = isset($_REQUEST['code']) ? $_REQUEST['code'] : '';
define('OAUTH2_CLIENT_ID', '882143362046640112');
define('OAUTH2_CLIENT_SECRET', 'hYvpAl_heUJNC0veaoraMxNhJL2fgHVU');
$authorizeURL = 'https://discord.com/api/oauth2/authorize';
$tokenURL = 'https://discord.com/api/oauth2/token';
$redirectURL = 'https://localhost/test_project/disocrd_responce.php';
if(get('code')) {
session_start();
// 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' => $redirectURL,
'code' => get('code')
));
$logout_token = $token->access_token;
$_SESSION['access_token'] = $token->access_token;
echo "<pre>"; print_r($token); exit; // get token properly
// header('Location: ' . $_SERVER['PHP_SELF']);
}
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(isset($_SESSION['access_token']))
$headers[] = 'Authorization: Bearer ' . $_SESSION['access_token'];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response);
}
function get($key, $default=NULL) {
return array_key_exists($key, $_GET) ? $_GET[$key] : $default;
}
?>
When I print tokens like this:
echo "<pre>"; print_r($token); exit;
We got token properly like this:
stdClass Object
(
[access_token] => 'FBLOYotKRxe0uO7KJcS8mfce5z9YEE'
[expires_in] => 604800
[refresh_token] => FxlsNH06OHcbMCJlAZhWzbi4DsIjUO
[scope] => identify guilds
[token_type] => Bearer
)
Note: I have a change customer id and token by security point of view
You get the answer in the redirect URL when you test it:
http://bouncerbot.go-atcode.com/auth.php?error=invalid_scope&error_description=The+requested+scope+is+invalid%2C+unknown%2C+or+malformed.
Try only ask for email and see if it works. If it does keep adding stuff until you find what causes the issue.
Related
I am using php, oAuth2 (from Discord) and cURL to connect to the Discord API, where after the user authorizes the connection, he will automatically enter the server (guild) with a specific nickname and role, but if the user is already on the server, just changes the nickname and adds the role automatically.
I've had success with Auth2, so I'm looking at it. He returns everything I wanted, using identy, guilds.join and email scopes. However, in the process of adding the member to the server or editing the member, it returns error 400 (BAD REQUEST). And I really don't have a clue what it is, so what I'm seeing seems to be all right.
The strange thing is that yesterday, it was working only in the anonymous browser tab, but today, it even worked in my normal browser, but for other users, it does not work.
To tell you the truth, I've already got error 400 and 403, it's really very confusing.
My complete code:
class Discord extends CodonModule {
private static $OAUTH2_CLIENT_ID = 'CLIENT_ID';
private static $OAUTH2_CLIENT_SECRET = 'CLIENT_SECRET';
private static $BOT_TOKEN = 'CLIENT_TOKEN';
private static $guildID = 453922275248265175;
private static $roleID = 45129328442467690261;
public static $authorizeURL = 'https://discordapp.com/api/oauth2/authorize';
public static $tokenURL = 'https://discordapp.com/api/oauth2/token';
public static $apiURLBase = 'https://discordapp.com/api/users/#me';
public function login() {
$params = array(
'client_id' => Discord::$OAUTH2_CLIENT_ID,
'redirect_uri' => 'LINK/request',
'response_type' => 'code',
'scope' => 'identify guilds.join email'
);
// Redirect the user to Discord's authorization page
header('Location: https://discordapp.com/api/oauth2/authorize' . '?' . http_build_query($params));
die();
}
public function request() {
if($this->get('code')) {
// Exchange the auth code for a token
$token = $this->apiRequest(Discord::$tokenURL, array(
"grant_type" => "authorization_code",
'client_id' => Discord::$OAUTH2_CLIENT_ID,
'client_secret' => Discord::$OAUTH2_CLIENT_SECRET,
'redirect_uri' => 'LINK/request',
'code' => $this->get('code')
));
$logout_token = $token->access_token;
$_SESSION['access_token'] = $token->access_token;
header('Location: ' . $_SERVER['PHP_SELF']);
}
if($this->session('access_token')) {
$user = $this->apiRequest(Discord::$apiURLBase);
$userID = intval($user->id);
$userTAG = $user->username.'#'.$user->discriminator;
$newName = 'Teste';
$params = '{"access_token": "'.$_SESSION['access_token'].'", "nick": "'.$newName.'", "roles": ['.Discord::$roleID.']}';
$code = $this->membersRequest($userID, 'PUT', $params);
// The pilot is not on the guild
if($code == 201) {
$this->show('discord/discord_success.php');
return true;
} elseif($code == 204) {
// The pilot is already on the server
$params2 = '{"nick": "'.$newName.'", "roles": ['.Discord::$roleID.']}';
$http = $this->membersRequest($userID, 'PATCH', $params2);
if($http == 204) {
$this->show('discord/discord_success.php');
return true;
} else {
$this->show('discord/discord_error.php');
return false;
}
} else {
$this->show('discord/discord_error.php');
return false;
}
} else {
$this->index();
}
}
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($this->session('access_token'))
$headers[] = 'Authorization: Bearer ' . $this->session('access_token');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
return json_decode($response);
}
function membersRequest($userID, $post, $params) {
$membersURL = 'https://discordapp.com/api/guilds/'.Discord::$guildID.'/members/';
$url = $membersURL.$userID;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $post);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Authorization: Bot ' . Discord::$BOT_TOKEN,
'Content-Type: application/json'
));
curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
return $http;
}
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;
}
}
Any help would be much appreciated. Thank you so much.
I implement OAUTH authentication. I'm sending a POST request to an API. But something is wrong in my code. I get error 404 back. can someone help me. this API does not support ClientSecret.
this is my Code
<?php
$callback_uri = "http://localhost/zeiterfassung/" ;
$client_id = "2371031349-3075189699-483870032-1896673008" ;
$code = $_GET['code'];
$resourc = "http://localhost/zeiterfassung/";
if (isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://adfs3int.fds.metro.info/oauth2/token';
$params = array(
"code" => $code,
"client_id" => $client_id,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"grant_type" => "authorization_code"
);
$ch = curl_init();
curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($info['http_code'] === 200) {
header('Content-Type: ' . $info['content_type']);
return $output;
} else {
return 'An error happened';
}
} else {
$url = "https://adfs3int.fds.metro.info/adfs/oauth2/authorize";
$params = array(
"response_type" => "code",
"client_id" => $client_id,
"redirect_uri" => $callback_uri,
"resource" => $resourc
);
$request_to = $url . '?' . http_build_query($params);
header("Location: " . $request_to);
}
?>
404 is a client site error and say's that you have done something wrong - it means that what you are looking for is not there where are you looking.
It's like, you searching socks in you closet but you cant find the socks cause your socks aren't in the closet.
I looks like the requesting api is hosted on your localhost, maybe the api is in an ohter folder?
I am using the following code to access an OpenId system and request a bearer token.
if (isset($_GET['code'])) {
// try to get an access token
$code = $_GET['code'];
$url = 'https://3rdpartydomain.com/connect/token';
$params = array(
"code" => $code,
"client_id" => CLIENTID,
"client_secret" => CLIENTSECRET,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"grant_type" => "authorization_code"
);
$ch = curl_init();
curl_setopt($ch, constant("CURLOPT_" . 'URL'), $url);
curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
curl_setopt($ch, constant("CURLOPT_" . 'POSTFIELDS'), $params);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if ($info['http_code'] === 200) {
header('Content-Type: ' . $info['content_type']);
return $output;
} else {
return 'An error happened';
}
} else {
$url = "https://3rdpartydomain.com/connect/token";
$params = array(
"response_type" => "code",
"client_id" => CLIENTID,
"redirect_uri" => 'http://' . $_SERVER["HTTP_HOST"] . $_SERVER["PHP_SELF"],
"scope" => "openid"
);
$request_to = $url . '?' . http_build_query($params);
header("Location: " . $request_to);
}
However, I'm getting the following message:
{"Message":"The requested resource does not support http method 'GET'."}
Can someone help identify the correct to my code please?
Thanks!
Add these:
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
There is probably a change of requested method in the redirect from your IdP. I've seen this issue when I was testing my OIDC with curl -XPOST. The workaround was to remove that request type specification. Try to comment your line: curl_setopt($ch, constant("CURLOPT_" . 'POST'), true);
I'm using the following PHP class which I found on GitHub: Twitch oauth class
So I've been creating the Authentification site, which will let you authentificate your twitch account and redirect you to another site using the following url:
http://website.com/twitch/dashboard.php?code=xxxxxxx&scope=user_read+channel_read+chat_login+user_follows_edit+channel_editor+channel_commercial+channel_check_subscription
Now I've used the following code to receive the access_token:
<?php
$ttv_code = $_GET['code'];
$access_token = $twitchtv->get_access_token($ttv_code);
$user_name = $twitchtv->authenticated_user($access_token);
if(isset($user_name)) {
echo 'Thank you ' . $user_name . '! Authentication Completed!';
}else{
echo 'Authentification failed!';
}
?>
But sadly there's no response coming back from the function. The function looks like the following:
function get_access_token($code) {
$ch = curl_init($this->base_url . "oauth2/token");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, 1);
$fields = array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'authorization_code',
'redirect_uri' => $this->redirect_url,
'code' => $code
);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
$data = curl_exec($ch);
$response = json_decode($data, true);
return $response["access_token"];
}
Does anyone have a idea what causes this mistake? I would appreciate any kind of help.
I'm trying to create an App for 'Exact Online' but i'm having a little bit of a problem with the OAuth security authentication
https://developers.exactonline.com/#OAuth_Tutorial.html%3FTocPath%3DAuthentication%7C_____2
After making my first authentication request and logging in I recieve a code.
With this code I can obtain an Token for making api calls.
if (!empty($_GET["code"])){
$code = $_GET["code"];
getting the code works so far. But when I try to make a new request (for the token) I get no response data.
My Code is as follows:
$data = array(
'code' => $code,
'redirect_uri' => 'http://****/asdf2.php',
'grant_type' => 'authorization_code',
'client_id' => '******-****-****-******-*****',
'client_secret' => '*********'
);
// Create map with request parameters
// Build Http query using params
$query = http_build_query ($data);
// Create Http context details
$contextData = array (
'method' => 'POST',
'header' => "Connection: close\r\n".
"Content-Length: ".strlen($query)."\r\n",
'content'=> $query );
// Create context resource for our request
$context = stream_context_create (array ( 'http' => $contextData ));
// Read page rendered as result of your POST request
$result = file_get_contents (
'https://start.exactonline.nl/api/oauth2/token', // page url
false,
$context);
// Server response is now stored in $result variable so you can process it
if (!empty($result)){
echo "success";
}else{
echo "no result";
}
}else {
echo "error";
}
$result is always empty, what could be the problem. I've checked my client_id and secret multiple times.
After changing it to cUrl it still didn't work:
$result = get_oauth2_token($code);
// Server response is now stored in $result variable so you can process it
if (!empty($result)){
echo "success";
}else{
echo "no result";
}
}else {
echo "error";
}
/*
Function
*/
function get_oauth2_token($code) {
global $client_id;
global $client_secret;
global $redirect_uri;
$oauth2token_url = "https://start.exactonline.nl/api/oauth2/token";
$clienttoken_post = array(
'code' => $code,
'redirect_uri' => 'http://*****/asdf2.php',
'grant_type' => 'authorization_code',
'client_id' => '{*******}',
'client_secret' => '******'
);
$curl = curl_init($oauth2token_url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $clienttoken_post);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$json_response = curl_exec($curl);
curl_close($curl);
$authObj = json_decode($json_response);
if (isset($authObj->refresh_token)){
//refresh token only granted on first authorization for offline access
//save to db for future use (db saving not included in example)
global $refreshToken;
$refreshToken = $authObj->refresh_token;
}
$accessToken = $authObj->access_token;
return $accessToken;
}
The documentation shows that client_id should be inside curly braces. So I think it should be:
'client_id' => '{******-****-****-******-*****}',