I m trying to get access to the linkedin api but like a lot of people, fail everytime and have this following message of error :
missing required parameters, includes an invalid parameter value, parameter more then once. : Unable to retrieve access token : appId or redirect uri does not match authorization code or authorization code expired
I've cheked the hosting server's timestamp and i revoke and create the token on the app admin before i launch the code (the faster i can due to the short life time of the authorization code given).
Here's my index file and just after the functions i use :
<?php
// VARS
define('API_KEY', 'xxxxxxxxxx');
define('API_SECRET', 'xxxxxxxxxx');
define('REDIRECT_URI', 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']);
define('SCOPE', 'r_basicprofile');
session_name('linkedin');
session_start();
include('lib/functions.php');
// OAuth 2 Control Flow
if (isset($_GET['error'])) {
// LinkedIn returned an error
print $_GET['error'] . ': ' . $_GET['error_description'];
exit;
}
elseif (isset($_GET['code'])) {
// User authorized your application
getAccessToken();
}
else {
if ((empty($_SESSION['expires_at'])) || (time() > $_SESSION['expires_at'])) {
// Token has expired, clear the state
$_SESSION = array();
}
if (empty($_SESSION['access_token'])) {
// Start authorization process
getAuthorizationCode();
}
}
// Congratulations! You have a valid token. Now fetch your profile
$user = fetch('GET', '/v1/people/~:(firstName,lastName)');
print "Hello $user->firstName $user->lastName.";
?>
And the functions :
<?php
function getAuthorizationCode() {
$params = array('response_type' => 'code',
'client_id' => API_KEY,
'scope' => SCOPE,
'state' => uniqid('', true), // unique long string
'redirect_uri' => REDIRECT_URI
);
// Authentication request
$url = 'https://www.linkedin.com/uas/oauth2/authorization?'.http_build_query($params);
// Needed to identify request when it returns to us
$_SESSION['state'] = $params['state'];
// Redirect user to authenticate
header("Location: $url");
exit;
}
function getAccessToken() {
$params = array('grant_type' => 'authorization_code',
'client_id' => API_KEY,
'client_secret' => API_SECRET,
'code' => $_GET['code'],
'redirect_uri' => REDIRECT_URI
);
var_dump($params);
// Access Token request
//$url = 'https://www.linkedin.com/uas/oauth2/accessToken?' . http_build_query($params);
$url = 'https://www.linkedin.com/uas/oauth2/accessToken';
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_POST,true);
curl_setopt($c, CURLOPT_POSTFIELDS, http_build_query($params));
$response = curl_exec($c); // on execute la requete
curl_close($c);
// Native PHP object, please
$token = json_decode($response);
// Store access token and expiration time
$_SESSION['access_token'] = $token->access_token; // guard this!
$_SESSION['expires_in'] = $token->expires_in; // relative time (in seconds)
$_SESSION['expires_at'] = time() + $_SESSION['expires_in']; // absolute time
// DEBUG //
echo 'Retour get access token : </br>';
var_dump($token);
echo '</br>--------------------------</br></br>';
// ! DEBUG //
return true;
}
function fetch($method, $resource, $body = '') {
$params = array('oauth2_access_token' => $_SESSION['access_token'], 'format' => 'json');
// Need to use HTTPS
//$url = 'https://api.linkedin.com' . $resource . '?' . http_build_query($params);
// Tell streams to make a (GET, POST, PUT, or DELETE) request
$url = 'https://api.linkedin.com' . $resource;
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, false);
curl_setopt($c, CURLOPT_POSTFIELDS,http_build_query($params));
$response = curl_exec($c);
curl_close($c);
// DEBUG //
echo 'Retour fetch : </br>';
var_dump($response);
echo '</br>--------------------------</br></br>';
// ! DEBUG //
// Native PHP object, please
return json_decode($response);
}
?>
I tried many things but it never works. If someone see the issue tnaks a lot in advance.
Thanks
I have faced the same problem and my issue was caused by http_build_query() function, http://www.php.net/manual/en/function.http-build-query.php
for some reason it tries to encode the parameters to build a query string that will be used by the Linkedin services, if you try to construct the string manually it will pass and it will work.
and actually I reached this page while searching to figure out if its a PHP version issue or maybe the function http_build_query() take in account some environment variables like encoding and locale settings.
not sure but this fixed my issue.
Related
I am trying to implement a call back method in PHP. I am successfully calling an instagram API to authorise the user but I do not know how to capture the token after the user authorises.
Below is my code:
public function oAuthBasic()
{
$instagramBasic = new InstagramBasicDisplay([
'appId' => 'xxx',
'appSecret' => 'xxx',
'redirectUri' => 'xxx'
]);
session()->forget('instagramErrorMessage');
$faceBookLoginUrl = $instagramBasic->getLoginUrl();
return response()->json(['redirectUrl' => $faceBookLoginUrl]);
}
This successfully brings up the sign in pop up. However after authorisation, how can I capture the user access token?
Any help is greatly appreciated.
I managed to fix the issue with the help of #CBore's comment:
Created a new route in my web.php
Route::get('linkinstagramBasic','InstagramController#linkBasic')->name('instagram.linkBasic');
Included the URL under Valid OAuth Redirect URIs on facebook app settings page.
Finally wrote the callback:
/*
* Function that works as the call back after Instagram basic display api authorisation
* Get the code and call access_token API
* AUTHOR : DON
* DATE : 12/10/2022
*/
public function linkBasic(InstagramLinkRequest $instagramRequest) {
if (isset($_GET['code'])) {
// Get the OAuth callback code
$code = $_GET['code'];
$ig_atu = "https://api.instagram.com/oauth/access_token";
$ig_data = [];
$ig_data['client_id'] = Config::get('instagram_basic.app_id');
$ig_data['client_secret'] = Config::get('instagram_basic.app_secret');
$ig_data['grant_type'] = 'authorization_code';
$ig_data['redirect_uri'] = Config::get('instagram_basic.redirect_uri');
$ig_data['code'] = $code;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ig_atu);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($ig_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$ig_auth_data = curl_exec($ch);
curl_close($ch);
$ig_auth_data = json_decode($ig_auth_data, true);
dd($ig_auth_data);
//$accessTok = $ig_auth_data['access_token'];
//$UID = $ig_auth_data['user_id'];
//echo "<script>window.close();</script>";
}
}
I am using Snapchat login kit web in my PHP project. I successfully connected the user-authorization page. After giving authorization I am getting code and state GET variables in my redirect_uri page. I need an access token, but when I proceed next step, I got an error in response,
1.invalid_grant
2.invalid code_verifier
here are my login page and redirect page code:
--Login page---
<?php
if(isset($_POST['login']))
{
$url="https://accounts.snapchat.com/accounts/oauth2/auth";
$clientId="my_client_id_get_from_snapchat_app_setting";
$client_secret="my_client_secrect_get_from_snapchat_app_setting";
$redirectUri="https://Snapreport.org/Redirect.php";
$method= "GET";
$str = 'arifusingsnapchat';
$state= base64_encode($str);
$code_verifier = "arifusingsnapchat225678909fghh8df777634567890";
$code_verifier_hash = hash("sha256",$code_verifier);
$code_challenge = base64_encode($code_verifier_hash);
$scopeList= array("https://auth.snapchat.com/oauth2/api/user.display_name",
"https://auth.snapchat.com/oauth2/api/user.bitmoji.avatar",
"https://auth.snapchat.com/oauth2/api/user.external_id"
);
$scope = implode($scopeList," ");
$stringArr = array(
"client_id" => $clientId,
"client_secret" => $client_secret,
"redirect_uri" => $redirectUri,
"code_challenge" => $code_challenge,
"code_challenge_method"=> "S256",
"response_type" => "code",
"scope" => $scope,
"state" => $state );
$query= http_build_query($stringArr, '', '&');
$request = $url."?".$query;
header("Location:".$request);
}
?>
--Redirect_uri page--
<?php
if(isset($_GET['code']) && isset($_GET['state']))
{
$code= $_GET['code'];
$state=$_GET['state'];
$url="https://accounts.snapchat.com/accounts/oauth2/token";
$clientId="my_client_id_get_from_snapchat_app_setting";
$client_secret="my_client_secrect_get_from_snapchat_app_setting";
$redirect_uri="https://Snapreport.org/Redirect.php";
$header = base64_encode($clientId.":".$client_secret);
$code_verifier = "arifusingsnapchat225678909fghh8df777634567890";
$payloaded_url=$url."?client_id=".$clientId."&client_secret=".$client_secret."&grant_type=authorization_code&redirect_uri=".$redirect_uri."&code=".$code."&code_verifier=".$code_verifier;
$ch = curl_init($payloaded_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type' => 'application/json',
'Authorization'=> 'Basic '.$header
));
// execute!
$response = curl_exec($ch);
// close the connection, release resources used
curl_close($ch);
$res= json_decode($response);
// do anything you want with your response
echo "<pre>";
var_dump($res);
echo "</pre>";
}
Snapchat Login Kit Web Documentation
Snapchat Login Kit Web Documentationhttps://kit.snapchat.com/docs/login-kit-web
On your login page:
$code_verifier_hash = urlencode(pack('H*', hash('sha256', $code_verifier)))
You should probably also use a B64 safe url encoder like the one here:
https://github.com/F21/jwt/blob/master/JWT/JWT.php#L120
I have a sign-in page that refers a user to GitHub for authentication.
After authenticating GitHub successfully returns the code and status as GET parameters to my sign-in page.
Is there a way to get the GitHub user email, name, and handle after getting the access_token?
if(get('action') == 'login')
{
// Generate a random hash and store in the session for security
$_SESSION['state'] = hash('sha256', microtime(TRUE) . rand() . $_SERVER['REMOTE_ADDR']);
unset($_SESSION['access_token']);
$params = array(
'client_id' => OAUTH2_CLIENT_ID,
'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
'scope' => 'user',
'state' => $_SESSION['state']
);
// Redirect the user to Github's authorization page
header('Location: ' . $authorizeURL . '?' . http_build_query($params));
die();
}
// When Github redirects the user back here, there will be a "code" and "state" parameter in the query string
if (get('code'))
{
// Verify the state matches our stored state
if (!get('state') || $_SESSION['state'] != get('state')) {
header('Location: ' . $_SERVER['PHP_SELF']);
die();
}
// Exchange the auth code for a token
$token = apiRequest($tokenURL, array(
'client_id' => OAUTH2_CLIENT_ID,
'client_secret' => OAUTH2_CLIENT_SECRET,
'redirect_uri' => 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'],
'state' => $_SESSION['state'],
'code' => get('code')
));
echo var_dump($token) ."<br>";
echo json_encode($token);
$_SESSION['access_token'] = $token->access_token;
header('Location: ' . $_SERVER['PHP_SELF']);
}
}
function apiRequest($url, $post = FALSE, $headers = array())
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
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;
}
You need to call the Github API with the access token to access the current User
So if you already have the access_token available and it's saved sucessfully in $_SESSION['access_token'] - it will be used automatically for all further requests done by apiRequest() Method Calls
$user = apiRequest("https://api.github.com/user');
var_dump($user);
// $user->name should be available in response
When I tested your code - the apiRequest-Method returned an error (var_dump($response))
Request forbidden by administrative rules. Please make sure your request has a User-Agent header (http://developer.github.com/v3/#user-agent-required). Check https://developer.github.com for other possible causes.
Just add a User-Agent to the headers[] array in the method (e.g. right below the added Accept: Header)
$headers[] = 'User-Agent: PHP Api Call';
... and your API-Call will work ;)
Edit: because you set 'scope' => 'user', in your initial Auth-Request - you requested Access to the User-Data - but nothing more (see OAuth-App-Scopes if you need additional permissions/info)
I'm trying to revoke the access from a web app. This is my code:
When the user do login:
$scriptUri = "http:...";
$client = new Google_Client();
$client->setAccessType('online');
$client->setApplicationName('xxx');
$client->setClientId('xxx');
$client->setClientSecret('xxx');
$client->setRedirectUri($scriptUri);
$client->setDeveloperKey('xxx'); // API key
$client->setScopes(array('https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile'));
$oauth2 = new Google_Service_Oauth2($client);
if (isset($_GET['code']) && isset($_GET["google"])){
$client->authenticate($_GET['code']);
$token = $client->getAccessToken();
$client->setAccessToken($token);
$_SESSION['google_token'] = $token;
}
And here is the code when I want to revoke the app:
$ch = curl_init("https://accounts.google.com/o/oauth2/revoke?token=".$_SESSION['google_token'].";");
curl_exec($ch);
curl_close($ch)
The result is a NOT FOUND page saying The requested URL /v2/{ "error" : "invalid_token"} was not found on this server.
I'm not sure if this is the correct way to revoke the access.
Thanks.
I tried your code and had the same error.
Take a look at how you have concatenated the strings at:
$ch = curl_init("https://accounts.google.com/o/oauth2/revoke?token=".$_SESSION['google_token'].";");
PHP easily lets committing syntax errors over concatenated strings. The fixed that worked for me was:
$RevokeTokenURL="https://accounts.google.com/o/oauth2/revoke?token=".$_SESSION['google_token'];
$ch = curl_init($RevokeTokenURL);
And in case you need it, my complete code is:
if(isset($_GET['action']) && $_GET['action'] == 'logout') {
session_destroy();
header('Location:'.$RedirectURL);
$RevokeTokenURL="https://accounts.google.com/o/oauth2/revoke?token=".$_SESSION['google_token'];
$ch = curl_init($RevokeTokenURL);
curl_exec($ch);
curl_close($ch);
}
I think this should work..
$revokeURL = "https://accounts.google.com/o/oauth2/revoke?token=".$access_token;
$ch = curl_init();
$options = array(
CURLOPT_URL => $revokeURL,
CURLOPT_HEADER => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => true, //verify HTTPS
CURLOPT_SSL_CIPHER_LIST => 'TLSv1'); //remove this line if curl SSL error
curl_setopt_array($ch, $options); //setup
$response = curl_exec($ch); //run
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); //get HTTP code
if ($httpCode == 200)
{
echo "Success"; // .$response;
}
else
{
echo "Error : ".$httpCode."__".curl_error($ch);
}
curl_close($ch);```
Based on https://developers.google.com/accounts/docs/OAuth2WebServer#tokenrevoke
Can you tell me with steps how can I do a like button in my site (php) to like a page photo on facebook?
I know that I have to use the GRAPH API and have to do the POST via HTTP to /likes .. but I dont know how can I do it with PHP code.
Somebody have an example?
Thank you
As long as you have obtained the publish_stream permission from the user you can like any photo you need to. If you are attempting to like the photo as a page be sure you have an access_token for the page (obtained via the /accounts connection on the user account).
Once you have the access token the like is as simple as issuing an HTTP POST to a URL that looks similar to this:
https://graph.facebook.com/PHOTO_ID/likes?access_token=ACCESS_TOKEN
Photo_ID = Photo ID in Facebook
Access_Token = Access token obtained from Facebook with the publish_stream permission.
UPDATE
PHP Sample Code based on PHP Form CURL Post
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/PHOTO_ID/likes");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, true);
$data = array(
'Access_Token' => 'token_value'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
I would check this though as I'm not sure how accurate it is since I don't normally code PHP. In any manner, the post should be a raw HTTP POST request.
Fabio here is the php post snippet that i was able to get working. Snippet includes a curl to get application access token and the api post to like an object, in this case a post on my app.
The Sample post is here: Shows the post to be liked
https://shawnsspace.com/plugins/TimeLinePost.php?pageid=135669679827333&postid=135669679827333_151602784936066&type=feed&fh=750
The Like Page is here: Should Return whether the user likes or not, or login if not connected.
https://shawnsspace.com/plugins/TheLike.php?postid=135669679827333_151602784936066
Getting the Application Access Token.
function GetCH(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&grant_type=client_credentials");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT_MS,20000);
if(substr($url,0,8)=='https://'){
// The following ensures SSL always works. A little detail:
// SSL does two things at once:
// 1. it encrypts communication
// 2. it ensures the target party is who it claims to be.
// In short, if the following code is allowed, CURL won't check if the
// certificate is known and valid, however, it still encrypts communication.
curl_setopt($ch,CURLOPT_HTTPAUTH,CURLAUTH_ANY);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
}
$sendCH = curl_exec($ch);
curl_close($ch);
return $sendCH;
};
$app_access_token = GetCH();
Looking in url for postid parameter then liking id
if($_GET['postid']){
$postid = $_GET['postid'];
}else{
$postid = '135669679827333_151602784936066';
}
if($user){
$pageLike = $facebook->api('/'.$postid.'/likes?access_token='.$access_token.'&method=post', 'POST');
}
You can get permissions by building an array of perms for login url. below i am requesting read_stream,publish_stream,publish_actions,offline_access in the scope for permissions.
NOTE: app access token needed for logout url.
<?php
$url = (!empty($_SERVER['HTTPS'])) ? 'https://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] : 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
require './src/facebook.php';
$facebook = new Facebook(array(
'appId' => 'APPID',
'secret' => 'APP-SECRET',
'cookie' => true, // enable optional cookie support
));
$user = $facebook->getUser();
if ($user) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$user_profile = $facebook->api('/me');
//$pageInfo = $facebook->api('/'.$pageid.'?access_token='.$_SESSION['fb_112104298812138_access_token].');
//$pageInfoUser = $user_profile[id];
} catch (FacebookApiException $e) {
error_log($e);
$user = null;
}
}
/* */
if ($user) {
$logoutUrl = $facebook->getLogoutUrl();
} else {
$params = array(
scope => 'read_stream,publish_stream,publish_actions,offline_access',
redirect_uri => $url
);
$loginUrl = $facebook->getLoginUrl($params);
}
$access_token = $_SESSION['fb_135669679827333_access_token'];
?>
<?php
if(!$user){
echo ' : Login ';
}else{
echo 'Logout';
}
?>