Google calendar v3 returns 403 Insufficient Permission - ruby-on-rails

I've been trying to access Calendar v3 API with a service account. I have already added the scope https://www.googleapis.com/auth/calendar from the admin console and shared my calendar with that service account's email address.
I have also been accessing https://www.googleapis.com/auth/coordinate scope with the very same service account and it works fine.
Also, tried revoking access as said here: Why is Google Calendar API (oauth2) responding with 'Insufficient Permission'?
All that, and I am still getting;
{"error"=>
{"errors"=>
[{"domain"=>"global",
"reason"=>"insufficientPermissions",
"message"=>"Insufficient Permission"}],
"code"=>403,
"message"=>"Insufficient Permission"}}
Am i missing something?

Try to add to you scope 'userinfo.email' and enable in Developers console "Contacts API" and "Google+ API". I've spent 2 weeks searching for answer to this question, and this trick has worked for me.

Did you have any joy with this? I've hit the same brick wall.
UPDATE:
$key = file_get_contents($key_file_location);
$scopes = array('https://www.googleapis.com/auth/calendar');
$cred = new Google_Auth_AssertionCredentials(
$service_account_name,
$scopes,
$key
);
This worked for my authorization, after sharing the calendar with the service email account.

I think if you use Google Calendar Quickstart for Ruby, I think you should delete your credentials in the specified path...I try it and it works well... You can see where the credentials is put in here
CREDENTIALS_PATH = File.join(Dir.home, '.credentials',
"calendar-ruby-quickstart.yaml")
In your home dir, you may find a dir which Google store your credentials after you approve Google request to access your data.

first of all change
static string[] Scopes = { CalendarService.Scope.CalendarReadonly };
to
static string[] Scopes = { CalendarService.Scope.Calendar };
and then in your documents folder delete .credentials folder
and run again.
this worked for me!

Related

Using Microsoft graph to read all users calendars

I gave my application the following scopes:
SCOPES = [ "Calendars.Read", "User.Read.All" ]
I got an access token. With this token I am able to get the users and I get two users back which is correct.
When I then ask for the calendar of myself (admin):
https://graph.microsoft.com/v1.0/users/stijn#temponia.onmicrosoft.com/calendarview?startDateTime=#{start_date.to_s}&endDateTime=#{end_date.to_s}
This also works perfectly. However when I do this for the other user:
https://graph.microsoft.com/v1.0/users/frank#temponia.onmicrosoft.com/calendarview?startDateTime=#{start_date.to_s}&endDateTime=#{end_date.to_s}
I get this error message:
Access is denied. Check credentials and try again.
According to the documentation: https://graph.microsoft.io/en-us/docs/authorization/permission_scopes
Calendars.Read: Read calendars in all mailboxes: Allows the app to read events of all calendars without a signed-in user.
The scope I got back together with the access token was this: "calendars.read user.read.all" so it got accepted.
What am I missing here?
We are working to support the scenario you are requesting (Accessing other users' calendars) but the feature hasn't shipped yet. Stay tuned ...
UPDATE: Please take a look at using client credential flow. The blog post https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-apps-with-office-365-mail-calendar-and-contacts-apis-oauth2-client-credential-flow/ explains how to do this for Outlook API endpoint. But you should be able to follow the instructions for Microsoft Graph as well.
The app will require an admin to consent, and then can access calendar of any user in the organization, as long as their mailbox is in Office 365.

Setting up Google Calendar API

I'm trying to use the Google Calendar API in one of my projects. To do so, I need to set up OAuth access in the Google API console.
But when creating the consent-form (which is required to use OAuth), I get a meaningless error message:
The translation is as follows:
A problem occured. Please check your data and try again . If you have
not given any details, the problem may solve itself . In this case, we
recommend that you wait and try again later.
I have set the E-Mail address and project name. The optional fields were left blank.
So far I have not been able to solve the problem. I tried to wait for hours/days. I tried three different browsers. I also tried to contact Google support. All without success.
After days of trying, this is the solution:
Create another Google account
Using your old account, add the new account as an owner to your Google API project in the console
Log in with your new user account and accept the invitation
Create the OAuth consent form with the new user account
I have no idea WHY this worked, but it did.

ruby google api client, service account and Google app to use google drive

You can skip to the problem below but in short I can auth, upload and get a file list but it doesn't correspond to the gmail account I setup with the service account and google dev console
longer version:
I created a new email account say blah#gmail.com and used the google development console to enable drive, contacts and a few other APIs for my project.
Then I created the service account API keys/secrets and downloaded the client_secrets.json as well.
It took a while but got authentication working with the ruby google-api-client and I can login via rails console.
Problem:
I'm getting file.list but it only has the Getting Started.pdf even though I've created a few docs and spreadsheets on the blah#gmail.com service account.
I can also upload a file but don't see it.
I "think" that it's uploading to Google Apps related account? but I have neither set one up nor do I own domain for the organization I'm setting this up with.
I have no idea where the files are going or uploading or how I can access the drive account I actually did setup with blah#gmail.com
what's going on .
EDIT:
Can i get some code example on how to modify this to impersonate user?
require 'google/apis/drive_v2'
Drive = Google::Apis::DriveV2
#drive = Drive::DriveService.new
scope = 'https://www.googleapis.com/auth/drive'
#drive.authorization = Google::Auth.get_application_default([scope])
#give me list of files
#files = #drive.list_files
puts "Search results:"
#files.items.each do |file|
puts "- File: #{file.title} (#{file.id})"
end
If I have to setup google apps this might be tough since they only have subdomains and I don't have direct access. The type of thing I wish I had been told up front.

Can't retrieve file meta data from Google Drive, 404

I'm having some seriously weird issues with the Google Drive API.
Bear with me here, there's a lot to explain.
I originally got the API working using one of my Google accounts -- let's call it test#google.com for simplicity. I got the Google Picker UI working and it correctly displays the list of files in my Drive account.
I set it to my APP_ID and I have some server-side logic that uses the official google-ruby-api-client gem to connect to the Drive API using the drive.files.get endpoint. I can then download the file's metadata using this snippet:
require 'google/api_client'
client = Google::APIClient.new
# client ID and secret from Google APIs Console
client.authorization.client_id = "{CLIENT_ID}"
client.authorization.client_secret = "{SECRET}"
client.authorization.redirect_uri = "http://myapp.com/users/auth/gdrive"
# access token stored in database from oauth2 flow
client.authorization.access_token = "TOKEN"
client.authorization.scope = [
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile"
]
result = client.execute!(
:api_method => 'drive.files.get',
:version => 'v2',
:parameters => { 'fileId' => params[:file_id] })
With the test#google.com account I tried this on, the result comes back with the file's metadata, and I'm able to download the file. All peachy.
The problem comes when I use a different Google account. I can access the files in Picker, but when the request is sent to the server with the fileId using the above, I just keep getting a 404 error, saying that the file doesn't exist. I've also tried to access the file's metadata using the OAuth 2.0 Playground provided by google, but the weird thing is that I still get that error, but I also get the same 404 error when I use the test#google.com account.
The only thing I can really think of is that I submitted a version of my app with all the Google Drive details once, and installed the app via the Chrome Webstore. After I realized it was showing up for everyone as a Drive-enabled app, I promptly removed it and changed the manifest.json file back to its normal, non-Drive enabled state. I did read that you should have the app installed via the Chrome Webstore to work properly, but I also read that that's not the case anymore. Are your installed Chrome Webstore apps stored in Google's cloud somewhere so they know that it was installed for a particular account? Or are webstore apps just installed locally? I'm so confused.
What am I missing here? I haven't been this frustrated with an API in a really long time. Please help!
Thanks to Ali Afshar for the answer -- the solution (for now) is to temporarily use the full scope of Google Drive instead of just the drive.file scope.
e.g. instead of using this scope,
https://www.googleapis.com/auth/drive.file
use this one instead:
https://www.googleapis.com/auth/drive

How do I connect to the Google Calendar API without the oAuth authentication?

I have been studying the Google Calendar API and the docs on authentication (http://code.google.com/apis/calendar/v3/using.html#auth). It seems that the use case mentioned here is writing an application that accesses the user's calendar. However, I am writing a web page that will access the web site owner's calendar and display just that one calendar's information. So, I don't want the user to enter in their Google account information which is what oAuth wants to do.
Basically, I am looking for a way to access a single private Google calendar and authenticate to it by passing the credentials directly to the service.
There is a similar questions here: How to use OAuth with Google Calendar to access only ONE calendar?
that seems to indicate that the poster originally was passing the credentials directly. Is this feature still available? How do you handle the use case I described?
If I'm not wrong, they've launched Service Account for this now: https://developers.google.com/accounts/docs/OAuth2ServiceAccount
Edit:
Here's the modification from their Prediction API
session_start();
require_once "google-api-php-client/src/Google_Client.php";
require_once "google-api-php-client/src/contrib/Google_CalendarService.php";
const CLIENT_ID = '...';
const SERVICE_ACCOUNT_NAME = '...';
// Make sure you keep your key.p12 file in a secure location, and isn't
// readable by others.
const KEY_FILE = '...';
$client = new Google_Client();
$client->setApplicationName("...");
if (isset($_SESSION['token'])) {
$client->setAccessToken($_SESSION['token']);
}
// Load the key in PKCS 12 format (you need to download this from the
// Google API Console when the service account was created.
$key = file_get_contents(KEY_FILE);
$client->setAssertionCredentials(new Google_AssertionCredentials(
SERVICE_ACCOUNT_NAME,
array('https://www.googleapis.com/auth/calendar', "https://www.googleapis.com/auth/calendar.readonly"),
$key)
);
$client->setClientId(CLIENT_ID);
$service = new Google_CalendarService($client);
//Save token in session
if ($client->getAccessToken()) {
$_SESSION['token'] = $client->getAccessToken();
}
//And now you can use the code in their PHP examples, like: $service->events->listEvents(...)
I have the same problem. I found this 3 part tutorial that makes exactly what you want . Web page for bookings
You create a web page that writes directly into your own calendar (not the users) and that is why users don't have to give you permission to access their calendar.
This solution works for me, but you have to manage it directly with REST.
I am looking for a way to use google api php client because it seems a bit simpler. But I have not yet found a way to how to properly edit the google-api-php-client/src/config.php file to work in a way where you authenticate yourself not the actual user, because you need access to your calendar. If anyone has an idea or a script that would do that I would be very grateful.
Also take a look here:
https://github.com/googleapis/google-api-php-client#authentication-with-service-accounts
After creating a service account you can authenticate without the user prompt for adding items to a calendar your service owns.

Resources