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.
Related
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
Receiving the following error response when doing a basic Graph API POST using REQUESTS in Python:
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"request-id": "36c01b2f-5c5c-438a-bd10-b3ebbc1a17c9",
"date": "2019-04-05T22:39:37"
}
}
}
Here is my token request and Graph request using REQUESTS in Python:
redirect_uri = "https://smartusys.sharepoint.com"
client_id = 'd259015e-****-4e99-****-aaad67057124'
client_secret = '********'
tennant_id = '15792366-ddf0-****-97cb-****'
scope = 'https://graph.microsoft.com/.default'
####GET A TOKEN
payload = "client_id="+client_id+"&scope="+scope+"&client_secret="+client_secret+"&grant_type=client_credentials"
headers = {'content-type':'application/x-www-form-urlencoded'}
tokenResponse = requests.post('https://login.microsoftonline.com/'+tennant_id+'/oauth2/v2.0/token',headers=headers, data=payload)
json_tokenObject = json.loads(tokenResponse.text)
authToken = json_tokenObject['access_token']
#### Make a call to the graph API
graphResponse = requests.get('https://graph.microsoft.com/v1.0/me/',headers={'Authorization':'Bearer '+authToken})
if tokenResponse.status_code != 200:
print('Error code: ' +graphResponse.status_code)
print(graphResponse.text)
exit()
print('Request successfull: Response: ')
print(graphResponse.text)
print('Press any key to continue...')
x=input()
According to the documentation ( https://learn.microsoft.com/en-us/graph/api/resources/users?view=graph-rest-1.0 ) for this /me call, I need just one of the following permissions:
User.ReadBasic.All
User.Read
User.ReadWrite
User.Read.All
User.ReadWrite.All
Directory.Read.All
Directory.ReadWrite.All
Directory.AccessAsUser.All
and I have all of these on both application and delegated permissions in the azure application manager.
What am I doing wrong here? I feel like it's something small but I just can't figure this out.
I decoded my token using: http://calebb.net/ and I do not see a spot for "AUD" or "role" or "scope" so maybe that is where I am doing it wrong?
I looked everywhere and can't find a resolution, any help would be VERY much appreciated.
Thank you.
This sounds like you forgot to "Grant Permissions" to your application.
See this answer.
I finally figured this out, it had to do with Admin rights that needed to be granted by the Admin for our Office 365.
it was as simple as giving my Office admin the following link and having him approve it:
https://login.microsoftonline.com/{TENNANT ID HERE}/adminconsent?client_id={CLIENT ID HERE}
Instantly worked.
i am trying to create bill for payment and send to my customer via telegram bot:
i am using blockchain API V2-https://blockchain.info/api/api receive .my code is:
xpub='***'
keyk='02e57f1***'
url='https://api.blockchain.info/v2/receive?xpub='+str(xpub)+'&callback=https%3A%2F%2Fdoors03.ru&key='+keyk
x=requests.get(url)
r=x.json()
r=r['address']
r -is an adress wich was made.
i am sending it to my costumer(by the way is there any way to send adress with exact sum for pay ) . After i want to check is payment was recieved:
data={ "Content-Type": "text/plain","key":keyk,"addr":r,"callback":"https%3A%2F%2Fdoors03.ru","onNotification":"KEEP", "op":"RECEIVE"}
r = requests.post(url, data=data)
and this is the response - u'{\n "message" : "Internal handlers error"\n}'
what i am doing wrong ? how to check payments ? how to send address with exact sum of btc or ethereum ?
Sorry, i don't have enough reputation to post a comment, so this is
the only option i have. #egorkh have you solved this problem? Maybe
you have received explanation from blockchain.info support? I have
sent them a question about that, but they are answering for too long.
UPDATE: Finally, i have found solution.
In my case, reason of "Internal handlers error" message is in a wrong interpretation of their API.
As they haven't implemented balance_update request in their java-api, i did it on my own and i did it in wrong way.
I have put this parameters:
{"key":keyk,"addr":r,"callback":"https%3A%2F%2Fdoors03.ru","onNotification":"KEEP", "op":"RECEIVE"}
as post parameters, like in other methods they have provided in api. In those methods parameters are URLEncoded like you did with callback link. But...
In this HTML request they must be sent as plain text in json format without any special encoding, like that:
Map<String, String> params = new HashMap<String, String>();
params.put("addr", address);
params.put("callback", callbackUrl);
params.put("key", apiCode);
params.put("onNotification", keepOnNotification? "KEEP" : "DELETE");
params.put("confs", Integer.toString(confirmationCount));
params.put("op", StringUtils.isBlank(operationType) ? "ALL" : operationType);
//parse parameters map to json string(that's optional: you can write it directly as string)
String body = new Gson().toJson(params);
if (requestMethod.equals("POST")) {
byte[] postBytes = body.getBytes("UTF-8");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "text/plain");
conn.setRequestProperty("Content-Length", String.valueOf(postBytes.length));
conn.getOutputStream().write(postBytes);
conn.getOutputStream().close();
}
The main reason of your error may be that you put "Content-Type": "text/plain" in data object (, and maybe encoded callback url) .
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.
I have server-side code that calls the Google geocoding API, like this:
http://maps.google.com/maps/geo?q=40.714224,-73.961452&output=json&sensor=false&key=API_KEY
where API_KEY is my API key. I get a JSON reply, as expected, but the reponse is always 602 (Unknown Address). Is my URL wrong? (I've also tried the URL in the Google docs, but that returns a status: 'REQUEST_DENIED'.
What else could be wrong?
Update:
Well, it seems to actually be a mistake in my implementation, not the URL. This was how I did it:
api_params = {
'q': '40.714224,-73.961452',
'sensor': 'false',
'key': KEY,
'output': 'json'
}
# make the api call
http_response = urllib.urlopen('http://maps.google.com/maps/geo',
urllib.urlencode(api_params))
r = json.load(http_response)
but changing it to:
api_params = {
#'q': str(lat) + ',' + str(lng),
'q': '40.714224,-73.961452',
'sensor': 'false',
'key': KEY,
'output': 'json'
}
# make the api call
http_response = urllib.urlopen('http://maps.google.com/maps/geo?q='+api_params['q']+'&output=json&sensor=false&key='+api_params['key'])
r = json.load(http_response)
print r
fixes the problem. So my new question is, what's wrong with the first one?
The first one executes POST request, the second - GET request.
You may also want to use the urllib.urlencode function for concatenation.
But the easiest way is to use geopy.
Try using a HTTP watcher to make sure that this is the actual URL that is being sent within your application. There could be a chance that it isn't being encoded correctly or maybe is being incorrectly assembled. Since you aren't getting request denied and we were able to get a good response when we viewed it directly it seems that could be the best place to start. Hope that helps!