I simply don't really understand how this whole OAuth authentification thing works and I'm pretty much stuck. I'm trying to let a user authentificate his/her YouTube account to my server using the Google PHP Client API.
Here's my current code:
<?php
require_once app_path().'/google-apis/Google_Client.php';
require_once app_path().'/google-apis/contrib/Google_YouTubeService.php';
class SignupController extends BaseController {
public function showSignupForm() {
$client = new Google_Client();
$client->setClientId('CLIENTID');
$client->setClientSecret('CLIENTSECRET');
$client->setAccessType('offline');
$client->setDeveloperKey('DEVKEY');
$youtube = new Google_YoutubeService($client);
$client->authenticate(Input::get('code'));
$token = json_decode($client->getAccessToken());
return View::make('signup')->with('google_token', $token->access_token);
}
public function getYTAccess() {
$client = new Google_Client();
$client->setClientId('CLIENTID');
$client->setClientSecret('CLIENTSECRET');
$client->setAccessType('offline');
$client->setDeveloperKey('DEVKEY');
$client->setRedirectUri('REDIRECT_URI');
$youtube = new Google_YoutubeService($client);
$authUrl = $client->createAuthUrl();
return View::make('connect_youtube')->with('authUrl', $authUrl);;
}
}
?>
This is the code for the SignupController in the Laravel-based application I'm building. The relevant routes are as follows:
Route::get('signup/connect_youtube/return', 'SignupController#showSignupForm');
Route::get('signup', 'SignupController#getYTAccess');
I only get an invalid request error after getting redirected to my application and I know it has something to do with the access token, just don't know what.
Any help would be appreciated.
Thanks
Tobias Timpe
(Secrets omitted, obviously)
To put it simply, there are 2 steps (at least) you have to do:
1. pass the correct parameters to google. The parameters tell you 1. who you are (you need to present your client id and client secret), 2. what you ask for (in your case youtube scope) 3. redirect_uri which is where your user will be redirected back after she accepts your app's request. 4. other options like access_type=offline which specifies that you have a backend server to continue the auth flow.
To check that this step works correctly, you don't always need run the code. Just print out your auth_url that the sdk makes for you. All those parameters i mentioned should be embedded there. Copy-paste the url in the browser, if the parameters are correct, it will take you to Google's consent page. If not, most likely is because the parameters you set in Google Apis setting page are mismatched with your parameters scripted in the auth_url. Examples are mismatched domains, redirect_uris, client_ids, client_secrets. I'm not sure if this is the error that you are receiving.
If your parameters are good, Google will let your user to login and allow youtube scope access for your app ('consent'). It will redirect user's browser back to your specified 'redirect_uri' with the parameter code=. So this will get you to the step 2 your server script has to process.
The value shooted from Google in the parameter ?code is what you need to get access token. So your server route (redirect_uri) needs to extract the code parameter and pass to the google api to exchange for 'credentials'. Note that the auth code can be used only once. The response credentials will contain access_token and refresh_token. These are important for the api calling so you need to persist them in a storage, possibly with google sdk you are using.
Hope that helps.
Related
I am already using google app for authentication. Now I have added additional URLs to "Authorized redirect URIs" but those URL are not working. Old ones are working properly but when I am using new URL google returns below error instead of google auth token.
{"error":"redirect_uri_mismatch","error_description":"Bad Request"}
Please suggest me solution.
Here is my code to generate login url :
require_once "../vendor/autoload.php";
$gClient = new Google_Client();
$gClient->setClientId("clientID");
$gClient->setClientSecret("clientSECRET");
$gClient->setApplicationName("MY GOOGLE APP");
$gClient->setRedirectUri("https://example.com/TEST/authenticate/pages_authnicate_google.php");
$gClient->addScope("https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/spreadsheets");
$gClient->setAccessType("offline");
$gClient->setPrompt('consent');
$loginURL = $gClient->createAuthUrl();
Double-check that what you sent earlier in the authorization request matches what you send in the request to the token endpoint. You can use either URL that you've configured in the API Console but it must be the same in both requests.
Make sure redirect_uri: 'https://www.example.org/token' is same configured on Google Client API with 'Authorized redirect URIs' block.
In my case, it works...!!!
I am building a portal where multiple users can log in to their multiple Gmail accounts. I have successfully retrieved the token value, However, I want to store that in my database but I am unable to store it.
Below is the code I am using:
function mInititalize(){
$client = new Google_Client();
$client->addScope('https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email https://mail.google.com/');
$client->setClientId(Config('gmail.client_id'));
$client->setClientSecret(Config('gmail.client_secret'));
$client->setRedirectUri('http://localhost:81'.Config('gmail.redirect_url'));
$loginURL = $client->createAuthUrl();
return redirect($loginURL);
}
After Redirection or user login
function mGetToken(){
$token = $client->fetchAccessTokenWithAuthCode( 'code'); // here i get the 'code' from login URL
I pass this code to get token I successfully get token
$oAuth = new Google_Service_Oauth2( $client);
$userData = $oAuth->userinfo_v2_me->get(); // get current user detail
}
I want to store $token value in database, but I am getting error message
>Serialization of 'Closure' is not allowed
Please anyone help me to solve this issue. Thanks.
I would suggest storing OAuth credential information for the Google API, not in your database, but through the API itself. If you're intending to use it any authentication manner, you'll run into problems, as the docs state:
Access tokens periodically expire and become invalid credentials for a related API request. Google Identity Platform: Using OAuth 2.0 for Web Server Applications
But, the same docs also show a way that you can set or retrieve the token natively within the API. Since it's data relating to google's auth'ing process, and since it might go stale if you store it, it seems best to just let them handle it and work with the API. The same source:
If you need to apply an access token to a new Google_Client object—for example, if you stored the access token in a user session—use the setAccessToken method:
$client->setAccessToken($access_token);
$client->getAccessToken();
I am currently new to using php and Laravel and working with an API however I have been following the Spotify PHP tutorial https://github.com/jwilsson/spotify-web-api-php.
I've also put in bold some of my questions that I wanted to ask , hopefully someone can help.
I have followed all steps but need help just to get it working.
Put the following code in its own file, lets call it auth.php. Replace CLIENT_ID and CLIENT_SECRET with the values given to you by Spotify.
(Where abouts should I save this file?)
The REDIRECT_URI is the one you entered when creating the Spotify app, make sure it's an exact match.
(I used my localhost:8888/callback/ not sure if that is correct?) Obviously I haven't put me details in here on this website as for security reasons.
<?php
require 'vendor/autoload.php';
$session = new SpotifyWebAPI\Session(
'CLIENT_ ID',
'CLIENT_SECRET',
'REDIRECT_URL'
);
$options = [
'scope' => [
'playlist-read-private',
'user-read-private',
],
];
header('Location: ' . $session->getAuthorizeUrl($options));
die();
?>
When the user has approved your app, Spotify will redirect the user together with a code to the specifed redirect URI. You'll need to use this code to request a access token from Spotify.
put this code in a new file called callback.php:
Do replace client id and secret with my detail? also how do I save the access token?
require 'vendor/autoload.php';
$session = new SpotifyWebAPI\Session(
'CLIENT_ID',
'CLIENT_SECRET',
'REDIRECT_URI'
);
// Request a access token using the code from Spotify
$session->requestAccessToken($_GET['code']);
$accessToken = $session->getAccessToken();
$refreshToken = $session->getRefreshToken();
// Store the access and refresh tokens somewhere. In a database for example.
// Send the user along and fetch some data!
header('Location: app.php');
die();
In a third file, app.php, tell the API wrapper which access token to use, and then make some API calls!
(Where do i also save this file and how do I make these calls in my Laravel Controllers?)
require 'vendor/autoload.php';
$api = new SpotifyWebAPI\SpotifyWebAPI();
// Fetch the saved access token from somewhere. A database for example.
$api->setAccessToken($accessToken);
// It's now possible to request data about the currently authenticated user
print_r(
$api->me()
);
// Getting Spotify catalog data is of course also possible
print_r(
$api->getTrack('7EjyzZcbLxW7PaaLua9Ksb')
);
(Where abouts should I save this file?)
You can save this file in differents places in laravel, for testing you could write it in a controller (not the best but you can).
Do replace client id and secret with my detail?
Yes of course !
also how do I save the access token?
You can save in a database or in a session or where you want. If you store it in a session you will have to make a new request to get a new Access token if the user logged out of your application. In a database you can reuse it.
Many access token are only available for a specific duration. The spotify doc should speak of it.
(Where do i also save this file and how do I make these calls in my Laravel Controllers?)
For testing you can do this in your controller, but it's a good idea to have a service layer where you put the business logic of your application.
Do not copy require 'vendor/autoload.php'; in your file laravel handle the composer autoload already.
I am trying to get a refresh token for the Google API's, using the PHP SDK. I am authenticating the user with Javascript, retrieving a code, and exchanging it for an access_token server side, but this doesn't grant me an access token. What am I doing wrong? Here is the code I use:
$client = new Google_Client();
$client->setClientId($client_id);
$client->setClientSecret($client_secret);
$client->addScope('https://www.googleapis.com/auth/plus.me');
$client->addScope('https://www.google.com/m8/feeds');
$client->setRedirectUri('postmessage');
$client->setAccessType('offline');
if (isset($_REQUEST['code'])) {
$client->authenticate($_REQUEST['code']);
if ($client->getAccessToken()) {
$_SESSION['access_token'] = $client->getAccessToken();
$token_data = $client->verifyIdToken()->getAttributes();
$result['data']=$token_data;
$result['access_token']=json_decode($_SESSION['access_token']);
}
}
debug($result); //my own function, var_dumps the content of an array
Here is the result of the array:
$result['access_token'] contains:
access_token: TOKEN
created: 1434380576
expires_in: 3594
id_token: IDTOKEN
token_type:"Bearer"
If I am not mistaken the first access token should also contain the refresh token, what am I doing wrong?
First check the settings in the developer console of Google to see if your RedirectUri is the same and that the API is activated (although if you already got that .json, then I assume it is.
You have to go through the Google Auth Prompt Screen at least 1 time to get a refresh token in your .json, and if your RedirectUri is taking you nowhere, you won't be able to get your refresh token or even the access validated.
You can also try a service account if you're doing small file transactions and don't need a user validation for the process of your script. Good Luck.
The problem was that I had to specify that I want offline access in the authentication process, the client side... The Google API's are horribly documented!!!
I am testing the Gmail API.
So far I have done the following:
I have created the project in the Google Developers Console
I have enabled the Gmail API.
I have created a new Client ID and the client secret.
In my PHP script I have installed the PHP Client library and followed
the instructions for the setup in PHP.
So now when I run the file quickstart.php it gives a link. When I open it, it appears an authorization page where I authorize my application to access the Gmail API.
Then it redirects to the Redirect URIs that I have declared in the setup (adding the code parameter).
In the address bar it appears exactly this:
http://localhost/main/gmail_callback?code=MY_CODE
Where main is my controller and gmail_callback so far is just a blank function.
And it should be correct since these are my settings:
Javascript origins: http://localhost
Redirect URIs: http://localhost/main/gmail_callback
What do I do next?
The next step in the flow is to exchange the Authorization Code for an Access Token (which will also include a Refresh Token if you requested offline access). If you use the https://developers.google.com/oauthplayground/ to execute the flow manually, you'll be able to see the URLs involved. There is a php library call to do the same thing, but I personally prefer to send my own HTTP rather than use a library. Even if you do use a library, it will still be worth spending a little time to understand the HTTP flow so you can more easily debug any problems you encounter.
Basically I was approaching wrongly. Following these instructions is enough to get the tokens:
https://developers.google.com/gmail/api/quickstart/php
The main point is to access the file from the command line and not from the app.
I made a Oauth Gmail some months ago, I got something like this :
In my callback function :
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
return $this->redirect($auth_url);
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = Router::url('/', true).'Users/gmail';
return $this->redirect($redirect_uri);
}
And in my gmail() function :
public function gmail(){
require APPLIBS.'Google/src/Google'.DS.'autoload.php';
$client = new Google_Client();
$client->setAuthConfigFile('../Config/client_secrets.json');
$client->addScope(Google_Service_Oauth2::PLUS_LOGIN);
$client->addScope(Google_Service_Oauth2::USERINFO_EMAIL);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$oauth_service = new Google_Service_Oauth2($client);
$data['Profile']['last_name'] = $oauth_service->userinfo->get()->familyName;
}
}
$data['Profile']['last_name'] contain the last_name of the user, for example.