Google Calendar API v3 - authenticate with hardcoded credentials

19,670

Solution 1

You will need to use both the Developer Key (API Key) and OAuth2. The developer key authenticates who wrote the software and is used for things like quota which is on a per developer basis not a per user basis. OAuth2 is for user authentication and will be need to access the non-public calendar.

OAuth2 has a renew token from which you can generate a session token and this means that you will not need to screen scrape the OAuth screens to get authenticated. To get this I would write a little command line application, or you use a one off PHP page.

  1. Under the Google Api Console go to API Access
  2. Generate a new Client ID and choose Installed Application ( as you will be authenticating you server as you not as your user)
  3. Either using a console app or a one off PHP page authenticate using OAuth and your google account (the one with the calendar you want access to)
  4. In the return from the authentication there should be a renew token, (called renew or refresh or something similar). Save this string and make it available to your PHP site.
  5. When you need to access the service your OAuth library should have a renew/refresh call. There is an example using .Net below.

private IAuthorizationState CreateAuthorization(NativeApplicationClient arg)
 {
   // Get the auth URL:
   IAuthorizationState state = new AuthorizationState(new[] { AdsenseService.Scopes.AdsenseReadonly.GetStringValue() });
   state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
   if (refreshToken.IsNotNullOrEmpty()) // refreshToken you stored in step 4
   {
     try
     {
       state.RefreshToken = refreshToken;
       if (arg.RefreshToken(state))     // This is calling out to the OAuth servers with the refresh token getting back a session token, returns true if successful.
       {
         if (state.RefreshToken != refreshToken) // if the refresh token has changed, save it.
         {
           PersistRefreshToken(authorization.RefreshToken);
         }
         return this.authorization = state; // Retain the authorization state, this is what will authenticate your calls.
       }
     }
     catch (ProtocolException ex) {...}

The AuthorisationState that has now been renewed can then be used to authenticate call you make to the API. this state can be used many time until it expires and then can be refreshed. As you are authenticating your application as yourself not as a user this AuthorisationState can be shared by all you sessions. Both the current AuthorisationState and the refresh token should be kept securely on your server and never sent to the client, if you ever sent these as part of a response your clients would have the same privileges as your code application

Solution 2

I have found a solution that I think that is "the official" for what you want to do.

First, you have to activate a Google API "Client ID for installed applications".

Go to the Google API console and create the project.

Then, activate the calendar.

Go to the "API access" option, and use the "Create OAuth 2.0 client" button.

Give a name (and a logo, if you want) to the product. Click "next".

Choose the "Installed application" option and click "Create Client Id".

Now you have your access configurated. Now, you will need some codes. To obtain them:

*The "Authentication Code". To get it, you need the following information:

SCOPE: https://www.google.com/calendar/feeds/ (if you want to access the calendar API. There are others you can find them at the OAuth 2.0 Playground)

CLIENT_ID: You will find it at the API Access Section at the Google API Console.

REDIRECT_URI: Get it at the same place.

Now, copy the following code into a file, put the values into the variables, execute the code (php -q script_name.php), and go to the URL printed.

<?php
$scope         =   '';
$client_id      =   '';
$redirect_uri   =   '';

$params = array(
                    'response_type' =>   'code',
                    'client_id'     =>   $client_id,
                    'redirect_uri'  =>   $redirect_uri,
                    'scope'         =>   $scope
                    );
$url = 'https://accounts.google.com/o/oauth2/auth?' . http_build_query($params);        
echo $url."\n";
?>

The web page will ask you to allow the access. Do it, and you will get a code, which is your Authentication Code.

*The "Refresh Code". To get it, you will need:

The data you used before, plus the "client secret" code in the API Console, between the "client id" and the "redirect URI".

As you did before, copy the following code, and put the variables in place (the code field is the Authentication Code). Execute and the result is the "Refresh Token".

<?php
$url = 'https://accounts.google.com/o/oauth2/token';
$post_data = array(
                    'code'          =>   '',
                    'client_id'     =>   '',
                    'client_secret' =>   '',
                    'redirect_uri'  =>   '',
                    'grant_type'    =>   'authorization_code',
                    );
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
$token = json_decode($result);

echo $token->refresh_token . "\n";
?>

At this moment, you have all you need. Be careful if one day you change the Authentication Code. You will have to get new keys.

To access a calendar service, here you have the example: Change the variable values before using it. This example gets the primary calendar events, but you can change the address for any in the calendar API (http://code.google.com/intl/ca/apis/calendar/v3/getting_started.html#background_operations)

    <?php
    $scope         =   'https://www.google.com/calendar/feeds/';
    $client_id      =   '';
    $client_secret  =   '';
    $redirect_uri   =   '';


    $refresh_token  =   '';

    $token_url = 'https://accounts.google.com/o/oauth2/token';
    $post_data = array(
                        'client_secret' =>   $client_secret,
                        'grant_type'    =>   'refresh_token',
                        'refresh_token' =>   $refresh_token,
                        'client_id'     =>   $client_id
                        );
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $token_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $result = curl_exec($ch);
    $token_object = json_decode($result);
    $access_token = $token_object->access_token;

    // Get the results
    $rest_url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events';
    $header = "Authorization: OAuth " . $access_token;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HTTPHEADER, array($header));
    curl_setopt($ch, CURLOPT_URL, $rest_url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $rest_result = curl_exec($ch);

    print_r(json_decode($rest_result));
    ?>

First, the script asks for an "Access Token", which is valid for an hour. Then, the script gets the REST service (any in the calendar scope), sending the access token in the header. To give a best speed at the scrip, it would be good to store the access token in a cache until it's older than 3600 seconds. This way, the script would avoid one of the two calls.

Tips:

Visit OAuth 2.0 Playground to understand all the information sent in the OAuth process. It helped me a lot

A post by Eric Nagel in his blog gave me the solution. All the merit is to him. I can't link it since I haven't got enough "reputation".

Solution 3

Can also be used with the Google php library. The access token for the $client->setAccessToken() function has to be formatted in the following way:

$at= '{"access_token":"' . $access_token . '",' .
      '"token_type":"Bearer",' .
      '"expires_in":3600,' .
      '"refresh_token":"' . $refresh_token . '",',
      '"created":' . time() . '}';

Where $access_token is the access token found by you and $refresh_token is the refresh token. Tested with the useless simple.php google example.

Authentication is then just:

$client->setAccessToken($at);
Share:
19,670
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I am writing a PHP application that's supposed to allow users to add certain events to a private Google Calendar. The calendar is owned by me, and I need a way for PHP to communicate with the calendar API using fixed credentials (everyone can add events using a form on the website, but the calendar itself is not publicly visible).

    From what I have read, this is possible using ClientLogin in the v1 API. In the v3 API, however, the available options are OAuth2.0 or the API key. Using the API key doesn't seem to work, since it can only be used for requests that don't require authorization, and OAuth doesn't seem right either, because users are not supposed to access their own calendars, but the one my application uses.

    I thought about getting the OAuth token programatically, but that's bound to break sooner or later, since the OAuth dialog can use captchas.

    This seems to be such a standard use case — a web application that lets users interact with a single calendar in some predefined ways — yet I can't find any documentation on how to make it happen in the v3 API. Can anyone help me?

  • S.Raaj Nishanth
    S.Raaj Nishanth about 10 years
    I used this method to upload videos to Youtube and it works like a charm. No need of asking users to authenticate!! Thanks a lot!
  • wdyp
    wdyp over 9 years
    Thank you Roger, this helped me a lot. This should be the accepted answer as it is more detailed and focused on php.
  • yatendra
    yatendra almost 9 years
    Now, to get refresh token, I need to send 'access_type:offline' while getting authentication code (developers.google.com/identity/protocols/…). And Is refresh_token available forever or is it expired after sometime?
  • Roger Veciana
    Roger Veciana almost 9 years
    Forever is a verystrong word! But you just have to do it once, and I have scripts running with this since some years ago.
  • melomg
    melomg about 8 years
    I created a Web Application OAuth Client Id because there was no Installed application option. I followed the steps and I am able to get the Authentication Code. But to get refresh token I get Notice: Trying to get property of non-object error at the echo $token->refresh_token . "\n"; line. And if anyone can look at my question it would be so nice. Because there is only one month left to finish my final graduate project. :(
  • Leopoldo Sanczyk
    Leopoldo Sanczyk almost 3 years
    Something important to note, is you only get the refresh token the first time you authorize your app, (and don't forget to include access_type: offline). If you authorized it before testing this solution, see the steps to remove it and give it access again to get the refresh token, instead of the expiring access token, in this answer: stackoverflow.com/questions/10827920/…