Calendar events not fetching | Microsoft Graph API | Using premium personal outlook accounts - python

I am trying to fetch the calendar events from my personal premium outlook account. It is not a work account.
I have a office 365 subscription. Using the same, I have setup Azure actuve directory where I have added my python web application, granted all the required permissions to the app. While accessing the API via web app I am able to fetch profile details, users and all, but unable to get data related to events, calendar etc.
I am getting this error - "message": "The tenant for tenant guid \u00*******b5d-*9-4b-b1-c5c***2ec8\u0027 does not exist."
I looked at many solutions on msdn and also on stackoverflow, but everyone told to get a premium account which I did but still the issue is not resolved.
Please help resolving the same. Thankyou in advance :)
I am attaching the copy of my app.config file for your reference.
import os
CLIENT_SECRET = "client secret key"
AUTHORITY = "https://login.microsoftonline.com/tenant id"
CLIENT_ID = "client id"
REDIRECT_PATH = "/getAToken"
ENDPOINT =ENDPOINT = 'https://graph.microsoft.com/v1.0/users/{my id}/events
# I also tried 'ENDPOINT = ' 'https://graph.microsoft.com/v1.0/users/{my id}/calendar/events''
SCOPE = ["User.ReadBasic.All"]
SESSION_TYPE = "filesystem" # So token cache will be stored in server-side session

use 'Oauth' class of python to pass all your token and ADD details like client id, client secret etc.
Something like this -
(Note config files contains all my details mentioned above.)
OAUTH = OAuth(APP)
MSGRAPH = OAUTH.remote_app(
'microsoft',
consumer_key=config.CLIENT_ID,
consumer_secret=config.CLIENT_SECRET,
request_token_params={'scope': config.SCOPES},
base_url=config.RESOURCE + config.API_VERSION + '/',
request_token_url=None,
access_token_method='POST',
access_token_url=config.AUTHORITY_URL + config.TOKEN_ENDPOINT,
authorize_url=config.AUTHORITY_URL + config.AUTH_ENDPOINT)
my config file :
CLIENT_ID = 'put here'
CLIENT_SECRET = 'put here'
REDIRECT_URI = 'http://localhost:5000/login/authorized'
AUTHORITY_URL = 'https://login.microsoftonline.com/common'
AUTH_ENDPOINT = '/oauth2/v2.0/authorize'
TOKEN_ENDPOINT = '/oauth2/v2.0/token'
RESOURCE = 'https://graph.microsoft.com/'
API_VERSION = 'v1.0'
SCOPES = ['User.Read', 'Mail.Send', 'Files.ReadWrite','Calendars.Read', 'Calendars.ReadWrite']
now you can call the get events like this :
eventResponse = MSGRAPH.get('me/events',headers=request_headers()) #request_headers() return all the requeried headers
print(eventResponce.data)

Related

How to use credentials obtained from google with google API

Libs: dj-rest-auth + allauth
I. I'm trying to interact with google API with credentials that I use to obtain internal access token. I managed to obtain both code and token but can't find how to use them with google API. The last page I found inapplicable is https://github.com/googleapis/google-api-python-client/blob/main/docs/oauth.md but probably I'm missing some things.
Here's the view I'm trying to use google API in:
class CreateGoogleDoc(GenericAPIView):
...
def get(self, request):
token = request.query_params['token']
module_dir = os.path.dirname(__file__) # get current directory
file_path = os.path.join(module_dir, 'client_secret.json')
flow = Flow.from_client_secrets_file(
file_path,
scopes=SCOPES,
redirect_uri='https://example.com'
)
credentials = service_account.Credentials.from_service_account_file(file_path, scopes=SCOPES)
service = build('docs', 'v1', credentials=credentials)
document = service.documents().create().execute()
return Response([document['documentId']])
II. While I tried to swap code to internal access token class I got another error:
Error retrieving access token: `{ "error": "invalid_request", "error_description": "You can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure. You can let the app developer know that this app doesn't comply with one or more Google validation rules."}`
Here's a view that I'm using for swapping:
GoogleLogin(SocialLoginView):
adapter_class = GoogleOAuth2Adapter
callback_url = 'http://localhist:8000/dj-rest-auth/google/'
client_class = OAuth2Client
Thanks!
Offering a workaround
If you already have a token from the GET response, why are you trying to get credentials from a service account file? Probably there is some wrong configuration there, but if you already have the access token, you can just use it like below and avoid the whole service account token fetching.
from google.oauth2.credentials import Credentials
# ...
def get(self, request):
token = request.query_params['token']
credentials = Credentials(token)
service = build('docs', 'v1', credentials=credentials)
document = service.documents().create().execute()
return Response([document['documentId']])

Unable to generate refresh token for Google Ads API using generate_refresh_token.py

I am very new to Python and Stackoverflow. I am working on connecting my Google Ads account with Python to automate few standard charts creation and email them to my team members. Please help me resolve this as I had not been able to find an answer to it upon Googling either.
Let me know if I have missed out on any info which might provide more context to the question here.
I have been using the steps as mentioned by #msaniscalchi. Created client ID and client Secret from https://console.developers.google.com and created googleads.yaml file in the same directory as the generate_refresh_token.py. When I run the script with respective client ID and client Secret values, I am getting "invalid syntax" error. I have verified my multiple times my client secret and ID values multiple times.
"""Generates refresh token for AdWords using the Installed Application flow."""
import argparse
import sys
from google_auth_oauthlib.flow import InstalledAppFlow
from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
# Your OAuth2 Client ID and Secret. If you do not have an ID and Secret yet,
# please go to https://console.developers.google.com and create a set.
DEFAULT_CLIENT_ID = 609XXXXXXX22-58mbhXXXXXXXXXXXXXXXXXX6ri.apps.googleusercontent.com
DEFAULT_CLIENT_SECRET = 7uO7XXXXXXXXXXXXXX7dKBAP
# The AdWords API OAuth2 scope.
SCOPE = u'https://www.googleapis.com/auth/adwords'
# The redirect URI set for the given Client ID. The redirect URI for Client ID
# generated for an installed application will always have this value.
_REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
parser = argparse.ArgumentParser(description='Generates a refresh token with '
'the provided credentials.')
parser.add_argument('--client_id', default=DEFAULT_CLIENT_ID,
help='Client Id retrieved from the Developer\'s Console.')
parser.add_argument('--client_secret', default=DEFAULT_CLIENT_SECRET,
help='Client Secret retrieved from the Developer\'s '
'Console.')
parser.add_argument('--additional_scopes', default=None,
help='Additional scopes to apply when generating the '
'refresh token. Each scope should be separated by a comma.')
class ClientConfigBuilder(object):
"""Helper class used to build a client config dict used in the OAuth 2.0 flow.
"""
_DEFAULT_AUTH_URI = 'https://accounts.google.com/o/oauth2/auth'
_DEFAULT_TOKEN_URI = 'https://accounts.google.com/o/oauth2/token'
CLIENT_TYPE_WEB = 'web'
CLIENT_TYPE_INSTALLED_APP = 'installed'
def __init__(self, client_type=None, client_id=None, client_secret=None,
auth_uri=_DEFAULT_AUTH_URI, token_uri=_DEFAULT_TOKEN_URI):
self.client_type = client_type
self.client_id = client_id
self.client_secret = client_secret
self.auth_uri = auth_uri
self.token_uri = token_uri
def Build(self):
"""Builds a client config dictionary used in the OAuth 2.0 flow."""
if all((self.client_type, self.client_id, self.client_secret,
self.auth_uri, self.token_uri)):
client_config = {
self.client_type: {
'client_id': self.client_id,
'client_secret': self.client_secret,
'auth_uri': self.auth_uri,
'token_uri': self.token_uri
}
}
else:
raise ValueError('Required field is missing.')
return client_config
def main(client_id, client_secret, scopes):
"""Retrieve and display the access and refresh token."""
client_config = ClientConfigBuilder(
client_type=ClientConfigBuilder.CLIENT_TYPE_WEB, client_id=client_id,
client_secret=client_secret)
flow = InstalledAppFlow.from_client_config(
client_config.Build(), scopes=scopes)
# Note that from_client_config will not produce a flow with the
# redirect_uris (if any) set in the client_config. This must be set
# separately.
flow.redirect_uri = _REDIRECT_URI
auth_url, _ = flow.authorization_url(prompt='consent')
print('Log into the Google Account you use to access your AdWords account '
'and go to the following URL: \n%s\n' % auth_url)
print('After approving the token enter the verification code (if specified).')
code = input('Code: ').strip()
try:
flow.fetch_token(code=code)
except InvalidGrantError as ex:
print('Authentication has failed: %s' % ex)
sys.exit(1)
print('Access token: %s' % flow.credentials.token)
print('Refresh token: %s' % flow.credentials.refresh_token)
if __name__ == '__main__':
args = parser.parse_args()
configured_scopes = [SCOPE]
if not (any([args.client_id, DEFAULT_CLIENT_ID]) and
any([args.client_secret, DEFAULT_CLIENT_SECRET])):
raise AttributeError('No client_id or client_secret specified.')
if args.additional_scopes:
configured_scopes.extend(args.additional_scopes.replace(' ', '').split(','))
main(args.client_id, args.client_secret, configured_scopes)
When I run the above code, I am getting the "Invalid Syntax" error highlighting at the numeric part of the Client ID and Secret.
Syntax error screenshot attached here
Editor Highlighter screenshot attached here

Python onedrivesdk - invalid_request error

I want to upload files and create folders on OneDrive with Python. So i copied the code from the OnDrive GitHub GitHub, registered my App at Azure, copied the ID and created an secret. So far so good.
But now, if i run my code. The Browser opens asking for the permission to login automatically, agreed and then i get this error:
Exception: invalid_request
I think it has something to do with the redirect_uri because if i copy this into my browser i cant access it.
Here is my code:
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
redirect_uri = 'http://localhost:8080/'
client_secret = 'The secret i created on Azure'
scopes=['wl.signin', 'wl.offline_access', 'onedrive.readwrite']
client = onedrivesdk.get_default_client(
client_id='The ID Azure created for me', scopes=scopes)
auth_url = client.auth_provider.get_auth_url(redirect_uri)
#this will block until we have the code
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
client.auth_provider.authenticate(code, redirect_uri, client_secret)
I also tried it with an Proxy:
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
from onedrivesdk.helpers import http_provider_with_proxy
redirect_uri = 'http://localhost:8080'
client_secret = 'Secret created with Azure'
client_id = 'ID id got from Azure'
scopes=['wl.signin', 'wl.offline_access', 'onedrive.readwrite']
client = onedrivesdk.get_default_client(client_id, scopes=scopes)
auth_url = client.auth_provider.get_auth_url(redirect_uri)
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
proxy = {
'http': 'http://localhost:8888',
'https': 'https://localhost:8888'
}
http = http_provider_with_proxy.HttpProviderWithProxy(proxy, verify_ssl=True)
auth = onedrivesdk.AuthProvider(http, client_id, ['onedrive.readwrite'])
client = onedrivesdk.OneDriveClient(redirect_uri, auth, http)
f = onedrivesdk.Folder()
i = onedrivesdk.Item()
i.name = 'New Folder'
i.folder = f
returned_item = client.item(drive='me', id='root').children.add(i)
That gives me this error message:
RuntimeError: Session must be authenticated
before applying authentication to a request.
Your code works - e.g. it sends the info you want to send. However the credentials you have entered will of course return an invalid request - you're trying to connect to azure with:
client_id: 'The ID Azure created for me'
Which I'm pretty sure doesn't exists. The issue is you need an account & pass your script those (valid) account informations to connect to it.

Use of token code when accessing OneDrive using Python

I am writing some code to move files over to OneDrive (enterprise account). My app is authenticated in Azure AD and should have the correct accesses (Files.ReadWrite.All in MS Graph, Sites.ReadWrite.All in Office365 SPO and User.Read in Azure AD).
The code to receive the app token works fine:
import msal
client_id = 'dc185bb*************6bcda94'
authority_host_uri = 'https://login.microsoftonline.com'
discovery_uri = 'https://api.office.com/discovery/'
client_secret = 'VsY7vV**************ToiA0='
tenant = '4a6*********************65079'
authority_uri = authority_host_uri + '/' + tenant
scopes=['https://graph.microsoft.com/.default']
app = msal.ConfidentialClientApplication(
client_id=client_id, authority=authority_uri,
client_credential=client_secret)
result = app.acquire_token_for_client(scopes=scopes)
print(result)
However, when I try to use this token with the OneDrive SDK library it seems like I am not able pass it through:
def __init__(self, http_provider, client_id=None, scopes=None, access_token=None, session_type=None, loop=None,
auth_server_url=None, auth_token_url=None):
"""Initialize the authentication provider for authenticating
requests sent to OneDrive
Args:
http_provider (:class:`HttpProviderBase<onedrivesdk.http_provider_base>`):
The HTTP provider to use for all auth requests
client_id (str): Defaults to None, the client id for your
application
scopes (list of str): Defaults to None, the scopes
that are required for your application
access_token (str): Defaults to None. Not used in this implementation.
The above is from the auth_provider.py part of the onedrivesdk, and clearly states the access_token is not used in the implementation.
Is there another way around this? Or other libraries to use?
You could try to use this Authentication of OneDrive for Business.
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
from onedrivesdk.helpers.resource_discovery import ResourceDiscoveryRequest
redirect_uri = 'http://localhost:8080'
client_id = your_client_id
client_secret = your_client_secret
discovery_uri = 'https://api.office.com/discovery/'
auth_server_url='https://login.microsoftonline.com/common/oauth2/authorize'
auth_token_url='https://login.microsoftonline.com/common/oauth2/token'
http = onedrivesdk.HttpProvider()
auth = onedrivesdk.AuthProvider(http,
client_id,
auth_server_url=auth_server_url,
auth_token_url=auth_token_url)
auth_url = auth.get_auth_url(redirect_uri)
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
auth.authenticate(code, redirect_uri, client_secret, resource=discovery_uri)
# If you have access to more than one service, you'll need to decide
# which ServiceInfo to use instead of just using the first one, as below.
service_info = ResourceDiscoveryRequest().get_service_info(auth.access_token)[0]
auth.redeem_refresh_token(service_info.service_resource_id)
client = onedrivesdk.OneDriveClient(service_info.service_resource_id + '/_api/v2.0/', auth, http)
Upload an Item:
returned_item = client.item(drive='me', id='root').children['newfile.txt'].upload('./path_to_file.txt')
For more examples, you can refer to this link.

Google Content API for Shopping - Python OAuth invalid_grant

I'm attempting to utilize the google content api for shopping to add/update products in my google merchant account.
It appears that I'm having some problems with OAuth.
Thanks in advance for the help!
Example Code
f = file("key.p12", 'rb')
CLIENT_SECRET = f.read()
f.close()
ACCOUNT_ID = 'xxxxxxx'
CLIENT_ID = 'xxxxxxxxx.apps.googleusercontent.com'
SERVICE_ACCOUNT_EMAIL = 'xxxxxxxx#developer.gserviceaccount.com'
SCOPE = 'https://www.googleapis.com/auth/structuredcontent'
USER_AGENT = 'content-api-example'
credentials = SignedJwtAssertionCredentials(
SERVICE_ACCOUNT_EMAIL,
CLIENT_SECRET,
scope=SCOPE)
http = httplib2.Http()
http = credentials.authorize(http)
auth_token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
entry = gdata.contentforshopping.data.ProductEntry()
...
shopping_client.InsertProduct(entry)
Output
auth2client.client.AccessTokenRefreshError: invalid_grant
It looks like you are using a Service Account to access the API. Make sure you login to the respective Google Merchant Center account you are trying to access and add the Service account email generated from the Google Developer Console (in your code, this is the value within SERVICE_ACCOUNT_EMAIL") to the "Settings > Users" section and grant this email address "standard" or "administrative" access depending on the scope you are requesting.
This is an often missed step and not called out specifically in Google's documentation.
Hope this helps

Categories