Microsoft Graph API Permissions - python

Well, I've registered a new app with following permissions
Now then i run this code
from O365 import Account
CLIENT_ID = 'xxxx'
SECRET_ID = 'xxxx'
TENANT_ID = 'xxxx'
credentials = (CLIENT_ID, SECRET_ID)
account = Account(credentials, auth_flow_type='credentials', tenant_id=TENANT_ID)
if account.authenticate():
print('Authenticated!')
schedule = account.schedule(resource='my_account#domain')
calendar = schedule.get_default_calendar()
events = calendar.get_events(include_recurring=False)
for event in events:
print(event)
I catch an error
Client Error: 401 Client Error: Unauthorized for url: https://graph.microsoft.com/v1.0/users/my_account#domain/calendar | Error Message: The token contains no permissions, or permissions can not be understood.
It seems like I should provide an access or doing something in azure web interface. I have no idea what should I fix. Could tell me what should I do

Like John Hanley already mentioned - your Scope is missing:
E.g:
from O365 import Account
CLIENT_ID = 'xxxx'
SECRET_ID = 'xxxx'
TENANT_ID = 'xxxx'
credentials = (CLIENT_ID, SECRET_ID)
scopes = ['https://graph.microsoft.com/Calendar.ReadWrite',
'https://graph.microsoft.com/Calendar.Read',
'https://graph.microsoft.com/User.Read']
account = Account(credentials, tenant_id=TENANT_ID)
if account.authenticate(scopes=scopes):
print('Authenticated!')

Related

I am authenticating to azure through python to list down all my virtual machines and I am getting this error

I am getting this error when I try to list down all my vms on Azure through python
Code: AuthorizationFailed
Message: The client "XXXX" with object id "XXXX" does not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/XXXXX or the scope is invalid. If access was recently granted, please refresh your credentials.
my code is below:
from azure.mgmt.compute import ComputeManagementClient
from azure.identity import ClientSecretCredential
Subscription_Id = "XXXX"
Tenant_Id = "XXXXX"
Client_Id = "XXXXX"
Secret = "XXXXX"
credential = ClientSecretCredential(
client_id=Client_Id,
client_secret=Secret,
tenant_id=Tenant_Id
)
compute_client = ComputeManagementClient(credential, Subscription_Id)
vm_list = compute_client.virtual_machines.list_all()
pageobject1 = vm_list.by_page(continuation_token=None)
for page in pageobject1:
for j in page:
print(j)
Instead of passing your app registration applicationId/objectId you need to pass the service principal/appregistration name when you are trying to assign a particular role like virtualmachinecontributor to your Service principal as show in below.
Post providing the required access to the service principal/appregistration you will be able to pull the list of virtual machines in your subscription. we have checked the above python in our local environment which is also working fine.
Here is sample output screenshot for reference:
Updated Answer To pull list of VM's using Resource Management Client:
from azure.mgmt.resource import ResourceManagementClient
from azure.identity import ClientSecretCredential
Subscription_Id = "<subId>"
Tenant_Id = "<tenantid>"
Client_Id = "<appId>"
Secret = "<clientSecret>"
credential = ClientSecretCredential(
client_id=Client_Id,
client_secret=Secret,
tenant_id=Tenant_Id
)
resource_client=ResourceManagementClient(credential=credential,subscription_id=Subscription_Id)
resource_list=resource_client.resources.list()
for item in resource_list:
if(item.type == 'Microsoft.Compute/virtualMachines'):
print(item)

AdalError in python with API

I am trying to use power bi API as shown below
and get this error:
import adal
import requests
import json
import pandas
import requests
print(requests.get("https://login.windows.net/common/UserRealm/johndoe#contoso.com?api-version=1.0").text)
the output:
{"ver":"1.0","account_type":"Managed","domain_name":"contoso.com","cloud_instance_name":"microsoftonline.com","cloud_audience_urn":"urn:federation:MicrosoftOnline"}
the inputs:
authority_url = 'https://login.windows.net/common'
resource_url = 'https://analysis.windows.net/powerbi/api'
client_id = 'myclient_id '
username = 'myusername'
password = 'mypassword'
context = adal.AuthenticationContext(authority=authority_url,
validate_authority=True,
api_version=None)
token = context.acquire_token_with_username_password(resource=resource_url,
client_id=client_id,
username=username,
password=password)
the error:
AdalError: Get Token request returned http error: 400 and server response: {"error":"invalid_request","error_description":"AADSTS90002: Tenant 'domen name' not found. This may happen if there are no active subscriptions for the tenant. Check to make sure you have the correct tenant ID. Check with your subscription administrator.\r\nTrace ID: num-num-num-num-num\r\nCorrelation ID: num-num-num-num-num\r\nTimestamp: 2020-10-18 17:02:34Z","error_codes":[90002],"timestamp":"2020-10-18 17:02:34Z","trace_id":"num-num-num-num-num","correlation_id":"num-num-num-num-num","error_uri":"https://login.microsoftonline.com/error?code=90002"}
notice: I did some edit on the error message (URL) for privacy reason
any ideas what does that mean?
problem is from the settings
authority_url = 'https://login.windows.net/common'
resource_url = 'https://analysis.windows.net/powerbi/api'
client_id = 'myclient_id '
username = 'myusername'
password = 'mypassword'
I don't know wich one, probably client_id

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.

python script for azure activity log

from azure.monitor import MonitorClient
#from azure.mgmt.monitor import MonitorMgmtClient
from azure.mgmt.monitor import MonitorManagementClient
from azure.common.credentials import UserPassCredentials
import datetime
# Replace this with your subscription id
subscription_id = '************'
# See above for details on creating different types of AAD credentials
credentials = UserPassCredentials(
'****', # Your user
'****', # Your password
)
client = MonitorClient(
credentials,
subscription_id
)
monitor_mgmt_client = MonitorManagementClient(
credentials,
subscription_id
)
after running this code its giving error:
raise error
msrest.exceptions.AuthenticationError: , InvalidClientIdError: (invalid_request) AADSTS900144: The request body must contain the following parameter: 'client_id'
It seems you should not use UserPassCredentials anymore, it has been deprecated.
See this link:
In previous version of the SDK, ADAL was not yet available and we provided a UserPassCredentials class. This is considered deprecated and should not be used anymore.
For Authenticate with token credentials, you could try the code below.
from azure.common.credentials import ServicePrincipalCredentials
# Tenant ID for your Azure Subscription
TENANT_ID = 'ABCDEFGH-1234-1234-1234-ABCDEFGHIJKL'
# Your Service Principal App ID
CLIENT = 'a2ab11af-01aa-4759-8345-7803287dbd39'
# Your Service Principal Password
KEY = 'password'
credentials = ServicePrincipalCredentials(
client_id = CLIENT,
secret = KEY,
tenant = TENANT_ID
)
If you need more control, it is recommended to use ADAL and the SDK ADAL wrapper.
import adal
from msrestazure.azure_active_directory import AdalAuthentication
from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD
# Tenant ID for your Azure Subscription
TENANT_ID = 'ABCDEFGH-1234-1234-1234-ABCDEFGHIJKL'
# Your Service Principal App ID
CLIENT = 'a2ab11af-01aa-4759-8345-7803287dbd39'
# Your Service Principal Password
KEY = 'password'
LOGIN_ENDPOINT = AZURE_PUBLIC_CLOUD.endpoints.active_directory
RESOURCE = AZURE_PUBLIC_CLOUD.endpoints.active_directory_resource_id
context = adal.AuthenticationContext(LOGIN_ENDPOINT + '/' + TENANT_ID)
credentials = AdalAuthentication(
context.acquire_token_with_client_credentials,
RESOURCE,
CLIENT,
KEY
)
For more details, you could refer to this link : Authenticate with the Azure Management Libraries for Python.
If you don't have an AD App, follow this link to create it. To get the client id(client id is the same with application id) and key, follow this link.

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.

Categories