Spotipy. Can`t pass the second part of oAuth (Python) - python

I want to create an app which will add some sorts of songs to the Spotify playlist. So it`s might be a good idea to use Spotipy (Python Library) to solve it.
To add song to the playlist I need to know its URI. To know its URI I should use method called search (https://spotipy.readthedocs.io/en/2.19.0/#spotipy.client.Spotify.search). It requires some inputs and one of them is Authorization, which requires access token (link for docs https://developer.spotify.com/documentation/web-api/reference/#category-search). Then I used Authorization Guide from Spotify to authorize(link for AuthGuide https://developer.spotify.com/documentation/general/guides/authorization-guide/#authorization-code-flow) and I stacked.
The first step is pretty easy:
self.query = {
'client_id': client_id,
'response_type': 'code',
'redirect_uri': 'andriime.github.com/pc/'
}
self.info_code = requests.get(url=SPOTIFY_URL, params=self.query)
self.authorization_code = self.info_code.text
But second step is really scary. I search for its solution over whole Internet and there isnt any one normal guide HOW to pass it. But this is the best I`ve found:
Spotify API {'error': 'invalid_client'} Authorization Code Flow [400]
Please, if you know how to deal with it or there is an answer, which I missed just write here!
EDIT
If I print self.info_code response code is 200. client_id and client_secret are environmental variables and I defined them above (I didn`t post this code). My step-2-code looks like this:
self.authorization_code = self.info_code.text
code_payload = {
'grant_type': 'authorization_code',
'code': self.authorization_code,
'redirect_uri': redirect_uri,
}
auth_str = '{}:{}'.format(client_id, client_secret)
b64_auth_str = base64.urlsafe_b64encode(auth_str.encode()).decode()
print(b64_auth_str)
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic {}'.format(b64_auth_str)
}
post_request = requests.post(url=API_URL, data=code_payload, headers=headers)
print(post_request.text)
The response text is {"error":"invalid_grant","error_description":"Invalid authorization code"}. There is an answer on StackOverflow, but it doesn`t work for me (How to fix 'error: invalid_grant Invalid authorization code' when asking for reshresh_token from Spotify API?), because I didnt make that mistake which is written about there.
Also there is an answer on Spotify community forum, but there is no answer there. There is one question on another forum,but it`s non-answered too
Links:
1.https://community.spotify.com/t5/Spotify-for-Developers/Unable-to-get-access-token-using-authorization-code-flow/m-p/5098258
2.https://developer.salesforce.com/forums/?id=906F00000009B2AIAU)
So again ask you to answer if you know how it should work. Many thanks!

Okay, I find out how to do it. This video really helped me (https://www.youtube.com/watch?v=yAXoOolPvjU), however it`s about javascript, but the consept is the same.
After the first step (after getting self.info_code response) you should check some things:
Is your redirect uri is the same as in DashBoard and was it written there in right format (https://example.com/callback/), where I made a mistake - I had 'redirect_uri parametr in self.query as 'andriime.github.com/pc/' not 'https://andriime.github.io/pc/' (its also important to remember that there isn`t any github.com, only github.io, so right link correctly right into DashBoard)
2."response_type" in your params (requests input) should equal to 'code'
After this, you should get a link of your request (I didn`t find how to do it beatifully, so just wrote this:
print(f'{SPOTIFY_URL}?client_id={client_id}&client_secret={client_secret}&response_type={self.query["response_type"]}&redirect_uri={"https://andriime.github.io/pc/"}')
where SPOTIFY_URL equals to "https://accounts.spotify.com/authorize"
then you just copy and paste link into the browser and click some "accept" buttons. After this, you`ll be redirected to the page you pasted as 'redirect_uri' and then you should click on the link in browser and you should see "code" param there after your "redirect_uri".
I know, that this part is a bit complecated, but you should watch the video I linked above, it would be useful and easier to understand
Then you can just copy the second part of my code and use it. But, of course, change the params.
code_payload = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': redirect_uri,
}
auth_str = '{}:{}'.format(client_id, client_secret)
b64_auth_str = base64.urlsafe_b64encode(auth_str.encode()).decode()
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic {}'.format(b64_auth_str)
}
new_response = requests.post(url=API_URL, headers=headers, params=code_payload)
print(new_response.text)
This answer also can be much impoved, so I really want to see your feedbacks
or another answers here to make this method easier and more beatiful

Related

Code does not post all output using jira-python in Jira

So I’m having some difficulty with my code. The code works but for some reason it only post one string instead of having all the strings posted in Jira. for example, up to the point that you see the #print(username, response), in the terminal I see all responses being printed in on screen. So it works great up to that point but the moment I send the same variable such as response through the Jira Dictionary called issue_dict, it creates the Jira but with only one of the responses and not all. I’ve tried doing something like response[x] but it just gives me an error that string indices must be integers. I’m not quite sure what else to do to be able to iterate through this so I can post all the results in the Description/body of a Jira ticket.
Ideally I would love to have both the user and the response in the description part. I’ve tried to do this with a List but I seem to get the same results where only one string gets printed. Anyone have done anything similar to post results in Jira?
Here is the code:
import jira from JIRA
for i in range(1,3):
user = os.getenv(‘USER’ + str(i))
pass = os.getenv(‘PASS’+ str(i))
headers = {
'X-Requested-With': 'Curl',
}
response =requests post('https://API-Address', headers=headers, auth=(USER,PASS))
root = ET.fromString(response.text) # Parses the JSON into text
for x in root.iter(’text’): #all this is doing is iterating through the file root and finding the text and saving the substring in response.
response = x[2].text
#print(username, response)
issue_dict = {
'project': {'id': 123},
'summary’:’My Jira Using Py',
'description': response, #This is the current issue!
'issuetype': {'name': 'Bug'},
}
new_issue = jira.create_issue(fields=issue_dict)

authlib.integrations.base_client.errors.MismatchingStateError

Trying to get a token for tradestation with flask_client.
baseurl='https://sim-api.tradestation.com/v2'
oauth.register(
name='tradestation',
client_id=api_key,
client_secret=api_secret,
access_token_url=baseurl+'/security/authorize',
access_token_params={ 'grant_type': 'authorization_code' },
authorize_url=baseurl+'/authorize',
authorize_params=None,
api_base_url=baseurl,
client_kwargs={
'scope': 'marketdata', # ,trade — for later
'response_type': 'code',
'token_endpoint_auth_method': 'client_secret_post',
},
)
#app.route('/authorize')
def authorize():
print(flask.request.args.get('state'), flask.session.get('_tradestation_authlib_state_'))
token = oauth.tradestation.authorize_access_token()
Login part works fine, I'm being redirected to the tradestation login page, after entering credentials I'm being redirected to localhost. In the flask output I see:
GET /authorize?code=<long_code> HTTP/1.1
And it returns this exception for authorize_access_token(). Debug print indeed says that the state is None. By looking into the code I see that it wants to get state from the url, and it's missing:
None c3GjcENWIe7Qg3FdQNYn1iSCuU1jZC
Am I registering the parameters wrongly here? Haven't yet got to the token_endpoint_auth_method, and I cannot find anything wrong with the other parameters.
Doing it the hackish way got me the token in the end:)
state=flask.session.get('_tradestation_authlib_state_')
flask.request.args=ImmutableMultiDict({**flask.request.args, 'state': state})
So someone suffering from the same check can use this quick and dirty approach to have it running, still maybe authlib developers may show up with some better solution.

Python request.post Missing Required Param

I've been looking around and trying to get a post request to work, but I haven't found any luck. I keep getting a MISSING_REQUIRED_PARAM each time the request is being made. My following code is shown below.
def create_sign_group(group_name, header, url):
temp_header = header
temp_header['Content-Type'] = 'application/json'
temp_header['Accept'] = 'application/json'
data = {
"GroupCreationInfo": {
"groupName": group_name
}
}
res = requests.post(url + 'groups', headers=temp_header, data=json.dumps(data))
if res.status_code == 200:
print('{} Group Created...'.format(group_name))
else:
print(res.status_code)
print(res.headers)
print(res.text)
exit(res.status_code)
I've tried using json instead of data, but still getting the same error. Using a the REST API client I was able to successfully make the call. The rest client is shown below:
If anyone can point shine some knowledge and point me in the right direction I would greatly appreciate it. Take care.
You should assign headers=temp_header not headers=header. MISSING_REQUIRED_PARAM is often griping about the content type header, which, as you can see IS being included in your screenshot test.
So I figured it out, I guess I was passing the wrong payload into the data param. I changed the code to:
data = {
"groupName": group_name
}
It looks like I didn't need the "GroupCreationInfo" parameter.

Graph API authenticate as a user programmatically

I'm trying to get a specific user OAuth2 bearer token using HTTP POST request, and nothing seems to work.
login_url = 'https://login.microsoftonline.com/'
authorize_endpoint = '{0}{1}{2}'.format(login_url,config.tenant_id,'/oauth2/authorize')
bodyvals = {'client_id': config.client_id,
'client_secret': config.client_secret,
'grant_type': 'client_credentials',
'resource':config.resource_endpoint}
return requests.post(authorize_endpoint, data=bodyvals)
The above code works, but generates a token on behalf of the application.
I can't seem to find a way to pass in the users credentials, and no documentation on this whatsoever.
Generally I don't care if the answer is in Python or Powershell or just a general explanation, I just don't seem to understand how to properly do that with AAD.
You can do it manually, see my other answer here: https://stackoverflow.com/a/40844983/1658906.
You must use grant_type=password and call the oauth2/token endpoint. Here is the C# version for authenticating:
private async Task<string> GetAccessToken()
{
string tokenEndpointUri = Authority + "oauth2/token";
var content = new FormUrlEncodedContent(new []
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", Username),
new KeyValuePair<string, string>("password", Password),
new KeyValuePair<string, string>("client_id", ClientId),
new KeyValuePair<string, string>("client_secret", ClientSecret),
new KeyValuePair<string, string>("resource", PowerBiResourceUri)
}
);
using (var client = new HttpClient())
{
HttpResponseMessage res = await client.PostAsync(tokenEndpointUri, content);
string json = await res.Content.ReadAsStringAsync();
AzureAdTokenResponse tokenRes = JsonConvert.DeserializeObject<AzureAdTokenResponse>(json);
return tokenRes.AccessToken;
}
}
In the request you must specify:
Username
Password
Client ID
Client secret
The resource URI
For GraphAPI, resource is "https://graph.windows.net/"
If you don't want to use ADAL, you might however take a look at the code for usage of "resource". This scenario is covered, so consider ADAL as a big sample :)
Also, msrestazure has a UserPassCredentials instance that works too on GraphAPI.

Instagram API - Unable to generate proper access token (Python)

I am getting a JSON return like this:
{'data': [],
'meta': {'code': 200},
'pagination': {'deprecation_warning': 'next_max_id and min_id are deprecated for this endpoint; use min_tag_id and max_tag_id instead'}}
I am doing the following (where I'm omitting my personal info for the sake of this post):
CONFIG = {
'client_id': '',
'client_secret': '',
'redirect_uri': 'http://localhost:8515/oauth_callback'
}
api = InstagramAPI(**CONFIG)
Then I follow this link (inserting my info):
https://instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
and I get an access token that allows me to do some things like the following:
api = InstagramAPI(access_token = access_token)
recent_media, next = api.user_recent_media()
but when I try to search for "nhl", for example:
url = requests.get('https://api.instagram.com/v1/tags/nhl/media/recent?access_token='+access_token)
url.json()
I get the error result seen at the top of this post.
On the other hand, using the apigee console to access the instagram API, I get a different access token (by allowing access to my instagram account) that gives the JSON response I'm looking for:
{"pagination":{"next_max_tag_id":"AQD9K8O5THfHA7yp1waOwivzT ...etc
including the data I want:
"data":[{"attribution":null,"tags":["nhl","zachayfucale","nhlpa"
...etc
My question is: how can I generate the access token that apigee was able to get?
I have also been able to acquire an access token a different way and I can include this method too if anyone asks, however it does not help solve my problem.

Categories

Resources