How to access spotify's web api with client id and secret? - python

I'm trying to write a script that creates a playlist on my spotify account in python, from scratch and not using a module like spotipy.
My question is how do I authenticate with my client id and client secret key using the requests module or grab an access token using those credentials?

Try this full Client Credentials Authorization flow.
First step – get an authorization token with your credentials:
CLIENT_ID = " < your client id here... > "
CLIENT_SECRET = " < your client secret here... > "
grant_type = 'client_credentials'
body_params = {'grant_type' : grant_type}
url='https://accounts.spotify.com/api/token'
response = requests.post(url, data=body_params, auth = (CLIENT_ID, CLIENT_SECRET))
token_raw = json.loads(response.text)
token = token_raw["access_token"]
Second step – make a request to any of the playlists endpoint. Make sure to set a valid value for <spotify_user>.
headers = {"Authorization": "Bearer {}".format(token)}
r = requests.get(url="https://api.spotify.com/v1/users/<spotify_user>/playlists", headers=headers)
print(r.text)

As it is referenced here, you have to give the Bearer token to the Authorization header, and using requests it is done by declaring the "headers" optional:
r = requests.post(url="https://api.spotify.com/v1/users/{your-user}/playlists",
headers={"Authorization": <token>, ...})
The details of how can you get the Bearer token of your users can be found here

Related

Request API with Bearer token

I am trying to use the Malwarebytes API to get data. However, I am not getting the results for request. I get the "Unauthorized" message. My understanding of the documentation is to get the "access token" using my client ID and client secret. I was able to get the access token. However, I am not sure how to run the access token I received to the headers so I can get data. help is appreciated.
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
import requests
import json
CLIENT_ID = "Client id "
CLIENT_SECRET = "client secret"
grant_type = 'client_credentials'
body_params = {'grant_type' : grant_type}
url='https://api.malwarebytes.com/oneview/oauth2/token'
response = requests.post(url, data=body_params, auth = (CLIENT_ID, CLIENT_SECRET))
#Gets only access token
response_token = response.json()
response_token2 = json.dumps(response_token, indent=2)
token_response = response_token.get("access_token",[0])
##BEARER AUTHORIZATION
headers = {
'Authorization':'Bearer token_response',
'Content-Type':'application/x-www-form-urlencoded'
}
companies = requests.get('https://api.malwarebytes.com/oneview/v1/sites', headers=headers)
print(companies.text)
print(companies.status_code)
Issue with getting data after getting access token

Verify Client ID and Client Secret before using it in Application

We have a use case in which Admin can set Google Or Microsoft's Apps Client Id and Secrets that can later be used for all users who sign up with this Admin's link, Is there a way to verify these fields before saving/using them?
like for Microsoft,How do I verify this info that admin is providing? Is there any API call to verify it?
Update:
I am able to do this for G suite, what I did was:
1- Create a request to get token from client id and secret, (with wrong code).
2- In response, google returns 'invalid_client' in case the credentials are wrong and 'invalid_grant' in case the credentials are correct. (because Code is wrong too.)
try:
discovery_url = settings.GOOGLE_DISCOVERY_URL
callback_url = settings.BASE_URL + "/accounts/invite/google/signup/callback/"
client = WebApplicationClient(client_id)
identity_provider_config = requests.get(
discovery_url,
).json()
token_endpoint = identity_provider_config["token_endpoint"]
token_url, headers, body = client.prepare_token_request(
token_endpoint, redirect_url=callback_url, code='**code'**
)
token_response = requests.post(
token_url,
headers=headers,
data=body,
auth=(client_id, client_secret),
).json()
# Parse the tokens!
client.parse_request_body_response(json.dumps(token_response))
except Exception as error:
json_object = json.loads(error.json)
pairs = json_object.items()
if list(pairs)[0][1] == 'invalid_grant':
return "Your credentials are correct"
if list(pairs)[0][1] == 'invalid_client':
return "Your credentials are NOT correct"
FOR MICROSOFT:
For microsoft, additional tenant id is required in order to do this:
We did this in following way:
def validate_azure_credentials(client_id, client_secret, tenant_id):
"""
validate client id and secret from microsoft and google
"""
try:
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=f"https://login.microsoftonline.com/{tenant_id}",
)
# call for default scope in order to verify client id and secret.
scopes = ["https://vault.azure.net/.default"]
token = app.acquire_token_for_client(scopes=scopes)
if token.get("access_token") is None:
return IdpResponseMessages.INVALID_CREDENTIALS
return IdpResponseMessages.VALID_CREDENTIALS
except Exception as error:
logger.debug(f"Exception {error}")
return str(error)

Reddit API Authentication Issue (OAuth)

The following code throws a 401 error and the access_token does not get retrieved. It seems like https://www.reddit.com/api/v1/access_token is rejecting the username/password or clientID/Secretkey that I have provided. But all that info is correct, the username and password is absolutely same as the Reddit login details, and the client ID & Secret key are directly a copy-paste from a dev app created here: https://www.reddit.com/prefs/apps
Please suggest what could be wrong
import requests
auth = requests.auth.HTTPBasicAuth('<client_id>', '<client_secret>')
data = {'grant_type': 'password','username': 'username','password': 'password'}
headers = {'User-Agent': 'ApiTest/0.0.1'}
res = requests.post('https://www.reddit.com/api/v1/access_token',auth=auth, data=data, headers=headers)
if "Unauthorized" in res.text:
print('401 error occured')
TOKEN = res.json()['access_token']
headers = {**headers, **{'Authorization': f"bearer {TOKEN}"}}
requests.get('https://oauth.reddit.com/api/v1/me', headers=headers)
Try to change from bearer to Bearer in your headers. You can also remove the **.
Should be something like this:
headers = {'Authorization': f"Bearer {TOKEN}"}

The default appengine service account does not have a client_id. Why or?

I can use the default service account <appengine_app_id>#appspot.gserviceaccount.com to get an access_token and make a request.
The oauth provider of the receiving appenine app receives 'anonymous' for the get_client_id(SCOPE). I use this SCOPE = "https://www.googleapis.com/auth/userinfo.email"
Making the request:
access_token = app_identity.get_access_token(SCOPE)[0]
response = urlfetch.fetch(
"https://my-other.appspot.com/provider",
method=urlfetch.POST,
payload=...,
follow_redirects=False,
headers={"Content-Type": "application/json",
"Authorization": "Bearer " + access_token})
Handle the request:
class ProviderHandler(webapp2.RequestHandler):
def post(self):
logging.info('app_id=' + self.request.headers['X-Appengine-Inbound-Appid'])
token_audience = oauth.get_client_id(SCOPE) # anonymous ??
When I create a new service account, furnish a new private key and use:
credentials = ServiceAccountCredentials.from_json_keyfile_name(<json_file_name>, SCOPE)
acees_token = credentials.get_access_token().access_token
it works fine.

"Error parsing JSON" when using Spotify API

I am learning Python and I am trying to create a playlist using the Spotify web api but get a http 400 error: Error parsing json. I guess it has to do with an incorrect variable type in the token but I am having a really hard time debugging it as I can't figure out a way to see the post request in raw format.
Posting through the API requires authorizing and this is the script I've created for that:
import requests
import base64
requests.packages.urllib3.disable_warnings()
client_id = 'ID'
client_secret = 'SECRET'
redirect_uri = 'http://spotify.com/'
scope = 'playlist-modify-private playlist-read-private'
def request_token():
# 1. Your application requests authorization
auth_url = 'https://accounts.spotify.com/authorize'
payload = {'client_id': client_id, 'response_type':'code','redirect_uri':redirect_uri}
auth = requests.get(auth_url,params = payload)
print '\nPlease go to this url to authorize ', auth.url
# 2. The user is asked to authorize access within the scopes
# 3. The user is redirected back to your specified URI
resp_url = raw_input('\nThen please copy-paste the url you where redirected to: ')
resp_code= resp_url.split("?code=")[1].split("&")[0]
# 4. Your application requests refresh and access tokens
token_url = 'https://accounts.spotify.com/api/token'
payload = {'redirect_uri': redirect_uri,'code': resp_code, 'grant_type': 'authorization_code','scope':scope}
auth_header = base64.b64encode(client_id + ':' + client_secret)
headers = {'Authorization': 'Basic %s' % auth_header}
req = requests.post(token_url, data=payload, headers=headers, verify=True)
response = req.json()
return response
This is the function actually trying to create the playlist using the authorization token (import authorizer is the function above):
import requests
import authorizer
def create_playlist(username, list_name):
token = authorizer.request_token()
access_token = token['access_token']
auth_header = {'Authorization': 'Bearer {token}'.format(token=access_token), 'Content-Type': 'application/json'}
api_url = 'https://api.spotify.com/v1/users/%s/playlists' % username
payload = {'name': list_name, 'public': 'false'}
r = requests.post(api_url, params=payload, headers=auth_header)
But whatever I try it only leads to a 400 error. Can anyone please point out my error here?
Solved by adding a json.dumps for the input: json.dumps(payload) and changing the payload to be 'data' and not 'params' in the request.
So the new functioning request equals:
r = requests.post(api_url, data=json.dumps(payload), headers=auth_header)

Categories

Resources