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:
Related
I am building a python flask API.
The requests are sent from the UI and they include an already authorized JWT token in the header (as expected bearer token).
My API service needs to validate the token and extract the tenant from the token.
I have a few questions about how a solution like that usually works.
does the API just need to decode the token and get the tenant from the payload?
the api cannot validate the signature of the token because I don't have the secret, right?
should the api juat call the auth. Server (in thia case key cloak)? If yes can someone please write an example code for that. Which libraries are good to use?
Thank you
Here are some answers.
From a pure technical point of view, you can indeed decode the JWT token (there exists plenty of libs to do it) to extract the payload claims, and you can do it "serverless"
The secret is used to CREATE the signature, not to verify it. When the signature is created (by the keycloak server) using a private key, the client app can verify it using the public key
Issuing an additional request to the KC server in order to decode the token has yet some added value. The (possibly long-living) token may, for some security reason, have been discarded to prevent if from being still used. In such case, the API will return a negative answer. The web service you need to invoke is the "Token Introspection Endpoint" (https://www.oauth.com/oauth2-servers/token-introspection-endpoint/)
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.
I am testing MSAL and ROPC flow. When I run sample https://github.com/Azure-Samples/ms-identity-python-desktop I get error:
python username_password_sample.py parameters.json
invalid_client
AADSTS7000218: The request body must contain the following parameter: 'client_assertion' or 'client_secret'.
I was having same problem while following MS documentation and used curl. Please check my other question where SO community helped me to solve problem. After adding application registration secret to curl request, I got valid token and I was able to fetch mails.
What is confusing me is fact that secret is not present in parameters.json file.
You missed the step No.6 from this link: https://github.com/Azure-Samples/ms-identity-python-desktop/tree/master/1-Call-MsGraph-WithUsernamePassword
If the application was set as Public Client, then the secret is not required.
For more details, you can read https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc#authorization-request for reference.
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 want to code that post facebook. So I decided to use python-sdk (https://github.com/pythonforfacebook/facebook-sdk).
Then I hit a problem.
graph = facebook.GraphAPI(oauth_access_token)
How can I get this "oauth_access_token"?
You need to use an authorization flow. Access tokens are the keys used after getting proper authorization.
An access token is an opaque string that identifies a user, app, or
page and can be used by the app to make graph API calls. Access tokens
are obtained via a number of methods, each of which are covered later
in this document. The token includes information about when the token
will expire and which app generated the token. Because of privacy
checks, the majority of API calls on Facebook need to include an
access token.
There are various ways to obtain an access token all explained in https://developers.facebook.com/docs/facebook-login/access-tokens/
For testing, one must create an app at https://developers.facebook.com/apps and can be issued an access token at https://developers.facebook.com/tools/access_token
Here is a way to get the user access token :
instance = UserSocialAuth.objects.get(user=request.user, provider='facebook')
token = instance.tokens
graph = facebook.GraphAPI(token['access_token'])
Maybe you've already figured this out, just in case somebody else is looking for it