Soundcloud API (PHP) returns "invalid grant" - php

We are using the code below to try to upload tracks from our WordPress site to SoundCloud through PHP. MP3 tracks are already on our server before running this script.
function upload_soundcloud()
{
//App credentials. Create one at http://soundcloud.com/you/apps
define('API_URL', 'https://api.soundcloud.com');
define('CLIENT_ID', '$client_id');
define('CLIENT_SECRET', '$client_secret');
//User credentials
define('EMAIL', '$email');
define('PASSWORD', '$password');
//Path to MP3 file to upload
define('FILE', ABSPATH . '/wp-content/uploads/path/to/file.mp3');
class SoundcloudAPI {
private $url;
private $clientID;
private $secret;
private $accessToken;
public function __construct($url, $clientID, $secret) {
$this->url = $url;
$this->clientID = $clientID;
$this->secret = $secret;
}
public function auth($username, $password) {
$url = $this->url . '/oauth2/token';
$data = array(
'client_id' => $this->clientID,
'client_secret' => $this->secret,
'grant_type' => 'password',
'username' => $username,
'password' => $password
);
$result = $this->request($url, $data, 'POST');
$this->accessToken = $result->access_token;
return $result;
}
public function upload($title, $path) {
$url = $this->url . '/tracks';
$data = array(
'oauth_token' => $this->accessToken,
'track[title]' => $title,
'track[asset_data]' => new CurlFile(realpath($path), 'audio/mpeg'),
);
$result = $this->request($url, $data, 'POST');
return $result;
}
private function request($url, $data, $method) {
$curl = curl_init();
if ($method === 'POST') {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
} else {
$url .= '?' . http_build_query($data);
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
$result = json_decode(curl_exec($curl));
curl_close($curl);
return $result;
}
}
$soundCloud = new SoundcloudAPI(API_URL, CLIENT_ID, CLIENT_SECRET);
$resultAuth = $soundCloud->auth(EMAIL, PASSWORD);
$resultUpload = $soundCloud->upload('Test', FILE);
echo '<pre>';
print_r($resultAuth);
print_r($resultUpload);
echo '</pre>';
}
This is what we are getting as a response:
stdClass Object
(
[error] => invalid_grant
)
Does anyone know why this might be happening? (the strangest part is that it was actually working 2 days ago, but then just stopped working and I feel like I am going crazy).

Try and save the access token and refresh token between requests (for example, in a local file or database) and reusing it. The rate-limit only seems to be on the /oauth2/token endpoint when using a username and password.
Once your access token has expired, you can use the refresh token to get a new one by making a request to /oauth2/token with:
'grant_type': 'refresh_token',
'client_id': <your client id>,
'client_secret': <your client secret>,
'refresh_token': <previous refresh token>

Related

Discord oauth2 with php

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.

cURL PUT/PATCH request with Discord API resulting in error 400 (BAD REQUEST)

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.

getting Error: invalid_client in instamojo

I am integrating instamojo payment-gateway in ionic at the server side i putted below code for access token
<?php
class Instamojo
{
private $client_id;
private $client_secret;
private $url = "https://api.instamojo.com/oauth2/token/";
private $env = "production";
public function __construct($client_id, $client_secret)
{
$this->client_id = $client_id;
$this->client_secret = $client_secret;
}
public function getToken() {
if (substr( $this->client_id, 0, 5 ) === "test_") {
$this->url = "https://test.instamojo.com/oauth2/token/";
$this->env = "test";
}
$curl = curl_init($this->url);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, rawurldecode(http_build_query(array(
'client_id' => $this->client_id,
'client_secret' => $this->client_secret,
'grant_type' => 'client_credentials'
))));
$json = json_decode(curl_exec($curl));
if(curl_error($curl))
{
echo 'error:' . curl_error($curl);
}
if (isset($json->error)) {
return "Error: " . $json->error;
throw new \Exception("Error: " . $json->error);
}
$this->token = $json;
return $this->env . $json->access_token;
}
}
$instamojo = new Instamojo("Client ID", "Client Secret");
echo $instamojo->getToken();
?>
when i run this code in url getting error 'Error: invalid_client'.how to get Client ID and Client Secret from instamojo account. In instamojo i am getting only API Key, Auth Token and Salt in api and plugin section.
Solved.
1. Go to App & Plugin Section under instamojo account.
2. Click on Generate Credentials Button
3. Choose Ionic-SDK under Platform/Framework then Click on Generate
4. Credentials Button. Got Client ID and Client Secret.

why an http post request isn't working in guzzle but works fine in curl

i am working on sending a request to github o auth to fetch the access token of a user and tried working with guzzle but the response didn't have any value i don't know why , in the other hand when i used curl it worked fine and returned the access token successfully ,
i am using form_parms from guzzle to set the fields
here the guzzle example
public function fetchGithubToken(\Illuminate\Http\Request $request, $code)
{
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://github.com/login/oauth/access_token', [
'form_params' => ['client_id' => env('GITHUB_CLIENTID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'code' => $code],
]);
Log::error(print_r($response, true));
return $response;
}
here the is the curl example
public function post_to_url($url, $data)
{
$fields = '';
foreach ($data as $key => $value) {
$fields .= $key . '=' . $value . '&';
}
rtrim($fields, '&');
$post = curl_init();
curl_setopt($post, CURLOPT_URL, $url);
curl_setopt($post, CURLOPT_POST, count($data));
curl_setopt($post, CURLOPT_POSTFIELDS, $fields);
curl_setopt($post, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($post);
curl_close($post);
return $result;
}
public function fetchGithubToken(\Illuminate\Http\Request $request, $code)
{
$data = ['client_id' => env('GITHUB_CLIENTID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'code' => $code];
$response = $this->post_to_url("https://github.com/login/oauth/access_token", $data);
Log::info(print_r($response, true));
return $response;
}
You'll have to add the authentication in cURL. You'll have to use the below statement as github needs authentication:
curl_setopt($process, CURLOPT_USERPWD, $data['username'] . ":" . $data['$password']);
Hope this helps.

PHP retrieve POST result

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' => '{******-****-****-******-*****}',

Categories