credentials = ClientSecretCredential(
client_id,
client_secret,
tenant_id
)
recoveryservices_client = RecoveryServicesClient(credentials, subscription_id)
list_vaults = recoveryservices_client.vaults.list_by_subscription_id()
list_vars returns <iterator object azure.core.paging.ItemPaged at 0x105377df0>
Iteration over itempaged gives this error:
in raise_from
azure.core.exceptions.ClientAuthenticationError: Authentication failed: Unable to get authority configuration for https://login.microsoftonline.com/xx-xx-xxx. Authority would typically be in a format of https://login.microsoftonline.com/your_tenant Also please double check your tenant name or GUID is correct.
Operations with api and the same service principal gives the list without error.
Any advice would be appreciated.
Related
I am trying to access the API to download usage statistics from PowerBI and integrate with other reports. When I run the below code
import requests
import json
base_url = "https://api.powerbi.com/v1.0/myorg/admin/"
url = "https://login.microsoftonline.com/my_tenant_id_goes_here/oauth2/token"
scope = "https://analysis.windows.net/powerbi/api/.default"
grant_type = "client_credentials"
client_id = "my_client_id"
client_secret = "my_client_secret"
resource = "https://analysis.windows.net/powerbi/api"
header = {
"scope": scope,
"grant_type": grant_type,
"client_id": client_id,
"client_secret": client_secret,
"resource": resource
}
r = requests.post(url, data = header)
login_result = r.json()
print(login_result)
token_type = login_result.get("token_type")
access_token = login_result.get("access_token")
authorization_key = token_type + " " + access_token
print('Authentication Key Generated')
headers = {'Content-Type':'application/json','Authorization': authorization_key}
print('Consuming Dashboards Rest End Point')
data = requests.get(base_url + 'dashboards', headers=headers)
print(data)
json_data = data.content
print(json_data)
I get the following result after print(login_result)
{'token_type': 'Bearer', 'expires_in': '3599', 'ext_expires_in': '3599', 'expires_on': '1667296164', 'not_before': '1667292264', 'resource': 'https://analysis.windows.net/powerbi/api', 'access_token': 'longlongalphanumericstring'}
It seems to have found the access token correctly. However when I print data I get a <401> error, and the json_data reads
b'{"error":{"code":"PowerBINotAuthorizedException","pbi.error":{"code":"PowerBINotAuthorizedException","parameters":{},"details":[],"exceptionCulprit":1}}}'
I have checked in Azure for the permissions. I have the Dashboard.Read.All permission.
When I remove the "admin" from
base_url = "https://api.powerbi.com/v1.0/myorg/admin/"
I get
'{"Message":"API is not accessible for application"}'
It looks to me like a permissions error, but I cannot seem to navigate the Azure interface to fix it.
I tried to reproduce the same in my environment via Postman and got the same error as below:
To resolve the error, try the below:
I created an Azure AD Application and granted permissions:
I created an Azure Security Group and added the Service Principal as a Member like below:
In the PowerBi Admin Portal, Enable Allow service principals to use read-only admin APIs add the security group created above:
It takes around 15 mins to reflect the settings. Now I generated the token via Client Credentials flow like below:
I used v2.0 token endpoint:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:clientID
client_secret:ClientSecret
grant_type:client_credentials
scope:https://analysis.windows.net/powerbi/api/.default
I am able to access PowerBi successfully like below:
https://api.powerbi.com/v1.0/myorg/admin/groups/ID
If still the issue persists, try using Authorization Code flow as Tenant.ReadWrite.All is an Application permission.
I want to pull emails by Graph API from client inbox using python.
I started with a tutorial and successfully experimented over my personal inbox.
My problem,
Every time my code generates an authorization URL.
I have to browse through it (using web browser library) , sign in using my credentials and copy paste the authorization code for generating access token.
Which is a lot of manual work every time.
Question :
Is there a way to automate the whole process of token generation ?
Such that my client only shares his application id and client secret, and email is pulled without his sign in credentials ?
My code is attached below -
import msal
from msal import PublicClientApplication
import webbrowser
import requests
import pandas as pd
APPLICATION_ID="app id"
CLIENT_SECRET="client secret"
authority_url='https://login.microsoftonline.com/common/'
base_url = 'https://graph.microsoft.com/v1.0/'
endpoint_url = base_url+'me'
SCOPES = ['Mail.Read','Mail.ReadBasic']
client_instance = msal.ConfidentialClientApplication(client_id = APPLICATION_ID,client_credential = CLIENT_SECRET,authority = authority_url)
authorization_request_url=client_instance.get_authorization_request_url(SCOPES)
#print(authorization_request_url)
# browsing authorization request URL for retrieving authorization code.
webbrowser.open(authorization_request_url,new=True)
# Manually pasting authorization code.
authorization_code='authorization code from authorization URL'
access_token = client_instance.acquire_token_by_authorization_code(code=authorization_code,scopes=SCOPES)
access_token_id=access_token['access_token']
# Rest of the codes are for hitting the end point and retrieving the messages
Any help with code suggestions will be much appreciated.
Thanks in advance
If you would like to authenticate only with a clientId and clientSecret, without any user context, you should leverage a client credentials flow.
You can check this official MS sample that uses the same MSAL library to handle the client credentials flow. It is quite straightforward, as you can see below:
import sys # For simplicity, we'll read config file from 1st CLI param sys.argv[1]
import json
import logging
import requests
import msal
# Optional logging
# logging.basicConfig(level=logging.DEBUG)
config = json.load(open(sys.argv[1]))
# Create a preferably long-lived app instance which maintains a token cache.
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
# token_cache=... # Default cache is in memory only.
# You can learn how to use SerializableTokenCache from
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache
)
# The pattern to acquire a token looks like this.
result = None
# Firstly, looks up a token from cache
# Since we are looking for token for the current app, NOT for an end user,
# notice we give account parameter as None.
result = app.acquire_token_silent(config["scope"], account=None)
if not result:
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
result = app.acquire_token_for_client(scopes=config["scope"])
if "access_token" in result:
# Calling graph using the access token
graph_data = requests.get( # Use token to call downstream service
config["endpoint"],
headers={'Authorization': 'Bearer ' + result['access_token']}, ).json()
print("Graph API call result: ")
print(json.dumps(graph_data, indent=2))
else:
print(result.get("error"))
print(result.get("error_description"))
print(result.get("correlation_id")) # You may need this when reporting a bug
The sample is retrieving a list of users from MS Graph, but it should be just a matter of adapting it to retrieve the list of emails of a specific user by changing the "endpoint" parameter in the parameters.json file to:
"endpoint": "https://graph.microsoft.com/v1.0/users//users/{id | userPrincipalName}/messages"
You can check here more information regarding the MS Graph request to list emails.
register your app
get your tenant id from azure portal and disable mfa
application_id = "xxxxxxxxxx"
client_secret = "xxxxxxxxxxxxx"
#authority_url = "xxxxxxxxxxx"
authority_url = 'xxxxxxxxxxxxxxxxxxxx'
base_url = "https://graph.microsoft.com/v1.0/"
endpoint = base_url+"me"
scopes = ["User.Read"]
tenant_id = "xxxxxxxxxxxx"
token_url = 'https://login.microsoftonline.com/'+tenant_id+'/oauth2/token'
token_data = {
'grant_type': 'password',
'client_id': application_id,
'client_secret': client_secret,
'resource': 'https://graph.microsoft.com',
'scope':'https://graph.microsoft.com',
'username':'xxxxxxxxxxxxxxxx', # Account with no 2MFA
'password':'xxxxxxxxxxxxxxxx',
}
token_r = requests.post(token_url, data=token_data)
token = token_r.json().get('access_token')
print(token)
I was trying to collect the List of Deny Assignments present in a particular tenant, so I passed the required arguments here:
tenant_id = arguments['tenant_id']
client_id = arguments['client_id']
client_secret = arguments['client_secret']
I created ClientSecretCredentials here:
csc = ClientSecretCredential(tenant_id=tenant_id,
client_id=client_id,
client_secret=client_secret)
From some other code, I have received a list of subscription IDs:
for subscription_id in subscription_id_list:
resource_client = authenticate.resource_client(subscription_id)
resources_groups = get_all_resource_groups_detail(resource_client)
I am able to get resourceGroups in that subscription id using this code:
amc = AuthorizationManagementClient(csc, subscription_id)
for resource_group in resources_groups:
denylocks = amc.deny_assignments.list_for_resource_group(resource_group)
try:
Here, it creates an error (denylocks); I am getting:
<azure.mgmt.authorization.v2018_07_01_preview.models._paged_models.DenyAssignmentPaged object>
When I loop over the list of that object, it gives the error
:ERROR 'ClientSecretCredential' object has no attribute
'signed_session'
for locks in denylocks:
print(locks)
except Exception as exc:
logger.error(exc)
'ClientSecretCredential' object has no attribute 'signed_session'
To resolve above error, according to documentation:
A client expecting an azure-common credential will raise an error like 'ClientSecretCredential' object has no attribute 'signed_session' when given an azure-identity credential.
So, try following code snippet according to documentation:
azure-common uses ServicePrincipalCredentials to authenticate a service principal:
from azure.common.credentials import ServicePrincipalCredentials
credential = ServicePrincipalCredentials(client_id, client_secret, tenant=tenant_id)
Alternatively, you can upgrade azure.mgmt.authorization to the latest version and continue using ClientSecretCredential of azure-identity.
It's because of the azure.mgmt.resource package, its latest version have some issue.
Try the following command:
pip install azure.mgmt.resource==21.2.1
Hello fellow User.
I'm trying to write to a Google sheets document via a Google service account. The account has writing permission the the document, so that's not the issue.
The reason I'm using a service account is to avoid having to constantly refresh access tokens. I think there lies the issue. Because this is the response from the API:
{
"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.",
"status": "UNAUTHENTICATED"
}
}
This occurs when I try sending a put request to the spreadsheet to edit data. I previously connected the service account to the sheets API, aquired the credentials from there and used them in the request.
If anyone knows, where the error might be, I'd be very thankful.
Here is the Python code that triggered the error:
iat = time.time()
exp = iat + 3600
payload = {'iss': <SERVICE ACCOUNT EMAIL>,
'sub': <SERVICE ACCOUNT EMAIL>,
'aud': f'https://sheets.googleapis.com/v4/spreadsheets/<SHEETID>/values/Sheet1!A2:B5',
'iat': iat,
'exp': exp}
additional_headers = {'kid': <PRIVATE KEY ID>}
signed_jwt = jwt.encode(payload, key=<PRIVATE KEY>,
headers=additional_headers, algorithm='RS256')
headers = {'authorization': f'Bearer {signed_jwt}'}
params = {'range': f'Sheet1!A2B5',
'majorDimension':'ROWS',
'values':[
<LISTS OF ENTRIES>
]}
spreadsheetId = <SHEETID>
resp = requests.put(url=f'https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/
values/Sheet1!A2:B5?valueInputOption=USER_ENTERED',
data = params, headers = headers)
For anyone interested, I was following these guides:
How to use service account for authentication: https://developers.google.com/identity/protocols/oauth2/service-account#python_1
How to issue correct put request: https://developers.google.com/sheets/api/samples/writing
How to get correct endpoint for jwt-encoded credentials: https://developers.google.com/sheets/api/reference/rest
Expected OAuth 2 access token, login cookie or other valid authentication credential.
The coded used for accessing APIs with a service account is not the same as the code used for Oauth2. The code you are using appears to be trying to authenticate using Oauth2.
You should be using something like this.
credentials = ServiceAccountCredentials.from_json_keyfile_name(
KEY_FILE_LOCATION, SCOPES)
service = build('calendar', 'v3', credentials=credentials)
Reference:
oauth2client.service_account module
I tried to use partnercenter api to get the billing details. But API call return 401 error code. the details provided on partnercpi are correct one and its working fine If I give it as input for Subscription API.
URL : https://api.partnercenter.microsoft.com/v1/customers/<Customer-tenant-ID>/subscriptions/<Subscription-ID>/usagerecords/resources
Can you suggest what can be the reason for the error.
Reference link : https://msftstack.wordpress.com/2016/01/05/azure-resource-manager-authentication-with-python/
Here is my python code.
import adal
import requests
application_secret = 'asdq23Y+tRgEspFxQDPasd'
application_id = '523129-1267b-123'
authentication_endpoint = 'https://login.microsoftonline.com/'
resource = 'https://management.core.windows.net/'
context = adal.AuthenticationContext(authentication_endpoint + tenant_id)
token_response = context.acquire_token_with_client_credentials(resource, application_id, application_secret)
access_token = token_response.get('accessToken')
endpoint = "https://api.partnercenter.microsoft.com/v1/customers/<customer tenant ID>/subscriptions/<sub-id>/usagerecords/resources"
headers = {"Authorization": 'Bearer ' + access_token}
json_output = requests.get(endpoint,headers=headers)
print json_output
Output Response:
<Response [401]>
Is this method not fit for partnerapi usage collection ?. If not pls suggest alternate option. Thanks in advance.
401 is because partner center does not work with just the token from Azure AD.
The actual Auth workflow
Get a Token from Azure AD.
Use that token to get an access token from PartnerCenter.
Use this token to communicate with the partner center REST APIs.
More Info Here