AdalError in python with API - python

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

Related

Microsoft Graph API Permissions

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!')

Getting authenticated to personal OneDrive

am trying to get authenticated with a Python to OneDrive (personal, not for business). I've registered an app in Azure AD, got client id and secret (turned to be not needed, as I am using 'desktop' app which is public and not using a secret), and Using browser and postman, managed to obtain an access token.
trying 2 different options now, both with no luck.
import hidden
from hidden import oauthr
import requests
import json
client_secret = oauthr()["consumer_secret"]
client_id = oauthr()["consumer_key"]
scope = 'Files.ReadWrite.All'
redirect_uri = "http://localhost/auth-response"
code = oauthr()["code"]
token = oauthr()["token_secret"]
RootFolder = 'https://api.onedrive.com/v1.0/drive/root:/'
r = requests.get(RootFolder, headers = {'Authorization': 'Bearer ' + token})
content=json.loads(r.content)
print(content)
This one results in: {'error': {'code': 'unauthenticated', 'message': 'Authentication failed'}}
Second thing I try is MSAL:
import hidden
from hidden import oauthr
import requests
import json
from msal import PublicClientApplication
client_secret = oauthr()["consumer_secret"]
client_id = oauthr()["consumer_key"]
scopes = ['https://graph.microsoft.com/.default']
redirect_uri = "http://localhost/auth-response"
code = oauthr()["code"]
token = oauthr()["token_secret"]
user = input("user: ")
pwd = input("pwd: ")
print('scopes are: ', scopes, ' the data type is: ',type(scopes) )
app = PublicClientApplication(
client_id,
authority="https://login.microsoftonline.com/UsadyProgimnasia.onmicrosoft.com")
result = None
flow = app.initiate_device_flow(scopes = scopes)
accounts = app.get_accounts()
if accounts:
# If so, you could then somehow display these accounts and let end user choose
print("Pick the account you want to use to proceed:")
for a in accounts:
print(a["username"])
# Assuming the end user chose this one
chosen = accounts[0]
# Now let's try to find a token in cache for this account
result = app.acquire_token_silent([scopes], account=chosen)
if not result:
print('So no suitable token exists in cache. Let\'s get a new one from Azure AD')
#result = app.acquire_token_by_username_password(user, pwd, scopes)
result = app.acquire_token_by_authorization_code(code, scopes, redirect_uri=redirect_uri, nonce=None, claims_challenge=None)
#result = app.acquire_token_by_device_flow(flow, claims_challenge=None)
if "access_token" in result:
print(result["access_token"]) # Yay!
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id")) # You may need this when reporting a bug
This gives a invalid_grant AADSTS70000121: The passed grant is from a personal Microsoft account and is required to be sent to the /consumers or /common endpoint.
Would appreciate an advice, chaps
Regards

"unauthorized_client" error when using google API to send an email

I get this error when running my code:
google.auth.exceptions.RefreshError: ('unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.', {'error': 'unauthorized_client', 'error_description': 'Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested.'})
Here is the code:
from __future__ import print_function
from googleapiclient import discovery, errors
from oauth2client import file, client, tools
from google.oauth2 import service_account
from email.mime.text import MIMEText
import base64
SERVICE_ACCOUNT_FILE = 'keys.json'
SCOPES = [' https://www.googleapis.com/auth/gmail.send']
# The user we want to "impersonate"
USER_EMAIL = "myName#myDomain.com"
def validationService():
# Set the crendentials
credentials = service_account.Credentials. \
from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
# Delegate the credentials to the user you want to impersonate
delegated_credentials = credentials.with_subject(USER_EMAIL)
service = discovery.build('gmail', 'v1', credentials=delegated_credentials)
return service
def send_message(service):
gmail_from = 'myName#myDomain.com'
gmail_to = 'anotherName#gmail.com'
gmail_subject = 'Hello World'
gmail_content = 'test test'
message = MIMEText(gmail_content)
message['to'] = gmail_to
message['from'] = gmail_from
message['subject'] = gmail_subject
raw = base64.urlsafe_b64encode(message.as_bytes())
raw = raw.decode()
body = {'raw': raw}
try:
message = (service.users().messages().send(userId='me', body=body)
.execute())
print('your message has been sent')
return message
except errors.HttpError as error:
print('An error occurred: %s' % error)
send_message(validationService())
I don't understand where in the code my email address "gmail_from" is connected to my email address. Apart from that i've given access to my IDE in gmail:
I've also created in the google console OAuth 2.0 Client IDs credentials and Service Accounts credentials but i don't really understand how/where to use these.
What am I missing?
On the google website: https://developers.google.com/identity/protocols/oauth2/service-account#error-codes I have found that I needed to "In the Domain-wide delegation page in the Admin console, remove the client, and re-add it with the numeric ID." but i don't understand how to do that nor how that would help.
There is an extra space in the scope:
SCOPES = [' https://www.googleapis.com/auth/gmail.send']
^ 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.

How to connect Microsoft Graph using python without UI Interaction?

I'm following this link> python-sample-send-mail to send email, but I would like to skip or authenticate the user on background without any UI interaction. I don't like the idea that OAuth: pop up a window.
My application is registered in Microsoft Azure AD.
I would like to know how to authenticate with a Email username and a password without UI interaction.
Thanks a lot!
Based on the doc:AAD V2.0 end pointRestrictions on protocols ,The OAuth 2.0 Resource Owner Password Credentials Grant is not supported by the v2.0 endpoint.
In python ADAL sdk , client secret is not accepted by acquire_token_with_username_password method, so you need to register native app.
Sample code:
import adal
import requests
tenant = ""
client_id = "app id"
# client_secret = ""
username = ""
password = "”
authority = "https://login.microsoftonline.com/" + tenant
RESOURCE = "https://graph.microsoft.com"
context = adal.AuthenticationContext(authority)
# Use this for Client Credentials
#token = context.acquire_token_with_client_credentials(
# RESOURCE,
# client_id,
# client_secret
# )
# Use this for Resource Owner Password Credentials (ROPC)
token = context.acquire_token_with_username_password(RESOURCE, username, password, client_id)
graph_api_endpoint = 'https://graph.microsoft.com/v1.0{0}'
# /me only works with ROPC, for Client Credentials you'll need /<UsersObjectId/
request_url = graph_api_endpoint.format('/me')
headers = {
'User-Agent' : 'python_test',
'Authorization' : 'Bearer {0}'.format(token["accessToken"]),
'Accept' : 'application/json',
'Content-Type' : 'application/json'
}
response = requests.get(url = request_url, headers = headers)
print (response.content)
In addition, native app is not necessary if you use REST API, but client secret need to be set.
Hope it helps you.

Categories