6
votes

I'm using the google API to access my calendar entries via OAuth. Unfortunately I'm getting the following error (server is a local raspi):

Failed to load https://accounts.google.com/o/oauth2/auth?response_type=code&access_type=online&client_id=****-****.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Fopenhabianpi..%2Fsmarthome%2Fphp%2Fscripts%2Fscript.oauth2callback.php&state&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&approval_prompt=auto: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://openhabianpi..' is therefore not allowed access. The response had HTTP status code 405.

My scripts:

Ajax Request

var termine = function (){
     $.ajax({
        type: "POST",
        url: "php/ajax/ajax.termine.php",
        data: {
            action: 'get_termine'
        },n
        success: function(response) {
            console.log(response);
        }
    });
}

ajax.termine.php

require dirname(dirname(__FILE__)).'/vendor/autoload.php';

$client = new Google_Client();
$client->setAuthConfig(dirname(dirname(__FILE__)).'/config/client_secret.json');
$client->addScope(Google_Service_Calendar::CALENDAR_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
  $client->setAccessToken($_SESSION['access_token']);
  $calendarId = 'primary';
  $optParams = array(
    'maxResults' => 10,
    'orderBy' => 'startTime',
    'singleEvents' => TRUE,
    'timeMin' => date('c'),
  );

  $service = new Google_Service_Calendar($client);
  $results = $service->events->listEvents($calendarId, $optParams);
  if (count($results->getItems()) == 0) {
    print "No upcoming events found.\n";
  } else {
    print "Upcoming events:\n";
    foreach ($results->getItems() as $event) {
      $start = $event->start->dateTime;
      if (empty($start)) {
        $start = $event->start->date;
      }
      printf("%s (%s)\n", $event->getSummary(), $start);
        echo date('c');
    }
  }
} else {
  $redirect_uri = 'http://openhabianpi.***.***/smarthome/php/scripts/script.oauth2callback.php';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

script.oauth2callback

<?php
require_once dirname(dirname(__FILE__)).'/vendor/autoload.php';
session_start();

$client = new Google_Client();
$client->setAuthConfigFile(dirname(dirname(__FILE__)).'/config/client_secret.json');
$client->setRedirectUri('http://openhabianpi.***.***/smarthome/php/scripts/script.oauth2callback.php');
$client->addScope(Google_Service_Calendar::CALENDAR_READONLY);
if (! isset($_GET['code'])) {
  $auth_url = $client->createAuthUrl();
  header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
  $client->authenticate($_GET['code']);
  $_SESSION['access_token'] = $client->getAccessToken();
  $redirect_uri = 'http://openhabianpi.***.***/smarthome/';
  header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}

I've tried the following, unfortunately without success:

  1. dataType: 'jsonp',

  2. header("Access-Control-Allow-Origin: *");

  3. Setting in .htaccess or apache.conf

Access-Control-Allow-Origin "*"

Thanks in advance for your help!

4
You cannot call this using AJAX, you need to use browser redirect for the OAuth to work. See a similar thing I answered recently stackoverflow.com/questions/45870488/…Tarun Lalwani
I did a workaround with a service account. Thanks all.cr1zz
Please post the details as an answer and accept the sameTarun Lalwani

4 Answers

4
votes
    if (isset($_SERVER['HTTP_ORIGIN'])){
        header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
        header('Access-Control-Allow-Credentials: true');
        header('Access-Control-Max-Age: 86400');    // cache for 1 day
    }
    // Access-Control headers are received during OPTIONS requests
    if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') 
    {
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
            header("Access-Control-Allow-Methods: GET, POST,OPTIONS");         
        if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
            header("Access-Control-Allow-Headers:        {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
        exit(0);
    }
0
votes

You can't use AJAX do do an OAuth authentication as the URL returned by $client->createAuthUrl() will show a login page.

You can still stay on the same page by following this steps:

  • Open ajax.termine.php in a new tab.

window.open('php/ajax/ajax.termine.php', '_blank');

  • Set the redirect uri to a blank page that only contains Javascript.
  • Use this javascript to change the parent page URL.

window.top.location.href = 'http://openhabianpi.***.***/smarthome/';

0
votes

You simply need to visit your google developer account and under API credentials add your web server address or IP address.

Visit console.developers.google.com

Then select your project. Then select credentials. Then select your API key. Then select Application restrictions then select HTTP referrers address and add your address.

enter image description here

Hope it solves your issue.

0
votes

The following script is working via ajax (you have to use a service account for this):

    <?php
    /**
    * Session aufbauen und user check
    */
    session_start();

    require dirname(dirname(__FILE__)).'/vendor/autoload.php'; //Google API via Composer

    $json_path = '***PATH to service account credential JSON***';

    $client = new Google_Client();

    $client->setAuthConfig($json_path);
    $client->useApplicationDefaultCredentials();
    $client->addScope(Google_Service_Calendar::CALENDAR_READONLY);

    $client->setApplicationName("***Your Appname***");

    $service = new Google_Service_Calendar($client);

    $calendarId = '***Your CAL ID***';
    $optParams = array(
       'maxResults' => 10,
        'orderBy' => 'startTime',
        'singleEvents' => TRUE,
        'timeMin' => date('c'),
    );

  $results = $service->events->listEvents($calendarId, $optParams);
  if (count($results->getItems()) == 0) {
    print "";
  } else {
    foreach ($results->getItems() as $event) {
      $start = $event->start->dateTime;
      if (empty($start)) {
        $start = $event->start->date;
      }

      $date = date("d.m.Y", strtotime($start));
      $time = date("G:i", strtotime($start));

      $today = date("d.m.Y");

      if ($date == $today){
        $array[] = array(
          "datum" => $date,
          "time" => $time,
          "termin" => $event->summary
        );
      }
    }
  }

  echo json_encode($array);