I would like to make a HTTP call to this resource :
https://bigquery.googleapis.com/bigquery/v2/projects/{projectId}/jobs
As I read to the documentation I use an API key generated from my GCP project to be authenticated. So with requests I make a simple call like this:
import requests
params = {'key': 'MY_API_KEY'}
base_url = 'https://bigquery.googleapis.com'
project_id = 'MY_PROJECT_ID'
r = requests.get(f'{base_url}/bigquery/v2/projects/{project_id}/jobs', params=params)
Unfortunately it returns a response 401 and I can't figure out why.
Thanks a lot and have a nice day !
Update code after guillaume blaquiere reply :
from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import service_account
base_url = 'https://bigquery.googleapis.com'
project_id = 'project_id'
credentials = service_account.Credentials.from_service_account_file(
'service_account.json',
scopes=['https://www.googleapis.com/auth/bigquery',
'https://www.googleapis.com/auth/cloud-platform'],
)
authed_session = AuthorizedSession(credentials)
response = authed_session.request('GET', f'{base_url}/bigquery/v2/projects/{project_id}/jobs')
print(response.json())
# this returns : {'etag': 'tAZvk1k2f2GY8yHaQF7how==', 'kind': 'bigquery#jobList'}
The API Key no longer works for a large number of Google API. Only some legacy continue to accept an API key.
Now, you need an authenticated request. You can find exemple in the google-auth python library documentation. Look at Refresh and Authorized_session.
Don't hesitate to comment if you need help about the credential obtention, I can also help you on this.
EDIT
When you perform the request, it's, by default, only on the current user. In your case, it's the service account when you use the Python code, and your User account when you use the API Explorer (the swagger like in the Google Documentation).
In your case, I guess that your service account has never performed a job (query or load job) and thus, there is no entry for it.
According with the documentation, is you want to see all the user jobs, you have to add the param ?allUsers=true at the end of your URL
response = authed_session.request('GET', f'{base_url}/bigquery/v2/projects/{project_id}/jobs?allUsers=true')
Related
I am migrating my code from ADAL to msal library. I have done all the necessary changes .
Trying to get access token by using the following code:
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:
result = app.acquire_token_for_client(scopes=config["scope"])
#With this code i am getting the (access token) but when using
headers = self.get_headers()
request = requests.get(url=folder_path, headers=headers, data={})
getting request response [401enter code here].
I cannot access any resource in the _api/web/lists/... api. SharePoint is a bit odd having multiple APIs to get data (Graph endpoint and _api endpoint), but before I dive into an MSAL conversion I wanted to know whether it actually supports access tokens to this SharePoint _api. I have tried without success. I cannot find anything in the Microsoft documentation about the supported APIs so I was hoping for some guidance. Note our application is currently working with ADAL. Thanks!
I'm trying to implement a simple python client for Spotify api. According to the Spotify's Authorization Guide, the app can be authorized in two ways:
App Authorization: Spotify authorizes your app to access the Spotify Platform (APIs, SDKs and Widgets).
User Authorization: Spotify, as well as the user, grant your app permission to access and/or modify the user’s own data. For information about User Authentication, see User Authentication with OAuth 2.0. Calls to the Spotify Web API require authorization by your application user. To get that authorization, your application generates a call to the Spotify Accounts Service /authorize endpoint, passing along a list of the scopes for which access permission is sought.
CLIENT CREDENTIALS
My first attempt used the app authorization using the oauth2 module from Spotipy, because it requires no token passed, but only client id and client secret, which belong to the app developer.
client.py
import spotipy
from spotipy.oauth2 import SpotifyClientCredentials
class SpotifyWrapper(spotipy.Spotify):
def category_playlists(self, category, limit=50, offset=0):
return self._get('browse/categories/%s/playlists' % category,
limit=limit,
offset=offset)
def get_api_client():
# create a client authentication request
client_cred = SpotifyClientCredentials(
client_id=DevelopmentConfig.SPOTIFY_CLIENT_ID,
client_secret=DevelopmentConfig.SPOTIFY_CLIENT_SECRET
)
# create a spotify client with a bearer token,
# dynamically re-created if necessary
return SpotifyWrapper(auth=client_cred.get_access_token())
Then I would import and declare it here:
spotify_utilities.py
from app.resources.spotify.client import get_api_client
sp = get_api_client()
And in order to make requests and get user playlists, pass it like so:
def get_user_playlist(username, sp):
ids=[]
playlists = sp.user_playlists(username)
for playlist in playlists['items']:
ids.append(playlist['id'])
print("Name: {}, Number of songs: {}, Playlist ID: {} ".
format(playlist['name'].encode('utf8'),
playlist['tracks']['total'],
playlist['id']))
return ids
This works and will get user content, where the user is the app developer.
IMPLICIT FLOW
Now I want to move on to Implicit Flow, whereby the app asks ANY user who uses for access and scopes, and for that a token will be required.
Once I fetch the token using Javascript, I know I can use it to get user data hitting the API with simple requests:
GET_USER_PROFILE_ENDPOINT = 'https://api.spotify.com/v1/users/{user_id}'
GET_USER_PLAYLISTS_ENDPOINT = 'https://api.spotify.com/v1/users/{user_id}/playlists'
def get_user_profile(token, user_id):
url = GET_USER_PROFILE_ENDPOINT.format(id=user_id)
resp = requests.get(url, headers={"Authorization": "Bearer {}".format(token)})
print (len(resp.json()))
return resp.json()
def get_user_playlists(token, user_id):
url = GET_USER_PLAYLISTS_ENDPOINT..format(id=user_id)
resp = requests.get(url, headers={"Authorization": "Bearer {}".format(token)})
print (len(resp.json()))
return resp.json()
but in order to get (and change) user data first I need to use this token to fetch user ID.
Also, by the following example form Spotipy docs, user must provide his username at terminal:
if __name__ == '__main__':
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print("Whoops, need your username!")
print("usage: python user_playlists.py [username]")
sys.exit()
token = util.prompt_for_user_token(username)
if token:
sp = spotipy.Spotify(auth=token)
playlists = sp.user_playlists(username)
After reading the docs from Spotify and Spotify, some things that are still not clear:
Is it possible to get this USER ID from passing the token only?
Must the app user necessarily provide his Spotify username via a form in a browser, besides authorizing the app when authentication is prompted?
Is it possible to tweak the wrapper above and implement a client which contemplates the parameters required for implicit flow? Would simply spotify = spotipy.Spotify(auth=token) work and get current usr data?
Also, by the following example form Spotipy docs, user must provide
his username at terminal:
That's because Spotipy caches tokens on disk. When no cache path is specified by the user the username simply gets appended to the files file extension as seen here. So the username specified is never being transmitted to any Spotify API endpoint.
1) Is it possible to get this USER ID from passing the token only?
Yes, using /v1/me instead of /v1/users/{user_id} will do exactly that assuming you are using an access token generated by Authorization Code flow or Implicit Grant flow.
2) Must the app user necessarily provide his Spotify username via a
form in a browser, besides authorizing the app when authentication is
prompted?
No, as seen in the first paragraph of my answer.
3) Is it possible to tweak the wrapper above and implement a client
which contemplates the parameters required for implicit flow? Would
simply spotify = spotipy.Spotify(auth=token) work and get current usr
data?
Spotipy seems to only use Authorization Code Flow right now. Due to you said you are
trying to implement a simple python client for Spotify api.
you should just implement Implicit Grant flow in your application. This has examples for all three Spotify authorization flows.
Hi I want to use the google api service to create service accounts.
Here is my current code:
base_url = f"https://iam.googleapis.com/v1/projects/{project}/serviceAccounts"
auth = f"?access_token={access_token}"
data = {"accountId": name,
"serviceAccount": {
"displayName": name
}}
Create a service Account
r = requests.post(base_url + auth, json=data)
try:
r.raise_for_status()
except requests.HTTPError:
if r.status_code != 409:
raise
This works, but it uses the requests package.
I want to use googleapiclient
from googleapiclient.discovery import build
credentials = GoogleCredentials.get_application_default()
api = build(service, version, credentials=credentials)
Then, where do I find information on how to use this api object?
I've tried:
api.projects().serviceAccounts.create(name=name).execute()
But this does not work, and I don't know how to find what arguments are expected or required.
You can find the GCP IAM API documentation here.
The arguments required and values are documented there.
For anyone else who is struggling.
Check out api explorer to get the format of the request.
For example, If the endpoint is iam.projects.serviceAccounts.get
and you need to provide name = "projects/project/serviceAccounts/sa#gsc.googleserviceaccounts.com"
Then your call will look like:
from googleapiclient.discovery import build
credentials = GoogleCredentials.get_application_default()
api = build(service, version, credentials=credentials)
sa = api.projects().serviceAccounts().get(name="projects/project/serviceAccounts/sa#gsc.googleserviceaccounts.com")
Hope this helps someone.
This is what I have so far. No real success. Trying to retrieve a token, but nothing seems to work. Just returns a giant mess of characters.
import requests
import json
auth_url = "http://learn.ZZZZZZZ.com/oauth2/authorize"
#credential
auth_client_id = "BBBBBBBBBBBBBBBBBBBBBBBB"
auth_client_secret = "YYYYYYYYYYYYYYYYYYYYY"
payload={'grant_type':'client_credentials', 'client_id':auth_client_id,'client_secret':auth_client_secret}
headers={'Accept':'application/json', 'Content-Type':'application/x-www-form-urlencoded'}
response = requests.post(auth_url,headers=headers,data=payload)
response.text
Use the token endpoint to obtain an access token.
auth_url = "http://learn.ZZZZZZZ.com/oauth2/token"
Docebo API documentation
We're using Rauth to connect to various OAuth 1 APIs. It works fine for a single request, but trying to do 2 or more requests against the given session results in 401 not authorized errors from the APIs.
Twitter API example:
import requests
from rauth import OAuth1Service
from rauth import OAuth1Session
consumer_key = {the consumer key}
consumer_secret = {the consumer secret}
access_token = {the access token}
access_token_secret = {the access token secret}
oauth_service = OAuth1Service(consumer_key = consumer_key,
consumer_secret = consumer_secret)
oauth_session = oauth_service.get_session(token = (access_token, access_secret))
url = 'https://api.twitter.com/1.1/statuses/home_timeline.json'
params = {'include_rts': 'true'}
r = oauth_session.get(url, params=params) # THIS WORKS
r = oauth_session.get(url, params=params) # THIS RETURNS 401 ERROR
This happens on both Twitter and LinkedIn APIs. How do we execute multiple requests against a single OAuth1Session object?
VERSIONS:
rauth==0.5.4
requests==1.1.0
UPDATE:
Strangely, if the params argument is not included then multiple requests can be made- but once params are included, even if it is an empty dict, we get 401s.
Example 1:
r = oauth_session.get(url) # THIS WORKS
r = oauth_session.get(url) # THIS WORKS
Example 2:
r = oauth_session.get(url, params={}) # THIS WORKS
r = oauth_session.get(url, params={}) # THIS RETURNS 401 ERROR
Carrying over from the comments, using session.get(..., header_auth=True) should do the trick. It's hard to say exactly why it doesn't work without this, but for the record, header-based authentication is preferred by the spec and given Twitter's position, I wouldn't be surprised if they also prefer it as a provider.
A quick search reveals dozens upon dozens of reports of their API failing where it ostensibly should work and one remedy is to prefer header authentication. From what I can tell, rauth is signing appropriately, so perhaps this is something to do with the way the provider is showing preference and handling non-header authenticated requests.
Update
It looks like either rauth or Requests was not properly handling params. It's odd because the signature base string and oauth_signature seemed to be correct, in that they were appropriately different on each respective request and the data they operated on seemed to checkout. So it seems like it should have validated the request.
At any rate, to correct this, we need to deepcopy elements of the request parameters that are mutable types, e.g. dictionaries. I've got a patch that should correct this, so you should be able to use this without header_auth. However, header authentication is the preferred method so I would still recommend it.