Can't Validate Google Access Token (wrong number of segments) - php

I have very simple code directly from Google's website
$client = new Google_Client(['client_id' => $CLIENT_ID]);
$payload = $client->verifyIdToken($id_token);
if ($payload) {
$userid = $payload['sub'];
echo $userid;
} else {
// Invalid ID token
echo "error";
}
I get the following error(s):
<b>Fatal error</b>: Uncaught exception 'UnexpectedValueException' with message 'Wrong number of segments' in /../vendor/firebase/php-jwt/src/JWT.php:79
Stack trace:
#0 /../vendor/google/apiclient/src/Google/AccessToken/Verify.php(103): Firebase\JWT\JWT::decode('ya29.GlzbAwEXTe...', '-----BEGIN PUBL...', Array)
#1 /../vendor/google/apiclient/src/Google/Client.php(713): Google_AccessToken_Verify->verifyIdToken('ya29.GlzbAwEXTe...', '1074005180734-g...')
#2 /../pages/auth/session.php(7): Google_Client->verifyIdToken('ya29.GlzbAwEXTe...')
Does anyone know why this is?

Answering this question because the other one is too short and vague.
Instead of passing the ID returned by profile.getId(), pass the one returned by googleUser.getAuthResponse().id_token as your id_token (the id field of the POST request you use to send the user's id over to your server).
A great tip for any developer: If you think you did everything you were supposed to do, and it is working for them, but it is not working for you, then you did not do everything you were supposed to do.

I used access_token instead of id_token when passing it in POST

I had the same issue and didn't get any fix. I had to change the way I was fetching user info. Instead of using $client->verifyIdToken(); I have used the service class this way :
$authService=new Google_Service_Oauth2($client);
if($client->getAccessToken()){
$data=$authService->userinfo->get();
}
So, to get the current user email, I used $email=data['email'];.
Hope this works!

Related

Error validate an ID token in PHP - Google API

I am using the following example backend-auth Google
<?php
require_once 'Google/vendor/autoload.php';
$CLIENT_ID = "xxxxxxxxxx";
// Get $id_token via HTTPS POST.
$client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend
$payload = $client->verifyIdToken($id_token);
if ($payload) {
$userid = $payload['sub'];
// If request specified a G Suite domain:
//$domain = $payload['hd'];
} else {
// Invalid ID token
}
?>
I have already created the credentials, API, and OAUTH2
API_KEY: AIzaAsDfGuYn6nk9761kvnwMxns-PPeO1Ka1YsA
CLIENT_ID: 15123456862-94jrd0d2lis29lbl6dekpk0fp4otgm8r.apps.googleusercontent.com
CLIENT_SECRET: qertf3l3UfgdhjiWEREZI8xN
But it generates the following error:
Notice: Undefined variable: id_token in C:\Adsense\index.php on line 10
Fatal error: Uncaught LogicException: id_token must be passed in or set as part of setAccessToken in C:\Adsense\Google\vendor\google\apiclient\src\Client.php:784 Stack trace: #0 C:\Adsense\index.php(10): Google\Client->verifyIdToken(NULL) #1 {main} thrown in C:\Adsense\Google\vendor\google\apiclient\src\Client.php on line 784
I have searched this forum in the google documentation and in the google console panel but I cannot find a fixed token or how to create it, I cannot find references
https://oauth2.googleapis.com/tokeninfo?id_token=XXXXX
It's a bit of an old post, but for anyone like me and the OP struggling with this, it's actually quite a simple solution.
The example code has a commented out line that reads
// Get $id_token via HTTPS POST.
You actually have to write this code. Using the worked examples from Google, the JavaScript function passes the authentication token as idtoken.
$id_token = $_POST['idtoken'];
Will do the trick. You'll probably want to perform some basic error checking, for example,
if (isset($_POST['idtoken'])){
$id_token = $_POST['idtoken'];
$payload = $client->verifyIdToken($id_token);
...

Able to authenticate with DocuSign PHP SDK, but createEnvelope method fails ('[400] Error connecting to the API')

I am attempting to send an envelope to a user like so:
$envelope_status = $this->envelopeApi->createEnvelope($this->accountId, $envelope, null);
But I get this error:
Exception: exception 'DocuSign\eSign\ApiException' with message '[400] Error connecting to the API (https://demo.docusign.net/restapi/v2/accounts/1687539/envelopes)' in /srv/www/vhosts/redacted/pages/test/docusign/sdk/docusign-php-client-master/src/ApiClient.php:250
Note that I am able to successfully poll the API for my Account ID after having successfully logged in, so the problem must lie elsewhere. I am attaching a link to a var_dump() of the $envelope here. I suspect I must be messing up one of the steps creating the envelope.
Thank you!
EDIT: for reference this is where I was messing up. When $index == 0, setDocumentId() would fail - Document IDs start at 1.
function addDocument($fileTitle, $fileContent)
{
$index = count($this->documents);
$this->documents[$index] = new DocuSign\eSign\Model\Document();
$this->documents[$index]->setDocumentBase64(base64_encode($fileContent));
$this->documents[$index]->setName($fileTitle);
$this->documents[$index]->setDocumentId($index + 1);
return json_encode($this->documents[$index]);
}
So I figured it out - I was setting my documentID (DocuSign\eSign\Model\Document()) to 0 when it should have been 1. That resolved the issue!

soundcloud api php add follower

I am making a page where you can log in with your soundcloud and gain access to download my songs as long as you are following me on soundcloud. I have authentication working but cannot figure out the following part. I pretty much copied and pasted the examples from the soundcloud developers website under the like and follow section, and it seams neither is working how its supposed to. The try catch makes it appear that i am not following my main account (which i got the user id# from testing the authentication step) even if i go on soundcloud, on my test account and follow my main account. Here is the error I am getting:
Warning: Missing argument 2 for Services_Soundcloud::put(), called in /my_website/index.php on line 43 and defined in /my_website/Services/Soundcloud.php on line 636
Notice: Undefined variable: postData in /my_website/Services/Soundcloud.php on line 642
Fatal error: Uncaught exception 'Services_Soundcloud_Invalid_Http_Response_Code_Exception' with message 'The requested URL responded with HTTP code 404.' in /my_website/Services/Soundcloud.php:941
Stack trace:
#0 /my_website/Services/Soundcloud.php(645): Services_Soundcloud->_request('https://api.sou...', Array)
#1 /my_website/index.php(43): Services_Soundcloud->put('/me/followings/...')
#2 {main}
thrown in my_website/Services/Soundcloud.php on line 941
heres the code im running:
require_once 'Services/Soundcloud.php';
//session_destroy();
session_start();
$soundcloud = new Services_Soundcloud(client_id, secret_id, redirect_uri)
$authURL = $soundcloud->getAuthorizeUrl();
echo "<pre>";
if (!empty ($_SESSION['token'])){
$soundcloud->setAccessToken($_SESSION['token']);
} else if(!empty($_GET['code'])){
try{
$accessToken = $soundcloud->accessToken($_GET['code']);
$_SESSION['token'] = $accessToken['access_token'];
$soundcloud->setAccessToken($_SESSION['token']);
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
exit($e->getMessage());
}
} else {
echo "<a href='".$authURL."'><img border='0' alt='Connect with Soundcloud' src='connect.png'></a>";
}
if (!empty ($_SESSION['token'])){
// check the status of the relationship
echo $_SESSION['token'];
try {
$soundcloud->get('/me/followings/#######');
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
if ($e->getHttpCode() == '404')
print "You are not following user #######\nTrying to follow now\n";
$soundcloud->put('/me/followings/#######');
}
}
Are the examples on soundcloud wrong or am i doing something wrong before i get to those commands?
also please note that my soundcloud object init and followings/##### was changed to protect my information.
after a lot of research and trial and error if figured out that setting the path to:
https://api.soundcloud.com/me/followings/#######?oauth_token=MY_TOKEN
seems to work. I don't know if this is just a workaround or how the API was intended to be used but its the only way i could get it to work, i was assuming the soundcloud client object was sending the token automatically with the command but it appears not.
I have also figured out that if it does find a match (user is following the id number) then it returns a 303 error, which the api guide does not even list in their http error codes.
You have a slash in front of me which must not be there. The following works for me:
$soundcloud->put('me/followings/#########','',array(CURLOPT_HTTPHEADER => array('Content-Type: application/xml')));

Google Analytics API 401 Invalid Credentials

I'm wracking my brain trying to figure out how to use the Google API PHP Client to access Google Analytics. Specifically, I want to upload cost data from other campaigns. My code does work to get information from GA, I can view traffic data for profiles, but I cannot figure out how to upload.
Here's the code that I'm using for auth:
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_AnalyticsService.php';
session_start();
$client = new Google_Client();
$client->setApplicationName("GA-Tester");
$client->setClientId('xxx.apps.googleusercontent.com');
$client->setClientSecret('xxx');
$client->setRedirectUri('http://www.site.com/indext.php');
$client->setDeveloperKey('xxx');
$analyticsService = new Google_AnalyticsService($client);
$dailyUploads = $analyticsService->management_dailyUploads;
if (isset($_GET['logout'])) {
unset($_SESSION['token']);
}
if (isset($_GET['code'])) {
$client->authenticate();
$_SESSION['token'] = $client->getAccessToken();
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
}
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
if (!$client->getAccessToken()) {
header ('Location:http://www.site.com/indext.php');
} else {...
This code does work for requesting data. I can get a list of accounts, profiles, download traffic data for a specific profile, etc. No errors or issues.
When I try to upload my CSV file containing cost data I get a '401 Invalid Credentials' error. Here's the code that sends the file:
$send = $dailyUploads->upload(
$accountId,
$webPropertyId,
$customDataSourceId,
$start_date,
1,
'cost',
array(
"reset" => true,
"data" => $cont,
"mimeType" => "application/octet-stream",
"uploadType" => "media"));
I've double checked all of my variables that I'm passing, they're sending the correct information.
So here's my question. If all of my GET requests work without issue, why would my POST request throw an error? I can't tell if this is an error with my code, or with settings in the API console. Can anyone steer me in the right direction?
EDIT:
Here's the error code generated (minus identifiable bits).
Fatal error: Uncaught exception 'Google_ServiceException' with message
'Error calling POST https://www.googleapis.com/upload/analytics/v3/man
agement/accounts/1234567/webproperties/UA-1234567-1/customDataSources/
xXxXxX/dailyUploads/2013-01-17/uploads?appendNumber=1&type=cost&reset=
true&uploadType=media&key=xXxXxX: (401) Invalid Credentials' in /../pub
lic_html/proj/google-api-php-client/src/io/Google_REST.php:66 Stack tra
ce: #0 /../public_html/proj/google-api-php-client/src/io/Google_REST.ph
p(36): Google_REST::decodeHttpResponse(Object(Google_HttpRequest)) #1 /
../public_html/proj/google-api-php-client/src/service/Google_ServiceRes
ource.php(186): Google_REST::execute(Object(Google_HttpRequest)) #2 /..
/public_html/proj/google-api-php-client/src/contrib/Google_AnalyticsSer
vice.php(82): Google_ServiceResource->__call('upload', Array) #3 /../pu
blic_html/proj/dailyUpload_send.php(60): Google_ManagementDailyUploadsS
erviceResource->upload('1234567', 'UA-1234567-1', 'xXxXxXxXxXxXxXx...',
' in /../public_html/proj/google-api-php-client/src/io/Google_REST.php
on line 66
I just successfully uploaded cost data for the first time. In trading comments with Nicholas Pickering I came across the documentation for Management API Authorization which states that:
You will get a 401 status code if your access_token has expired or if you are using the wrong scope for the API.
The default for scope is read only, which is why all of my GET requests were working without difficulty, but I couldn't complete any POST requests through the API. I can't remember how I found it, but the way to accomplish this within the PHP client library is to append the following line to the client declaration:
$client->setScopes('https://www.googleapis.com/auth/analytics');
As soon as I added that line to my project, I was able to successfully upload cost data. I'm really glad to have cleared this hurdle. I still have a long way to go to complete my project, but at least I know that it's going to work.
I kept geting this error until I went to Google Console -> APIs & auth ->
APIs and turned on this API usage.

LinkedIn API OAuth Problem

I'm using the PEAR OAuth Class to access the LinkedIn developer API and I've come across a bit of a problem. I can authorize my application but when it comes to getting an accessToken I'm receiving this error:
Edit:
Code after Adam's suggestions
public function oauth_access()
{
session_start();
$token = $_GET['oauth_token'];
$verifier = $_GET['oauth_verifier'];
$secret = $_SESSION['trequest_token_secret'];
$key = "****";
$secret = "****";
$oauthc = new OAuth($key, $secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_AUTHORIZATION);
$oauthc->setToken($token, $secret);
$oauthc->setNonce(rand());
try
{
$access_token_info = $oauthc->getAccessToken("https://api.linkedin.com/uas/oauth/accessToken");
$_SESSION['laccess_oauth_token']= $access_token_info['oauth_token'];
$_SESSION['laccess_oauth_token_secret']= $access_token_info['oauth_token_secret'];
$_SESSION['loauth_verifier'] = $verifier;
}
catch (OAuthException $e)
{
echo $e->getMessage();
}
}
But I'm now getting a different error:
Invalid auth/bad request (got a 401, expected HTTP/1.1 20X or a redirect)
You don't need to manually compute the signature, as pecl/oauth will do that for you.
Also, you're telling the library to pass the data in the Authorization HTTP header. That is a good place to have it. Then you are passing it via a query parameter. That is permitted, but less optimal. (You may actually be passing it in two places.) Also, pecl/oauth will automatically generate the proper timestamp.
When I first started, I found this blog post to be a good first start.
Or you can use the LinkedIn PHP library listed by Paul. It's also a good place to begin, if you don't want to reuse pecl/oauth because you're using that someplace else.

Categories