PHP Gmail API Invalid Grant: Code was already redeemed (Codeigniter) - php

First of all I want to say that I read all the other post about this same problem and I couldn't find a solution.
This is the error:
exception 'Google_Auth_Exception' with message 'Error fetching OAuth2 access token, message: 'invalid_grant: Code was already redeemed.
In localhost, it works perfect. I can debug it and I get Google plus && emails info without problem.
I create a new credential for production (Web App) and I set my oauth return uri in: Authorized redirect URI
(http://www.__myweb_.com/plus_gmail/oauth2callback)
It works, because I can accept and I get the code in callback, but it fails when I try to authenticate;
I also tried to revokeToken and my Session is empty...
How can I solve this problem??
Thanks a lot!!
This is my code:
function __construct()
{
define('CLIENT_SECRET_PATH', 'client_secret_online.json');
$this->redirect_url=base_url()."plus_gmail/oauth2callback";
$this->client = new Google_Client();
$this->client->setIncludeGrantedScopes(true);
$this->client->setAuthConfigFile(CLIENT_SECRET_PATH);
$this->client->addScope(Google_Service_Plus::PLUS_LOGIN);
$this->client->addScope(Google_Service_Plus::PLUS_ME);
$this->client->addScope(Google_Service_Plus::USERINFO_EMAIL);
$this->client->addScope(Google_Service_Plus::USERINFO_PROFILE);
$this->client->addScope(Google_Service_Gmail::MAIL_GOOGLE_COM);
$this->client->setRedirectUri($this->redirect_url);
$this->client->setAccessType('offline');
$this->client->setIncludeGrantedScopes(true);
}
function index()
{
$auth_url = $this->client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
}
function oauth2callback()
{
if (! isset($_GET['code']))
{
echo "Error getting code"
}
else
{
$token=$_GET['code'];
$data["token"]=$token;
try
{
$this->client->authenticate($token);
$access_token = $this->client->getAccessToken();
$plus = new Google_Service_Plus($this->client);
$me=$plus->people->get('me');
$this->daouser->newUserPlus($me,$access_token);
var_dump($me);
$this->readEmailsId($this->client);
}
catch (Exception $e)
{
var_dump($e)
}
}
}
I also need to know why it shows me the var_dump($e), but I have a new row in my database withe user google plus info.
I delete access to my app in my gmail account (https://security.google.com/settings/security/permissions) and give access again getting the same error (Code was already redeemed). I used a new gmail account and I get also the same error...

Related

error on listing all files using google drive api in php

I am working on google drive api by using PHP. I am facing an error while using this drive api. I am using google api client library "google/apiclient ^2.0". I am trying to user login with google authentication and view all files available in drive for this purpose, i am using this library but it's showing error:
Notice: Undefined property: Google_Client::$files in
/Applications/XAMPP/xamppfiles/htdocs/google_app/index.php on line 31
Fatal error: Uncaught Error: Call to a member function listFiles() on
null in /Applications/XAMPP/xamppfiles/htdocs/google_app/index.php:31
Stack trace: #0
/Applications/XAMPP/xamppfiles/htdocs/google_app/index.php(55):
retrieveAllFiles(Object(Google_Client)) #1 {main} thrown in
/Applications/XAMPP/xamppfiles/htdocs/google_app/index.php on line 31
include_once 'vendor/autoload.php';
function retrieveAllFiles($service) {
$result = array();
$pageToken = NULL;
do {
try {
$parameters = array();
if ($pageToken) {
$parameters['pageToken'] = $pageToken;
}
$files = $service->files->listFiles($parameters);
$result = array_merge($result, $files->getItems());
$pageToken = $files->getNextPageToken();
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
$pageToken = NULL;
}
} while ($pageToken);
return $result;
}
$client = new Google_Client();
$client->setAuthConfig('client_secrets.json');
$client->setAccessType("offline"); // offline access
//$client->setIncludeGrantedScopes(true); // incremental auth
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
$redirect_uri = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
$client->setRedirectUri($redirect_uri);
if (isset($_GET['code'])) {
$token = $client->fetchAccessTokenWithAuthCode($_GET['code']);
}
$service = new Google_service_Device();
echo retrieveAllFiles($service );
Actually i am trying to retrieve all files in my google drive with my file id and after that set status auto publish of specific files. Please help me to get rid of this error.
Thanks in advance.
"Daily limit for unauthenticated Use Exceeded"
Means that you are making a request without properly authenticating your script. there is probably something up with your fetchAccessTokenWithAuthCode.
You might consider something long these lines
function getOauth2Client() {
try {
$client = buildClient();
// Set the refresh token on the client.
if (isset($_SESSION['refresh_token']) && $_SESSION['refresh_token']) {
$client->refreshToken($_SESSION['refresh_token']);
}
// If the user has already authorized this app then get an access token
// else redirect to ask the user to authorize access to Google Analytics.
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
// Set the access token on the client.
$client->setAccessToken($_SESSION['access_token']);
// Refresh the access token if it's expired.
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
$client->setAccessToken($client->getAccessToken());
$_SESSION['access_token'] = $client->getAccessToken();
}
return $client;
} else {
// We do not have access request access.
header('Location: ' . filter_var( $client->getRedirectUri(), FILTER_SANITIZE_URL));
}
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
Code ripped from my sample project oauth2php
Undefined property Google_Client
Means you havent properly declared the google client
Uncaught Error: Call to a member function listFiles() on null in
what happens if you remove $parameters and just call $service->files->listFiles();

Laravel | LinkedIn Login - '401 Unauthorized'

I'm getting another error with my LinkedIn application to be able to login on my website, so I get redirected to the right url, I click on 'Authorize' once I'm on the LinkedIn login page, and I get redirected to a link like this:
http://localhost:8000/login/linkedin/callback?code=XXXXXXXXXXXXXXXXXXXXX...
With the following error:
Client error: POST https://www.linkedin.com/oauth/v2/accessToken resulted in a 401 Unauthorized response: {"error":"invalid_client","error_description":"Client authentication failed"}
I don't understand why because I did a Twitter application to login on my website that works with the same controller, and it's perfectly working.. Here is my SocialAuthController:
public function redirectToProvider($driver)
{
if( ! $this->isProviderAllowed($driver) ) {
return $this->sendFailedResponse("{$driver} is not currently supported");
}
try {
return Socialite::driver($driver)->redirect();
} catch (Exception $e) {
// You should show something simple fail message
return $this->sendFailedResponse($e->getMessage());
}
}
public function handleProviderCallback( $driver )
{
try {
$user = Socialite::driver($driver)->user();
} catch (Exception $e) {
return $this->sendFailedResponse($e->getMessage());
}
// check for email in returned user
return empty( $user->email )
? $this->sendFailedResponse("No email id returned from {$driver} provider.")
: $this->loginOrCreateAccount($user, $driver);
}
My routes:
Route::get('login/{driver}', 'Auth\SocialAuthController#redirectToProvider')->name('social.oauth');
Route::get('login/{driver}/callback', 'Auth\SocialAuthController#handleProviderCallback')->name('social.callback');
I checked multiple time that all the data between the services.php and the LinkedIn application matchs exactly.. I can't figure this out.
You need to add
'x-li-src' => 'msdk'
Into headers array in file vendor/laravel/socialite/src/Two/LinkedInProvider.php
Please check this link for more information Android LinkedIn SDK produces unusable access tokens

Wrong number of segments in token (OAuth Google Api with php)

I have a php application that use OAuth2 to authenticate users to their account.
until yesterday, everything worked very well.
But today, and without changing my code, when I try to access to my account, and after I authenticates to my google account, I obtain a blank page.
I debug the code and I found that it crashed when the Google_Client try to verifyIdToken and more exactly in the function verifySignedJwtWithCerts because : $segments = explode(".", $jwt); find 4 segments and not 3.
here is my code :
...
$client = new Google_Client();
$client->setClientId($clientId);
$client->setClientSecret($clientSecret);
$client->setRedirectUri($redirectUri);
$client->setScopes("email");
if(!isset($_GET['code']))
header("Location: ".$client->createAuthUrl());
else
{
$client->authenticate($_GET['code']);
$_SESSION["access_token"] = $client->getAccessToken();
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
} else {
$authUrl = $client->createAuthUrl();
}
$ticket = $client->verifyIdToken();
if ($ticket) {
$admin = $ticket->getAttributes();
}
$_SESSION["email"] = $admin["payload"]["email"];
...
Can anyone offer an explanation?
Thank's in advance
Some how I didn't find any answer in Google. So I going to share what I do to make it work.
The short answer: Because the token you use in verifyIdToken() is invalid.
The long answer as below:
I'm not sure if it is the correct steps:
After Google Login Authentication, we will get the "Authorization
Code" from oauthplayground (for testing). Please enter your oauth client_id and oauth client secret in the setting before usage.
I have use the "Authorization Code" to get the other tokens by writing
$token = $client->fetchAccessTokenWithAuthCode("THE_AUTHORIZATION_CODE");
Inside $token, I have receive the following: access_token, token_type, expires_in, refresh_token, id_token, created.
Now use the id_token in $payload = $client->verifyIdToken(id_token);
Then you will get the correct information you needed like names, aud, exp, iss etc in $payload.
Note: To avoid your code return the "Wrong number of segments in token" error again, you have to try and catch the verifyIdToken method
try {
$payload = $client->verifyIdToken(id_token);
}
catch (Exception $e) {
echo "Invalid id token";
}
On my side, I've been working on MERN Application and, the issue was on the way I send the tokenId on the backend.
Check if the idToken you are sending to the backend is the same as the one you are getting on googleSuccess.
before.
const onGoogleSuccess = (response) => {
const tokenId = response.accessToken;//Wrong
console.log("SUCCESS::", response);
dispatch(login({ tokenId })).then((res) => {
console.log("GOOGLE-LOGIN::", res);
});
};
After:
before.
const onGoogleSuccess = (response) => {
const tokenId = response.accessToken;
console.log("SUCCESS::", response);
dispatch(login({ tokenId })).then((res) => {
console.log("GOOGLE-LOGIN::", res);
});
};

How can I get an updated access token, using stored refresh token

I'm building an application that allows the admin to authenticate access to their analytics account for offline usage, and stores the refresh token in the database.
Now when I try to use the API on the frontend, it returns the following error:
"Access Token Expired. There wan a general error : The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved."
Here's my code that generates this error so far:
require_once "lib/google/Google_Client.php";
require_once "lib/google/contrib/Google_AnalyticsService.php";
$_analytics = new analytics();
$_googleClient = new Google_Client();
$_googleClient->setClientId($_analytics->gaClientId);
$_googleClient->setClientSecret($_analytics->gaClientSecret);
$_googleClient->setRedirectUri($_analytics->gaRedirectUri);
$_googleClient->setScopes($_analytics->gaScope);
$_googleClient->setAccessType($_analytics->gaAccessType);
// Returns last access token from the database (this works)
$_tokenArray['access_token'] = $_analytics->dbAccessToken($_agencyId);
$_googleClient->setAccessToken(json_encode($_tokenArray));
if($_googleClient->isAccessTokenExpired()) {
// Don't think this is required for Analytics API V3
//$_googleClient->refreshToken($_analytics->dbRefreshToken($_agencyId));
echo 'Access Token Expired'; // Debug
}
if (!$_googleClient->getAccessToken()) {
echo '<h2>Error - Admin has not setup analytics correct yet</h2>';
}
I'm after a function to run something like setRefreshToken - entering the value from the database, from the admin previously authenticating it online.
You could try the following, you would need to add in the code to store the new token in your database.
if($_googleClient->isAccessTokenExpired()) {
// Don't think this is required for Analytics API V3
//$_googleClient->refreshToken($_analytics->dbRefreshToken($_agencyId));
echo 'Access Token Expired'; // Debug
$_googleClient->authenticate();
$NewAccessToken = json_decode($_googleClient->getAccessToken());
$_googleClient->refreshToken($NewAccessToken->refresh_token);
}
Use a try/catch and use the catch for redirection/refresh of the access token.
Below is the solution I used for similar problem:
$plus = new Google_Service_Plus($client);
try {
$me = $plus->people->get('me');
} catch(Exception $e){
if(!(strpos($_SERVER["REQUEST_URI"],'logout'))){
if (isset($authUrl)){
$redirect = $authUrl;
}
else{
$redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] .'?logout';
}
header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));
exit;
}
You can replace the statement under try with the line throwing the exception, I guess that would be
$_googleClient->setClientId($_analytics->gaClientId);
or you can also try refreshing the token as per solution given here:
https://stackoverflow.com/a/22096740/1675384

Can't get soundcloud access_token using php sdk. invalid_grant error

I am using soundcloud php sdk. It works successfully when i use the sdk to get track. But when i've tried to get an access Token in order to use it, the sdk send me back an error 401. After debugging the error message, i ve get the responseJSON below: {"error":"invalid_grant"}
This is my code , i m using Zend framework
$code = $this->getRequest()->getParam('code',false);
if($code){
$client = new Services_Soundcloud($this->soundcloud['client_id'],$this->soundcloud['secret_key']);
try {
$access_token = $client->accessToken($code);
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
exit($e->getMessage());
}
}
Did anyone has any idea about how to solve this error ?
In order to exchange a code for an access token, you must instantiate your Services_Soundcloud instance with a client id, client secret and a redirect uri. The following code should work, assuming you are storing the redirect uri in $this->soundcloud:
$client = new Services_Soundcloud(
$this->soundcloud['client_id'],
$this->soundcloud['secret_key'],
$this->soundcloud['redirect_uri']
);
$code = $this->getRequest()->getParam('code',false);
if ($code) {
try {
$access_token = $client->accessToken($code);
} catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
exit($e->getMessage());
}
}
Let me know if that solves the problem.

Categories