I only want to pull data from a list called dataacq within a group (or site?) called prod within the domain (or root site?) tenant.sharepoint.com (or tenant-my.sharepoint.com ?) and put it into a DataFrame.
I have an issue with the token gotten through app.acquire_token_silent.
Microsoft documentation is not comprehensible because it's too heavy and has little workable cookbooks/working examples (as can be seen by my numerous question marks). Also it seems they want to centralize all their APIs into graph.microsoft.com, yet there is no warning that tenant.sharepoint.com/sites/prod/_api/ is going to be discontinued.
I have gotten the following permissions from the azure portal for my app.
I don't believe I need all of them, but I am not sure. I just want to read a list. So is only Microsoft Graph > Sites.read.All necessary? Or is it Sharepoint > Allsites.Read ?
I know I both have an "app only" permission and a "signed in user" permission.
I did download the "quickstart" examples and I did read https://msal-python.readthedocs.io/en/latest/ . Although a token was successfully pulled using app.acquire_token_silent, using the returned token always throws some error whatever scope ('https://microsoft.sharepoint-df.com/.default' or 'https://graph.microsoft.com/.default') or API domain (graph.microsoft.com or tenant.sharepoint.com) I am using into a request:
{'error_description':
"Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
{'error': {'code': 'AccessDenied',
'message': 'Either scp or roles claim need to be present in the token.',
'innerError': {'date': '2021-02-19T08:05:16',
'request-id': '01efc071-18e6-4006-8780-f771419ebe3e',
'client-request-id': '01efc071-18e6-4006-8780-f771419ebe3e'}}}
On the other hand, there is an API developer testing portal. When I am copying the token given in this portal into my python code, both scope/API domains work.
This is e.g. an example that works with copying & pasting the token from the portal, but not working with the token issued by the app.acquire_token_silent method:
r = requests.get( # Use token to call downstream service
fr'https://graph.microsoft.com/v1.0/sites/root:/sites/prod:/lists/{list_id}/items?expand=fields(select=Created))',
headers={'Authorization': 'Bearer ' + result['access_token'],},)
So the issue is with this app.acquire_token_silent method or the configuration file. But the returned response seems alright:
{'token_type': 'Bearer',
'expires_in': 3599,
'ext_expires_in': 3599,
'access_token': '...'}
What am I missing?
According to the code r = requests.get..... you provided in your description, it seems you use the microsoft graph api to implement it. If you use this api, you should use https://graph.microsoft.com/.default as scope to get the access token. And you can copy the access token to this page, decode the token and check if the permissions are included in it.
And according to the screenshot of "API permissions" tab of your registered app, please also do grant admin consent operation for the permission Sites.Read.All although it shows not required admin consent.
================================Update===============================
It seems the method acquire_token_silent() acquire the access token by client credential flow. So we should add the "Application" type permission but not "Delegated" permission in registered app.
Related
According to the documentation, I can either send the request with authorization (token) in order to get all of my gists, or anonymously and I will get public popular gists.
My Python code is:
url = "https://api.github.com/gists"
with Get(
url,
headers={"Accept": accept},
params={"since": since, "per_page": per_page, "page": page},
auth=("token", token)
) as response:
return response
When token is set to None, I get all public gists (not mine) and when token is set to my OAuth token, I get all of my gists.
However, the issue is that it only gives me my non-secret gists instead of secret and public together.
Initially I was thinking that my token was wrong and therefore I was not getting the secret gists, but turns out that the token is correct (for sure, I can even post new gists) and also has permissions to read/write gists, and that is why it is weird.
The issue is also not related to either params or headers, tested.
Additional Information:
Get is a class which implements a context-manager and sends a get request [link].
After a long research I found out that GitHub's OAuth token from Developer Settings is not enough to perform this action and I need to create a GitHub App in order to extend GitHub.
I used this tool:
https://github.com/defunkt/gist
in order to ask GitHub for such a particular token (which is being used in the GitHub App), and then I started using it, and it worked!
With the new fine grained personal access tokens this can now be done without a GitHub App:
You need to give read-write access to Gists under Account Permissions:
I just want to make a hello world post on LinkedIn.
One method is to use selenium, but i would rather use the API if possible.
Another method is to use the API which is well explained here:
https://www.jcchouinard.com/how-to-post-on-linkedin-api-with-python/
I execute the code, and get an access token from the website.
I then use the access token to get the user info.
From this i can make the post.
However, the issue that i have is that the access token can expire:
{
'serviceErrorCode': 65600,
'message': 'Invalid access token',
'status': 401
}
There is a way to get the new token manually here:
https://pypi.org/project/python3-linkedin/
with this instruction When you grant access to the application, you will be redirected to the return url with the following query strings appended to your RETURN_URL: "http://localhost:8000/?code=#############################################&state=########################"
My question is this: Is there a way to get a refreshed access token without having to do this manually ?
(In particular the LinkedIn site indicates that the token is valid for 2 months)
Hello I am using the Twitter API via Tweepy on Python, since it is a read function, I don't understand why I get the following message:
[{'message': 'Application cannot perform write actions. Contact Twitter Platform Operations through https://help.twitter.com/forms/platform.', 'code': 261}]
When I checked my developer portal I found the following message:
This App has violated Twitter Rules and policies. As a result, certain functions will be limited. An email has been sent to ******#gmail.com with details. For assistance, submit a support ticket.
Which is funny since I have only used the API with my own credentials/user for:
public_tweets = api.user_timeline()
lookup_users = api.lookup_users(user_ids=[user_id])
Additional info:
I gave read, write, post permissions to my app
Why cannot I perform writing actions if this is a read function?
Is there any way I can manage this issue with my app? Twitter is not responding to my appeal
This error code seems to indicate an issue with the app permissions, unspecific to the endpoint:
Code 261 - App cannot perform write actions.
The App that you are using with the API does not have the proper permission level set for its access token and access token secret. Please navigate to the 'Keys and tokens' tab on the Twitter Apps dashboard and check the permission levels assigned to your access token and access token secret. If it is set to anything other than 'Read, write and Direct Messages,' then you are going to have to adjust the settings under the 'Permission' tab and regenerate your access token and access token secret to apply the new settings.
https://developer.twitter.com/en/support/twitter-api/error-troubleshooting
Beyond submitting a support ticket and waiting for a response, I don't think there's much else you can do in terms of the restriction itself.
I am evaluating different options for authentication in a python App Engine flex environment, for apps that run within a G Suite domain.
I am trying to put together the OpenID Connect "Server flow" instructions here with how google-auth-library-python implements the general OAuth2 instructions here.
I kind of follow things up until 4. Exchange code for access token and ID token, which looks like flow.fetch_token, except it says "response to this request contains the following fields in a JSON array," and it includes not just the access token but the id token and other things. I did see this patch to the library. Does that mean I could use some flow.fetch_token to create an IDTokenCredentials (how?) and then use this to build an OpenID Connect API client (and where is that API documented)? And what about validating the id token, is there a separate python library to help with that or is that part of the API library?
It is all very confusing. A great deal would be cleared up with some actual "soup to nuts" example code but I haven't found anything anywhere on the internet, which makes me think (a) perhaps this is not a viable way to do authentication, or (b) it is so recent the python libraries have not caught up? I would however much rather do authentication on the server than in the client with Google Sign-In.
Any suggestions or links to code are much appreciated.
It seems Google's python library contains a module for id token validation. This can be found at google.oauth2.id_token module. Once validated, it will return the decoded token which you can use to obtain user information.
from google.oauth2 import id_token
from google.auth.transport import requests
request = requests.Request()
id_info = id_token.verify_oauth2_token(
token, request, 'my-client-id.example.com')
if id_info['iss'] != 'https://accounts.google.com':
raise ValueError('Wrong issuer.')
userid = id_info['sub']
Once you obtain user information, you should follow authentication process as described in Authenticate the user section.
OK, I think I found my answer in the source code now.
google.oauth2.credentials.Credentials exposes id_token:
Depending on the authorization server and the scopes requested, this may be populated when credentials are obtained and updated when refresh is called. This token is a JWT. It can be verified and decoded [as #kavindu-dodanduwa pointed out] using google.oauth2.id_token.verify_oauth2_token.
And several layers down the call stack we can see fetch_token does some minimal validation of the response JSON (checking that an access token was returned, etc.) but basically passes through whatever it gets from the token endpoint, including (i.e. if an OpenID Connect scope is included) the id token as a JWT.
EDIT:
And the final piece of the puzzle is the translation of tokens from the (generic) OAuthSession to (Google-specific) credentials in google_auth_oauthlib.helpers, where the id_token is grabbed, if it exists.
Note that the generic oauthlib library does seem to implement OpenID Connect now, but looks to be very recent and in process (July 2018). Google doesn't seem to use any of this at the moment (this threw me off a bit).
I'm trying to build a (what I thought would be) a simple script in Python to download Microsoft's Azure's rate card using the Billing API.
token_response = adal.acquire_token_with_client_credentials(
'https://login.microsoftonline.com/' + TENANT_ID,
CLIENT-ID,
CLIENT-KEY)
access_token = token_response.get('accessToken')
endpoint = "https://management.azure.com/subscriptions/[SUBSCRIPTION-ID]/providers/Microsoft.Commerce/RateCard?api-version=2015-06-01-preview&$filter=OfferDurableId eq 'MS-AZR-0003P' and Currency eq 'GBP' and Locale eq 'en-GB' and RegionInfo eq 'GB'"
headers = {"Authorization": 'Bearer ' + access_token}
out = requests.get(endpoint,headers=headers)
json_output = out.json()
print son_output
The query seems to be executing correctly. Authorisation seems to go ok, and I'm getting a 200 OK message response. But the output is empty: {u'value': []}. I've tried different OfferIDs, different $filter strings and now it's driving me mad...
I wonder if perhaps I haven't delegated suitable permissions, but I've created an Application attached to Active Directory, generated a key, and delegated permissions to Windows Azure Service Management? And if that was the problem, wouldn't I receive an error?
Happy to hear alternative ways of doing the same thing, but Python is all I really know...
Please make sure that the user account you're using to interact with the billing and usage API has access to the Azure Subscription. In your case, you're using a Service Principal so please make sure that this user is assigned a role in the Subscription.
To assign a Service Principal a role, you may find this link helpful: https://azure.microsoft.com/en-in/documentation/articles/resource-group-create-service-principal-portal/.
When it comes to assigning role, since this user only needs to read the data, its better to go with Reader role so that inadvertent changes can't be made to your Azure Subscription.