I was following tutorial https://towardsdatascience.com/using-the-strava-api-and-pandas-to-explore-your-activity-data-d94901d9bfde and this github https://github.com/franchyze923/Code_From_Tutorials/blob/master/Strava_Api/strava_api.py (proposed in tutorial).
And cannot find solution to problem below, I found something about scope but do not know how to use it, thus I am here seeking help
{'message': 'Authorization Error',
'errors': [{'resource': 'AccessToken',
'field': 'activity:read_permission',
'code': 'missing'}]}
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
auth_url = "https://www.strava.com/oauth/token"
activites_url = "https://www.strava.com/api/v3/athlete/activities"
payload = {
'client_id': "XXXXXX",
'client_secret': 'XXXXXX',
'refresh_token': 'XXXXXXXXX',
'grant_type': "refresh_token",
'f': 'json'
}
print("Requesting Token...\n")
res = requests.post(auth_url, data=payload, verify=False)
access_token = res.json()['access_token']
print("Access Token = {}\n".format(access_token))
activities_url = f"https://www.strava.com/api/v3/athlete/activities?" \
f"access_token={access_token}"
print('RESTful API:', activities_url)
# Get the response in json format
response = requests.get(activities_url)
activity = response.json()
I tried to change payload and find another solution but results were always as above. I receive my access token though
Access Token = 61766e12XXXX062XXX2a2eXXXXXXXXXX
first of all, scope in strava api is something that represents what types of access are being granted to the app from a strava user account. it can be read user's public activity, read private activity, write etc.
in case of getting authenticated: strava uses oAuth2 and has a very detailed guideline to get started for the first time. You may check their official doc page: (https://developers.strava.com/docs/authentication/#oauthoverview).
the process is explained in very detailed and should be enough for your problem.
Related
The Task##
A django application that allows users to sign up and once the user clicks on the account activation link, Zoho CRM is receiving the data and a contact is created in the CRM section.
The Problem
I am currently working on an absolute masterpiece - the ZOHO API.
I am struggling to set up the native Python code that uses POST/GET requests.
Regarding the zcrmsdk 3.0.0, I have completely given up on this solution unless somebody can provide a fully functional example. The support simply blames my code.
The documentation I consulted:
https://www.zoho.com/crm/developer/docs/api/v2/access-refresh.html,
https://www.zoho.com/crm/developer/docs/api/v2/insert-records.html
Since the post request in postman API works fine I do not understand why it does not work in python code
My approach
Generate an self-client API code on: https://api-console.zoho.com/
Insert that code on Postman and retrieve the access or refresh token
Use this access token in an add_user_contact function that is defined in the documentation
It works! Response is success and it is in Zoho CRM
The permsissions scope I am using is: ZohoCRM.modules.contacts.ALL, ZohoCRM.users.ALL, ZohoCRM.modules.deals.ALL, ZohoCRM.modules.attachments.ALL, ZohoCRM.settings.ALL, AAAserver.profile.ALL
Picture of Post Man POST REQUEST
My own Code
def authenticate_crm():
"""
access to response object id:
response_object.get('data')[0].get('details').get('id')
"""
url = 'https://accounts.zoho.com/oauth/v2/token'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
# one time self-client token here -
request_body = {
"code": "1000.aa8abec144835ab79b8f9141fa1fb170.8ab194e4e668b8452847c7080c2dd479",
"redirect_uri": "http://example.com/yourcallback",
"client_id": "1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ",
"client_secret": "290e505ec52685fa62a640d874e6560f2fc8632e97",
" grant_type": "authorization_code"
}
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
print(response.json())
I am essentially struggling to convert the Postman API request to a Python request to get the token as part of the workflow. What am I doing wrong here?
The documentation states: Note: For security reasons, pass the below parameters in the body of your request as form-data. (access-refresh link) but passing it in postman as form-data breaks the call completely.
According to their own documentation (which is convoluted, contradictory and full of outdated screenshots) the authentication key is needed only once.
Once the request from above runs, I would take the response in the third image and use the refresh key to add the contact.
I am also open to a solution with the SDK 3.0.0, if anybody can help.
I solved it!
I have changed this line:
response = requests.post(url=url, headers=headers, data=json.dumps(request_body).encode('utf-8'))
to this and added some return statement:
payload = '1000.6d9411488dcac999f02304d1f7843ab2.e14190ee4bae175debf00d2f87143b19&' \
'redirect_uri=http%3A%2F%2Fexample.com%2Fyourcallback&' \
'client_id=1000.H95VDM1H9KCXIADGF05E0E1XSVZKFQ&' \
'client_secret=290e505ec52685fa62a640d874e6560f2fc8632e97&'\
'grant_type=authorization_code'
response = requests.request(method="POST", url=url, headers=headers, data=payload)
if response is not None:
print("HTTP Status Code : " + str(response.status_code))
# print(response.text)
print(response.json())
# catch access and refresh token
at = response.json().get('access_token')
rt = response.json().get('refresh_token')
return at, rt
I do not understand why that is different but that fixed it and I could retrieve keys from ZOHO.
I am trying to make a request to the Proactive Events API by using the requests module of Python.
However I always receive a response that the scope is invalid.
Can anyone help? What am I doing wrong? My code looks like this:
#ask.launch
def launch():
content_type = "application/x-www-form-urlencoded;charset=utf-8"
client_id = "amzn1.application-oa2-client.6a48XXXXXXX408"
client_secret = "592XXXXxxxxxxx6"
scope = "alexa::proactive_events"
grant_type = "client_credentials"
data = {"grant_type": grant_type, "client_id": client_id, "client_secret": client_secret, "scope": scope}
r = requests.post("https://api.amazon.com/auth/O2/token", data=data, headers={"content-type": content_type})
speech = render_template("welcome")
reprompt = render_template("welcome_reprompt")
return question(speech).reprompt(reprompt)
That is the response I get:
{'error_description': 'The request has an invalid parameter : scope', 'error': 'invalid_scope'}
Since one of the reason you get the invalid scope is that you dont have the events included in your skill manifest I include some steps here. I found quite cumbersome to use the SMAPI to update the skill manifest so instead I used ask cli.
install ask-cli: get authorization code for your amazon acount. In my case the backend is not an AWS lambda function but an external web server
get the skill manifest in json format:
ask api get-skill -s "amzn1.ask.skill.ZZZYYYZZ" --stage development > skill.json
Add the notifications permission and the events elements to the manifest:
{
"name": "alexa::devices:all:notifications:write"
}
and
"events": {
"publications": [
{
"eventName": "AMAZON.AAABBBCC"
}
],
"endpoint": {
"uri": "https://XXXYYYZZ:443/whatevercontext"
}
}
update the manifest:
ask api update-skill -s "amzn1.ask.skill.ZZZYYYZZ" --stage development -f skill.json
enable the notifications in the alexa app for your specific skill
Now you should be able to get the token and next step is to send the notification to the device
Have you tried making the API call via any other method? I just tried that with Postman and it worked for me.
My Python's a bit rusty, but here's the self generated code from Postman for Python. May be this should help?
import http.client
conn = http.client.HTTPConnection("api,amazon,com")
payload = "grant_type=client_credentials&client_id=amzn1.application-oa2-client.whatever-value&client_secret=client-secret&scope=alexa%3A%3Aproactive_events&undefined="
headers = {
'Content-Type': "application/x-www-form-urlencoded"
}
conn.request("POST", "auth,O2,token", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
As Karthik asked previously have you tried the call via postman? I first suggest trying to via postman before you trying to code it.
If the issue still persists its most likely because you haven't included the necessary permissions required for Proactive Events in your Skill Manifest.
To add the necessary permissions to Skill Manifest you need to use the Skill Management API & ASK Cli.
Follow this section of the documentation and visit the links referenced there to correctly add the required permissions to your skill - https://developer.amazon.com/docs/smapi/proactive-events-api.html#onboard-smapi
Once you have successfully added the events and publications with a skill schema you should be able to successfully generate a token.
Please feel to ask if you want me to elaborate more on the exact steps.
Cheers!
This is what I have tried and it worked:
amazon_token_url = "https://api.amazon.com/auth/O2/token"
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'}
body = "grant_type=client_credentials&client_id=amzn1.application-oa2-client.XXXYYYZZ&client_secret=ZZZYYYXXX&scope=alexa::proactive_events"
log.debug("Sending token request with body: %s", body)
resp = requests.post(amazon_token_url, data=body, headers=headers)
resp_json = json.loads(resp.content.decode('utf-8'))
if (resp.status_code < 299) and (resp.status_code > 199):
log.debug("token received from Amazon")
log.debug("Content : %s", resp.content)
token = resp_json["access_token"]
return token
I am trying to use the foursquare API for the first time and have not been able to get a 200 status code no matter what I tried. Using directly the code foursquare provides in its docs, I attempt to do a userless request, replacing my client ID and secret where necessary.
def places_search(term,street, zipcode):
params = dict(
client_id='MY_CLIENT_ID',
client_secret='MY_CLIENT_SECRET',
v='20181122',
near=street + 'New York, NY ' + zipcode,
query=term,
limit=1
)
url = "https://api.foursquare.com/v2/venues/explore"
resp = requests.get(url=url, params=params)
#grabbing the JSON result
data = json.loads(resp.text)
return data
print(places_search("starbucks","3rd avenue","10009"))
I get the following error code:
{'meta': {'code': 400, 'errorType': 'invalid_auth', 'errorDetail': 'Missing access credentials. See https://developer.foursquare.com/docs/api/configuration/authentication for details.', 'requestId': '5bf6cbb26a607137bc33b7f2'}, 'response': {}}
I find it odd given my request is userless and matches exactly the way they outline it in the docs... Would you have an idea what I am doing wrong?
Thanks,
As per the documentation:
To make a userless request, specify your consumer key’s Client ID and
Secret instead of an auth token in the request URL.
Like this:
https://api.foursquare.com/v2/venues/search?ll=40.7,-74&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&v=YYYYMMDD
Since you are passing the credentials as the request parameters, the server cannot authenticate you.
Goodmorning,
i have some trouble in wrinting a callback method that it's used to login to my web app (hosted in gae)
#app.route('/callback')
def callback_handling():
env = os.environ
code = request.args.get('code')
json_header={'Content-Type': 'application/x-www-form-urlencoded'}
token_url = "https://{domain}/oauth/token".format(domain='mydomain')
token_payload = {
'client_id': 'myid',
'client_secret': 'mysecret',
'redirect_uri': 'http://localhost:8080/callback',
'code': code,
'grant_type': 'authorization_code'
}
encoded = urllib.urlencode(token_payload)
user_url = "https://{domain}/userinfo?access_token={access_token}"\
.format(access_token=token_info['access_token'])
user_info = urlfetch.Fetch(user_url, method=urlfetch.GET, headers=json_header)
session['profile'] = user_info
return redirect('/dashboard')
i costantly get error 401 unathorized..from debug console any ideas to fix?..reading over the internet i understand that i must use urlfetch from gae because is the only lib allowed in gae (requests does not in localhost)..
In your code, is this : "https://{domain}/userinfo" your own endpoint or is this some third-party that you are trying to auth with?
Either way the 401 unauthorised seems legit, and being thrown by the endpoint, If "https://{domain}/userinfo" is pointing to your own endpoint then being able to see that logic would help, alternatively if it is a third-party I would recommend testing your request with something like postman, to see what your request looks like, headers etc. and make sure that it matches what the endpoint is expecting.
Hope this helps.
I'm trying to use Google OAuth2 to get user's contact info. I'm not struggling with getting accesses, I am wondering that for some reason I've stopped getting refresh_token instead I get id_token (long JWT string).
I use python urllib to retrieve access information for users. My code is:
scope = 'https://accounts.google.com/o/oauth2/token'
params = urllib.urlencode({
'code': request.GET['code'],
'redirect_uri': settings.SOCIAL_AUTH_GOOGLE_REDIRECT_URI,
'client_id': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY,
'client_secret': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET,
'grant_type': 'authorization_code',
})
Response:
{u'access_token': u'hash',
u'token_type': u'Bearer',
u'expires_in': 3600,
u'id_token': u'really long hash'}
I use contacts scope https://www.google.com/m8/feeds/contacts/default/full?alt=json
When I'm trying to add to params access_type : offline I get the error below:
Failed to retrive access_token. Status: 400
Message: {
"error" : "invalid_request",
"error_description" : "Parameter not allowed for this message type: access_type"
}
So after that I am wondering:
Can I use id_token refresh my access_token ?
If first is True: How ?
Are there any differences between types of users who are getting authenticated, because I noticed that sometimes you get refresh_token, but I need to get it permanently, next time I make a OAuth2 flow I get id_token
I'm sure I'm far too late to help here, but I ran into the same issue so hopefully this will help others.
Google ONLY provides the refresh_token on the first authorization. If the account has already allowed access, the refresh_token will not be provided again. Try revoking access to the app from your google account, then re-authorizing. You will then receive the refresh_token.
If you need a refresh token, you better add access_type=offline and approval_prompt=force onto https://accounts.google.com/o/oauth2/auth?
var url = 'https://accounts.google.com/o/oauth2/auth?' +
'client_id=' + CLIENT_ID + '&' +
'response_type=code&access_type=offline&approval_prompt=force&' +
'redirect_uri=' + encodeURIComponent(REDIRECT_URL) +
'&scope=' + SCOPES;
Then the returned code will always give you a refresh code in the next handshake with https://www.googleapis.com/oauth2/v4/token