Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!
I'm trying to test the APIs (get a list of datasets in my workspace) before progressing on to doing some dataflow work, but anything I do with the APIs after getting my token returns a 403 error.
I'm using the example website sample code from the adal python github page (https://github.com/AzureAD/azure-activedirectory-library-for-python/tree/dev/sample)
I added an extra requests.get call hitting up https://api.powerbi.com/v1.0/myorg/datasets to get a list of datasets and then just printing it out to the console, which gives me:
Running API
API Result: 403
The resource in the parameters.json file passed into the python script is "00000009-0000-0000-c000-000000000000" which I believe is correct. When I run the token through jwt.io to check it out, I see my username and scps of:
Capacity.Read.All Capacity.ReadWrite.All Content.Create Dashboard.Read.All Dashboard.ReadWrite.All Dataflow.Read.All Dataflow.ReadWrite.All Dataset.ReadWrite.All Group.Read Report.ReadWrite.All Workspace.Read.All Workspace.ReadWrite.All
Any help would be appreciated.
try:
from http import server as httpserver
from http import cookies as Cookie
except ImportError:
import SimpleHTTPServer as httpserver
import Cookie as Cookie
try:
import socketserver
except ImportError:
import SocketServer as socketserver
try:
from urllib.parse import urlparse, parse_qs
except ImportError:
from urlparse import urlparse, parse_qs
import json
import os
import random
import string
import sys
import requests
import urllib.request
import adal
# You can provide account information by using a JSON file. Either
# through a command line argument, 'python sample.py parameters.json', or
# specifying in an environment variable of ADAL_SAMPLE_PARAMETERS_FILE.
#
# The information inside such file can be obtained via app registration.
# See https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/Register-your-application-with-Azure-Active-Directory
#
# {
# "resource": "your_resource",
# "tenant" : "rrandallaad1.onmicrosoft.com",
# "authorityHostUrl" : "https://login.microsoftonline.com",
# "clientId" : "624ac9bd-4c1c-4687-aec8-b56a8991cfb3",
# "clientSecret" : "verySecret=""
# }
parameters_file = (sys.argv[1] if len(sys.argv) == 2 else
os.environ.get('ADAL_SAMPLE_PARAMETERS_FILE'))
if parameters_file:
with open(parameters_file, 'r') as f:
parameters = f.read()
sample_parameters = json.loads(parameters)
else:
raise ValueError('Please provide parameter file with account information.')
PORT = 8088
TEMPLATE_AUTHZ_URL = ('https://login.windows.net/{}/oauth2/authorize?'+
'response_type=code&client_id={}&redirect_uri={}&'+
'state={}&resource={}')
PBI_RESOURCE = '00000009-0000-0000-c000-000000000000'
RESOURCE = sample_parameters.get('resource', PBI_RESOURCE)
REDIRECT_URI = 'http://localhost:{}/getAToken'.format(PORT)
authority_url = (sample_parameters['authorityHostUrl'] + '/' +
sample_parameters['tenant'])
class OAuth2RequestHandler(httpserver.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/':
self.send_response(307)
login_url = 'http://localhost:{}/login'.format(PORT)
self.send_header('Location', login_url)
self.end_headers()
elif self.path == '/login':
auth_state = (''.join(random.SystemRandom()
.choice(string.ascii_uppercase + string.digits)
for _ in range(48)))
cookie = Cookie.SimpleCookie()
cookie['auth_state'] = auth_state
authorization_url = TEMPLATE_AUTHZ_URL.format(
sample_parameters['tenant'],
sample_parameters['clientId'],
REDIRECT_URI,
auth_state,
RESOURCE)
self.send_response(307)
self.send_header('Set-Cookie', cookie.output(header=''))
self.send_header('Location', authorization_url)
self.end_headers()
elif self.path.startswith('/getAToken'):
is_ok = True
try:
token_response = self._acquire_token()
access_token = token_response['accessToken']
#Later, if the access token is expired it can be refreshed.
#auth_context = adal.AuthenticationContext(authority_url)
#token_response_refresh = auth_context.acquire_token_with_refresh_token(
# token_response['refreshToken'],
# sample_parameters['clientId'],
# RESOURCE,
# sample_parameters['clientSecret'])
################OK We now have a token, lets do stuff with it to see if that works#########################
#refresh_token = token_response_refresh['accessToken']
print("Running API")
headers = {'Authorization': 'Bearer {}'.format(access_token), 'Content-Type': 'application/json'}
api = requests.get('https://api.powerbi.com/v1.0/myorg/datasets', headers=headers)
print("API Result: {}\n{}\n".format(api.status_code, api.text))
message = "Full Token Response: {}<br><br>token: {}<br><br>Status Code: {}<br>Returned: {}".format(token_response, access_token, api.status_code, api.text)
except ValueError as exp:
message = str(exp)
is_ok = False
self._send_response(message, is_ok)
def _acquire_token(self):
parsed = urlparse(self.path)
code = parse_qs(parsed.query)['code'][0]
state = parse_qs(parsed.query)['state'][0]
cookie = Cookie.SimpleCookie(self.headers["Cookie"])
if state != cookie['auth_state'].value:
raise ValueError('state does not match')
### Main logic begins
auth_context = adal.AuthenticationContext(authority_url)
return auth_context.acquire_token_with_authorization_code(
code,
REDIRECT_URI,
RESOURCE,
sample_parameters['clientId'],
sample_parameters['clientSecret'])
### Main logic ends
def _send_response(self, message, is_ok=True):
self.send_response(200 if is_ok else 400)
self.send_header('Content-type', 'text/html')
self.end_headers()
if is_ok:
#todo, pretty format token response in json
message_template = ('<html><head><title>Succeeded</title></head>'
'<body><p>{}</p></body></html>')
else:
message_template = ('<html><head><title>Failed</title></head>'
'<body><p>{}</p></body></html>')
output = message_template.format(message)
self.wfile.write(output.encode())
httpd = socketserver.TCPServer(('', PORT), OAuth2RequestHandler)
print('serving at port', PORT)
httpd.serve_forever()
Solved! Go to Solution.
Finally figured it out. The resource in the parameters.json needs to be https://analysis.windows.net/powerbi/api or it won't work.
Finally figured it out. The resource in the parameters.json needs to be https://analysis.windows.net/powerbi/api or it won't work.
User | Count |
---|---|
15 | |
2 | |
1 | |
1 | |
1 |
User | Count |
---|---|
17 | |
11 | |
5 | |
4 | |
3 |