Google Calendar API / Python : I can't delete event - python

when I want to delete an event with a "XXXXXXX#group.calendar.google.com" with this command (below), it's work with my primary email but not with this "XXXXXXX#group.calendar.google.com":
from __future__ import print_function import httplib2 import os
from apiclient import discovery from oauth2client import file import
oauth2client from oauth2client import client from oauth2client import
tools
import datetime import requests
SCOPES = 'https://www.googleapis.com/auth/calendar' CLIENT_SECRET_FILE
= 'credentials.json' APPLICATION_NAME = 'Google Calendar API Python Quickstart' calendar_use = 'XXXXXXX#group.calendar.google.com'
def get_credentials():
"""Gets valid user credentials from storage.
If nothing has been stored, or if the stored credentials are invalid,
the OAuth2 flow is completed to obtain the new credentials.
Returns:
Credentials, the obtained credential.
"""
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,'calendar-python-quickstart.json')
store = oauth2client.file.Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def deleteEvent():
get_credentials()
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('calendar', 'v3', http=http)
x = requests.delete('https://www.googleapis.com/calendar/v3/calendars/xxxxxxxxxxxxx#group.calendar.google.com/events/xxxxxxxxxxxxxxxxx')
print(x.text)
deleteEvent()
But i get this error message, and i can't find the answer.
{
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED",
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "CREDENTIALS_MISSING",
"domain": "googleapis.com",
"metadata": {
"service": "calendar-json.googleapis.com",
"method": "calendar.v3.Events.Delete"
When I open the link, which is write in the error code, I don't find the anwser
However, I can already create event, but i can't delete. Thanks for all

I guess you don't need to use request.delete (Because the request doesn't get auth credentials) but something like
service.events().delete(calendarId=calendarId, eventId=eventId).execute()
you just need to set up proper calendarId, eventId

Related

Missing API key even though I am using OAuth

I am a beginner programmer. I am trying to work with Google API. I am using the OAuth to send requests to Google Calendar API. However, I get error 403:
{
"error": {
"code": 403,
"message": "The request is missing a valid API key.",
"errors": [
{
"message": "The request is missing a valid API key.",
"domain": "global",
"reason": "forbidden"
}
],
"status": "PERMISSION_DENIED"
}
}
The following question Google Calendar "The request is missing a valid API key" when using OAuth suggests using:
google.calendar({ version: "v3", auth: client })
However my code provided by Google uses:
service = build('calendar', 'v3', credentials=creds)
so the suggested solution is not applicable.
My full code is the same as Google API's provided 'Quickstart.py' except for the name of the client_secre_file:
from __future__ import print_function
import datetime
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
def main():
"""Shows basic usage of the Google Calendar API.
Prints the start and name of the next 10 events on the user's calendar.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'client_secret_desktop.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('calendar', 'v3', credentials=creds)
# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
return
# Prints the start and name of the next 10 events
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
print(start, event['summary'])
except HttpError as error:
print('An error occurred: %s' % error)
if __name__ == '__main__':
main()
Maybe there is an issue in my Credentials configuration?

401 error when trying to send a get requet to GMAIL API with access token

Hi I am trying to fetch the emails using gmail api. I have used google's boilerplate code to authorize access to my private data and an access token is created.Now I want to make a get request using 'aiohttp'. Below is the function that I have written. It gives me 401 error. What am I doing wrong?
token generator function:(this is the code provided by google in gmail api docs, I just wrapped it into a function)
def authenticate(self):
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
self.service = build('gmail', 'v1', credentials=creds)
async def __get_email_by_id(self, id):
url = GET_MAIL_FROM_ID_URL.format("me", id)
headers = {'Authorization': 'Bearer {}'.format(CRED['token'])}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as response:
print("Content:", await response.text())
return json.loads(await response.text())
Below object is retreived from my local db, where I have stored all the emails and their ids(using code from gmail api docs). Now I am trying to fetch email using the id.
mail: {'_id': ObjectId('6134dfa9ac85cffb6a8d4125'), 'id': '17bb5be9d7b9eb97', 'threadId': '17bb5be9d7b9eb97'}
CRED object:
CRED = {
"token": "ya29.a0ARrdaM-xxxxxxxxxxxxxxxxxxxxxxxTPHExxllfnfLXXBi87udo4eJX-gn21WPq5t2uehpaPO7bhBh0bYQNpsMKFIVucg0d0F7gI5IVwxxxxxxxx-sQ-LWuSSgQRCiguQHqn5ImGJ6aoHLRWxxxxxxxxxxxxxxxx",
"refresh_token": "1//0ggpEqfxxxxxxxxxxARAAGBASNwF-L9IrfyKVwwRbTd71C0p0s3urnFjYVHvV7QDsRxsa_xxxxxxxxxxxxxx_4DAB0stzCGDSJQw",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "1xxxxxxxxx96-hpfxxxxxxxxxs16e3avje3mdgalv4h2v.apps.googleusercontent.com",
"client_secret": "U3xxxxxL-nxxxxxxxxxxKzGd",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly"
],
"expiry": "2021-09-07T04:24:48.509005Z"
}
Response:
Status: 401
Content: {
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Invalid Credentials",
"domain": "global",
"reason": "authError",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"
}
}
NOTE: The access token is not expired, the same token object is working when I try to use code provided in google docs as below.
service = build('gmail', 'v1', credentials=creds)
results = service.users().labels().list(userId='me').execute()

Error 403 using Google Drive API with Python - Daily Limit for Unauthenticated Use Exceeded

I'm getting the error 403 using the Google Drive API with Python.
I can see the files on google drive but when I tryed to download it I got the following error:
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
I'm using the code:
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Drive API Quickstart'
def get_credentials():
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'drive-python-quickstart.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else: # Needed only for compatibility with Python 2.6
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('drive', 'v3', http=http)
results = service.files().list(
q="'0BxZjsrGFMvPSNmprUFp0Y25BNFU' in parents", #first execution...
pageSize=10,
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
#print('{0} ({1})'.format(item['name'], item['id']))
#file_id = '0BxZjsrGFMvPSWmtDYXB6RG5VTHM'
request = service.files().get_media(fileId='0BxZjsrGFMvPSWmtDYXB6RG5VTHM')
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
#print ("Download %d%%." % int(status.progress() * 100))
if __name__ == '__main__':
main()
I'm also have the OAuth 2.0 client configured: https://prnt.sc/gqasjz
I don't know what I'm doing wrong.
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
Means that you are trying to access a Google API without being authenticated first. The credentials are not being properly applied to your service. It should be popping up and asking you permission to access your data.

Using python for google calendar watch-requests

I want to set up a watch request for a google calendar, using python
(without setting up a separate domain).
I imported the api client, and can successfully get the authenticated credentials, following the example: https://developers.google.com/google-apps/calendar/quickstart/python.
Then I set up a calendar service, and I am able to list, insert and delete events without any issue.
The problem I am having is when I perform a watch request so that I have a webhook from within python.
I receive the error:
"googleapiclient.errors.HttpError: https://www.googleapis.com/calendar/v3/calendars/primary/events/watch?alt=json returned "WebHook callback must be HTTPS:">"
Clearly I am missing something that needs to be setup so that calendar is satisfied with the webhook I am giving it.
Is it possible to do this from within python, without setting up a separate domain with https, and if so, how?
Minimum working example:
import httplib2
import os
from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
import uuid
try:
import argparse
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
except ImportError:
flags = None
SCOPES = 'https://www.googleapis.com/auth/calendar'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Calendar API'
def get_credentials():
home_dir = os.path.expanduser('~')
credential_dir = os.path.join(home_dir, '.credentials')
if not os.path.exists(credential_dir):
os.makedirs(credential_dir)
credential_path = os.path.join(credential_dir,
'calendar-api.json')
store = Storage(credential_path)
credentials = store.get()
if not credentials or credentials.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
flow.user_agent = APPLICATION_NAME
if flags:
credentials = tools.run_flow(flow, store, flags)
else:
credentials = tools.run(flow, store)
print('Storing credentials to ' + credential_path)
return credentials
def main():
credentials = get_credentials()
http = credentials.authorize(httplib2.Http())
service = discovery.build('calendar', 'v3', http=http)
## TESTING callback receiver:
eventcollect = {
'id': str(uuid.uuid1()),
'type': "web_hook"
}
service.events().watch(calendarId='primary', body=eventcollect).execute()
if __name__ == '__main__':
main()
In the documentation of watch requests, there is a Required Properties part. In this part it is clearly stated that:
An address property string set to the URL that listens and responds to notifications for this notification channel. This is your Webhook callback URL, and it must use HTTPS.
I am sorry but I do not think there is a workaround for this.

failedPrecondition when using google Oauth2 Service Account

There're three types of google api client_id:
1. Web Application
2. Service Account
3. Installed application
I have used 3. Installed application successfullly base on oauth2client, but failed on 2. Service Account. I wanna access my own gmail inbox with oauth2.0 Credentials.
import imaplib
import json
import urllib2
from oauth2client.client import SignedJwtAssertionCredentials
from httplib2 import Http
from apiclient.discovery import build
import os
reldir = os.path.dirname(os.path.relpath(__file__))
CLIENT_SECRET_FILE = os.path.join(reldir, 'gmail_service.json')
OAUTH_SCOPE = "https://mail.google.com"
GMAIL_ADDRESS = 'my_gmail_address#gmail.com'
def jwt_oauth2():
'''
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
'''
with open(CLIENT_SECRET_FILE) as f:
data = json.loads(f.read())
private_key = data['private_key']
client_email = data['client_email']
credentials = SignedJwtAssertionCredentials(
client_email, private_key, scope=OAUTH_SCOPE)
http_auth = credentials.authorize(Http())
try:
gmail_service = build('gmail', 'v1', http=http_auth)
threads = gmail_service.users().messages().list(userId='me').execute()
except Exception as e:
return e
I got an exception same as the question. I encounter another exception while trying to add sub=GMAIL_ADDRESS into credentials:
AccessTokenRefreshError: unauthorized_client: Unauthorized client or scope in request.
I'm trying to figure out the problem, with credentials without sub:
>>> credentials = SignedJwtAssertionCredentials(
client_email, private_key, scope=OAUTH_SCOPE)
>>> http = credentials.authorize(Http())
>>> credentials.access_token
>>> credentials.refresh(http)
>>> credentials.access_token
u'ya29.pAGJjddCXjwsiHFN6hKU1yAkdWN7xMJbks5O76Pmrpe1hW1BbgwfZifjp81aDE55ALMVgjv-yBYiyQ'
>>> gmail_service = build('gmail', 'v1', http=http)
>>> request = gmail_service.users().messages().list(userId='me')
>>> response = request.execute()
{
"error": {
"errors": [
{
"domain": "global",
"reason": "failedPrecondition",
"message": "Bad Request"
}
],
"code": 400,
"message": "Bad Request"
}
}
Try to use credentials with sub:
>>> credentials = SignedJwtAssertionCredentials(
client_email, private_key, scope=OAUTH_SCOPE, sub=GMAIL_ADDRESS)
>>> http = credentials.authorize(Http())
>>> credentials.access_token
>>> credentials.refresh(http)
AccessTokenRefreshError: unauthorized_client: Unauthorized client or scope in request.
I found a similar question Google OAuth2 Service Account HTTP/REST Authentication, but I don't know much about node.js. Any help would be appreciated.
You should use the sub field where you specify the account which you want to impersonate.
Say, using your service Account, you want to get details of a user user#domain.com, the sub field should be populated as:
sub: user#domain.com
You should also make sure that you have given the service Account access to users in the domain.
Refer - https://developers.google.com/drive/web/delegation

Categories

Resources