I'm creating an application in Azure AD as a daemon to get user phone
authentication methods using the python msal library and calling the following following endpoint GET https://graph.microsoft.com/beta/users/{id | UPN}/authentication/phoneMethods but i get the following error
{
"error": {
"code": "accessDenied",
"message": "Request Authorization failed",
"innerError": {
"message": "Request Authorization failed",
"date": "2020-11-19T19:26:28",
"request-id": "11975e07-ee6b-4bd2-9a74-7c175c5da560",
"client-request-id": "11975e07-ee6b-4bd2-9a74-7c175c5da560"
}
}
}
My app has the required application permissions to get the info i'm looking for, which are UserAuthenticationMethod.Read.All and UserAuthenticationMethod.ReadWrite.All and it already works with different end points such as GET https://graph.microsoft.com/beta/users/{id | UPN}, this is the code i'm using in order to get the access token required and call the graph api
import json
import logging
import requests
import msal
config = {
"authority": "https://login.microsoftonline.com/TENANT_NAME",
"client_id": "APP_ID",
"scope": ["https://graph.microsoft.com/.default"],
"secret": "APP_SECRET",
"endpoint": "https://graph.microsoft.com/beta/users/{USER_ID}/authentication/phoneMethods"
}
app = msal.ConfidentialClientApplication(
config["client_id"], authority=config["authority"],
client_credential=config["secret"],
)
result = 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:
graph_data = requests.get(
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"))
i tried to do the same thing using curl or postman and i get the exact same error, so i'm guessing it's an access token issue maybe ?
Thanks in advance
The api call does not support application permissions. You need to grant delegated permissions to the application, and then use the auth code flow to obtain the token.
Related
I'm trying to communicate with rancher API, tried different combinations, getting the same result every time:Unauthorized 401: must authenticate
steps to reproduce:
1)Create Rancher API key and secret
2)Create a simple script that uses them to deploy a test workload.
import requests
api_url = "https://myrancherurl.com/v3/project/c-m-qh7tkqn4/jobs"
access_key = "token-zmdpqs"
secret_key = "fr9v6z9xxfqdgmjv2k9z44zvx6mlrandomtoke"
token=access_key+":"+secret_key
# Set the API token
headers = { "Authorization": "Bearer "+token }
# Set the payload for the API request
payload = {
"name": "my-job",
"jobConfig": {
"image": "nginx:latest",
"command": ["nginx", "-g", "daemon off;"],
"restartPolicy": {
"name": "Never"
}
}
}
# Send the API request to create the job
response = requests.post(api_url, json=payload, headers=headers)
# Print the API response
print(response.json())
I'm not 100% sure what exaclty is "Project id", so I tried different combinations, results are the same. I have the impression, that additional config has to be done on rancher side, but can't find any info.
Any ideas?
I've tried also using the official python library, but it seems outdated(and also returns the same erro)
Every object in the Rancher API has an id. Project is a like a group used to organize various namespaces, and workloads.
There are three types of clients that are used to interact with the Rancher API.
Management (Used to interact with general objects not tied to any cluster/project)
Cluster (Used to interact with objects that are tied to a specific cluster)
Project (Used to interact with objects that are tied to a specific project)
Sample code:
pip install git+https://github.com/rancher/client-python.git#master
import rancher
rancher_url = 'https://rancher.example.com/v3'
rancher_token = 'token-abcde:abcdefghijklmnopqrstuvwxyz0123456789'
rancher_verify_ssl_certs = True
management_client = rancher.Client(
url=rancher_url,
token=rancher_token,
verify=rancher_verify_ssl_certs
)
clusters_info = management_client.list_cluster(name='leo-downstream')
my_cluster = clusters_info.data[0]
projects_info = management_client.list_project(name='Default')
default_project = projects_info.data[0]
default_project_url = default_project.links['self'] + '/schemas'
default_project_client = rancher.Client(url=default_project_url, token=rancher_token, verify=False)
containers = [
{
'name': 'one',
'image': 'nginx',
}
]
default_project_client.create_workload(
name='test-workload-creation',
namespaceId='default',
scale=1,
containers=containers
)
I'm implementing (in Python with the Microsoft Graph API) the creation of Azure AD application based on the AWS template. I'm stuck when implementing the automatic role provisioning like describe in this documentation : https://learn.microsoft.com/fr-fr/graph/application-provisioning-configure-api?tabs=http#step-3-authorize-access
When I call the servicePrincipals/{id}/synchronization/secrets API for the first time just after the creation of the synchronization job, I receive a HTTP error (400 - Bad Request) with the following body :
{
"error": {
"code": "BadRequest",
"message": "The credentials could not be saved. This is due to an internal storage issue in the Microsoft Azure AD service. For information on how to address this issue, please refer to https://go.microsoft.com/fwlink/?linkid=867915",
"innerError": {
"code": "CredentialStorageBadRequest",
"details": [],
"message": "The credentials could not be saved. This is due to an internal storage issue in the Microsoft Azure AD service. For information on how to address this issue, please refer to https://go.microsoft.com/fwlink/?linkid=867915",
"target": null,
"innerError": {
"code": "CredentialStorageBadRequest",
"details": [],
"message": "Message:The credentials could not be saved. This is due to an internal storage issue in the Microsoft Azure AD service. For information on how to address this issue, please refer to https://go.microsoft.com/fwlink/?linkid=867915",
"target": null
},
"date": "2021-01-05T15:53:59",
"request-id": "---",
"client-request-id": "---"
}
}
}
When a do a second same call (with MS Graph Explorer, Postman or directly in Python), it works, the second call returns an HTTP 204 like expected ! So I think my request is correct.
This is my implementation (which works because I retry the call a second time…) :
# Default value :
GRAPH_API_URL = "https://graph.microsoft.com/beta/{endpoint}"
class Azure:
# […]
# self._http_headers contains my token to access to MS Graph API
# self._aws_key_id and self._aws_access_key contains AWS credentials
def _save_sync_job_auth(self, principal_id):
self._put(
f"servicePrincipals/{principal_id}/synchronization/secrets",
{"value": [
{"key": "ClientSecret", "value": self._aws_key_id},
{"key": "SecretToken", "value": self._aws_access_key},
]},
retry=1 # If I put 0 here, my script fail
)
# […]
def _put(self, endpoint, json, retry=0):
return self._http_request(requests.put, endpoint, retry, json=json)
# […]
def _http_request(self, func, endpoint, retry=0, **kwargs):
url = GRAPH_API_URL.format(endpoint=endpoint)
response = func(url, headers=self._http_headers, **kwargs)
try:
response.raise_for_status()
except requests.HTTPError as e:
if retry:
logging.warning(f"Error when calling {func.__name__.upper()} {url}")
return self._http_request(func, endpoint, retry - 1, **kwargs)
else:
raise e
return response
Am I missing something ? Have you a solution to remove this "retry hack" ?
I'm trying to make a data partition refresh (post) following this azure documentation : https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-async-refresh
Either with post or get I got 401 Unauthorized (Even when the service is Off !).
I got the token from azure AD (ServicePrincipalCredential).
I added the AD as Analysis Services Admins (https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-server-admins)
I gave the owner role to AD in Analysis Services IAM.
it worked with Analysis Services management rest api (https://learn.microsoft.com/en-us/rest/api/analysisservices/operations/list) With the same authentification (got code response 200)
My python code :
from azure.common.credentials import ServicePrincipalCredentials
import requests
credentials = ServicePrincipalCredentials(client_id="ad_client_id",
secret="ad_secret",
tenant="ad_tenant")
token = credentials.token
url = "https://westeurope.asazure.windows.net/servers/{my_server}/models/{my_model}/refreshes"
test_refresh = {
"Type": "Full",
"CommitMode": "transactional",
"MaxParallelism": 1,
"RetryCount": 1,
"Objects": [
{
"table": "my_table",
"partition": "my_partition"
}
]
}
header={'Content-Type':'application/json', 'Authorization': "Bearer {}".format(token['access_token'])}
r = requests.post(url=url, headers=header, data=test_refresh)
import json
print(json.dumps(r.json(), indent=" "))
Response I got :
{
"code": "Unauthorized",
"subCode": 0,
"message": "Authentication failed.",
"timeStamp": "2019-05-22T13:39:03.0322998Z",
"httpStatusCode": 401,
"details": [
{
"code": "RootActivityId",
"message": "aab22348-9ba7-42c9-a317-fbc231832f75"
}
]
}
I'm hopeless, could you please give me somes help to make this clear ?
Finally I resolved the issue.
I had wrong token. The api expect an OAuth2.0 authentification token (The Azure analysis services rest api documentation ins't very clear about the way to get one)
For thoses will encounter the same issu there is the way to get one.
from adal import AuthenticationContext
authority = "https://login.windows.net/{AD_tenant_ID}"
auth_context = AuthenticationContext(authority)
oauth_token = auth_context.acquire_token_with_client_credentials(resource="https://westeurope.asazure.windows.net", client_id=AD_client_id, client_secret=AD_client_id)
token = oauth_token['accessToken']
Documentation about this :
https://learn.microsoft.com/en-us/python/api/adal/adal.authentication_context.authenticationcontext?view=azure-python#acquire-token-with-client-credentials-resource--client-id--client-secret-
https://github.com/AzureAD/azure-activedirectory-library-for-python/wiki/ADAL-basics
Most likely your token is not right.
Have you tried validating your token? Use something like http://calebb.net/
I see some examples of ServicePrincipalCredentials that stipulate the context or resource like this:
credentials = ServicePrincipalCredentials(
tenant=options['tenant_id'],
client_id=options['script_service_principal_client_id'],
secret=options['script_service_principal_secret'],
resource='https://graph.windows.net'
Good samples here:
https://www.programcreek.com/python/example/103446/azure.common.credentials.ServicePrincipalCredentials
I think the solution is try a couple more things that make sense and follow the error details.
You need token which has resource (audience) set to https://*.asazure.windows.net
For token validation I like https://jwt.io
Also if you want to automate this properly you have two options
Either by Logic Apps
or with Azure Data Factory
Both of which I have very detailed posts on if you want to check them out
https://marczak.io/posts/2019/06/logic-apps-refresh-analysis-services/
https://marczak.io/posts/2019/06/logic-app-vs-data-factory-for-aas-refresh/
I am trying to programmatically create and manage facebook advertising campaigns.
The following is my python code:
my_app_id = 'MyAppId'
my_app_secret = 'MyAppSecret'
my_access_token = 'MyAccessToken'
FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token)
me = AdUser(fbid='MyFbId')
my_accounts = list(me.get_ad_accounts())
print(my_accounts)
Sadly, when I run this function I get an error from the following line:
my_accounts = list(me.get_ad_accounts())
The error is:
facebookads.exceptions.FacebookRequestError:
Message: Call was not successful
Method: GET
Path: https://graph.facebook.com/v2.8/643866195/adaccounts
Params: {'summary': 'true'}
Status: 400
Response:
{
"error": {
"message": "(#3) Application does not have the capability to make this API call.",
"code": 3,
"type": "OAuthException",
"fbtrace_id": "H3BFNpSClup"
}
}
I have tried messing with a few things to resolve this. One thing I thought would work was to add my account ID to the Authorized Ad Account Ids in the Facebook Develop App settings page but that didn't help.
Thanks.
I have a permissions request that looks like this:
timestamp, signature = genPermissionsAuthHeader.getAuthHeader(str(self.username), str(self.password), str(access_token), str(token_secret), "POST", "https://api-3t.sandbox.paypal.com/nvp") # https://svcs.sandbox.paypal.com/Permissions/GetBasicPersonalData
log.info(timestamp)
log.info(signature)
authorization_header = "timestamp=" + timestamp + ",token=" + access_token + ",signature=" + signature
log.info(authorization_header)
headers = {
"X-PAYPAL-AUTHORIZATION": authorization_header,
}
url = "https://api-3t.sandbox.paypal.com/nvp"
nvp_params = {
"METHOD": "TransactionSearch",
"STARTDATE": "2012-01-01T05:38:48Z",
}
r = requests.post(url, data=nvp_params, headers=headers)
log.info(r.text)
self.response.content_disposition = "text/html"
self.response.write(r.text)
I have an access token and token secret from the permissions API using my PayPal credentials on developer.paypal.com under "Sandbox Accounts"
When I run this method I get the error message:
TIMESTAMP=2014%2d04%2d21T22%3a50%3a18Z&CORRELATIONID=c8f9212035b60
&ACK=Failure&VERSION=0%2e000000&BUILD=10277387&L_ERRORCODE0=10002
&L_SHORTMESSAGE0=Authentication%2f
Authorization%20Faile
d&L_LONGMESSAGE0=You%20do%20not%20have%20permissions%20to%20make%20this%20API%20call
&L_SEVERITYCODE0=ErrorNone
I can make a call to GetBasicPersonalDetails and it seems to work. Any help would be great, thanks!
I found the answer, I was missing the "SUBJECT" parameter on the parameter string being sent for the payment. So just in case anyone else runs across this in the future the full code after getting the permissions tokens to run a test payment for the sandbox is:
def test_sales(self, access_token=None, token_secret=None):
timestamp, signature = genPermissionsAuthHeader.getAuthHeader(str(self.username), str(self.password), str(access_token), str(token_secret), "POST", "https://api-3t.sandbox.paypal.com/nvp") # https://svcs.sandbox.paypal.com/Permissions/GetBasicPersonalData
log.info(timestamp)
log.info(signature)
authorization_header = "timestamp=" + timestamp + ",token=" + access_token + ",signature=" + signature
log.info(authorization_header)
headers = {
"X-PAYPAL-AUTHORIZATION": authorization_header,
}
url = "https://api-3t.sandbox.paypal.com/nvp"
nvp_params = {
"METHOD": "DoDirectPayment",
"PAYMENTACTION": "Sale",
"AMT": "22.00",
"ACCT": "4111111111111111",
"CVV2": "111",
"FIRSTNAME": "Jane",
"LASTNAME": "Smith",
"EXPDATE": "012018",
"IPADDRESS": "127.0.0.1",
"STREET": "123 Street Way",
"CITY": "Englewood",
"STATE": "CO",
"ZIP": "80112",
"VERSION": "86",
"SIGNATURE": self.signature,
"USER": self.username,
"PWD": self.password,
"SUBJECT": "person_who_you_acting_on_behalf_of#domain.com"
}
r = requests.post(url, data=nvp_params, headers=headers)
log.info("Search transaction\n\n" + r.text + "\n\n")
self.response.content_disposition = "text/html"
self.response.write(urllib.unquote(r.text).decode('utf8'))
And for generating the header I used: https://github.com/paypal/python-signature-generator-for-authentication-header
Hope this helps someone, thanks!
Here is some information on the error message you are getting. One reason is invalid API Credentials. Another possibility is you are trying to pass an expired token. Once a transaction is created on PayPal the token is no longer valid. Instead you have a transaction id created.
Below is some more information on PayPal API Error Messages.
PayPal API Error Messages
If you are attempting a transaction search for your most recent transactions in PayPal, then you can use the PaymentDetailsRequest API
Here is an integration guide from the PayPal Developer Site:
Get Payment Details PayPal API Codes
TransactionSearch is not part of the AdaptivePayments API,
so no "X-PAYPAL-AUTHORIZATION" is required with this method.
Assuming that you got the permission for TransactionSearch method on the target account (see https://developer.paypal.com/docs/classic/permissions-service/gs_PermissionsService/)
the following code will works:
import requests
api_username="username"
api_password="password"
api_signature="signature"
target_account_email="xxx.yyy-buyer#zzz.com" #customers email
data_req = {
'METHOD':'TransactionSearch',
'SUBJECT':, target_account_email,
'VERSION':'86.0',
'STARTDATE':'2009-10-11T00:00:00Z',
'USER':api_username,
'PWD':api_password,
'SIGNATURE':api_signature
}
response=requests.post(url_en_point,data=data_req,timeout=3).text
print response