gae appengine + auth0 localhost - python

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.

Related

Strava getting data from api

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.

Zoho CRM API: Python request-based POST or GET authentication + insertion of contacts

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.

Accomplishing Oauth2.0 authorization with refresh token through Python (Google API service creation)

I'm trying to access Google API services through a headless Linux server using Oauth2. I read through all the answers on this post: How do I authorise an app (web or installed) without user intervention? but none of them showed how to use the refresh token to generate an access token in python. pinnoyyid had a javascript example (https://stackoverflow.com/a/19766913/15713034) that went something like this:
function get_access_token_using_saved_refresh_token() {
// from the oauth playgroundfunction get_access_token_using_saved_refresh_token() {
// from the oauth playground
const refresh_token = "1/0PvMAoF9GaJFqbNsLZQg-f9NXEljQclmRP4Gwfdo_0";
// from the API console
const client_id = "559798723558-amtjh114mvtpiqis80lkl3kdo4gfm5k.apps.googleusercontent.com";
// from the API console
const client_secret = "WnGC6KJ91H40mg6H9r1eF9L";
// from https://developers.google.com/identity/protocols/OAuth2WebServer#offline
const refresh_url = "https://www.googleapis.com/oauth2/v4/token";
let refresh_request = {
body:`grant_type=refresh_token&client_id=${encodeURIComponent(client_id)}&client_secret=${encodeURIComponent(client_secret)}& refresh_token=${encodeURIComponent(refresh_token)}`;,
method: "POST",
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded'
})
}
JavaScript isn't really my best language, but I could decipher they were sending a POST request to the google server. So I tried to recreate the request in Python with the requests package:
import requests
result = requests.post("https://www.googleapis.com/oauth2/v4/token", body={'grant_type':'refresh-token', 'client_id':client_id, 'client_secret':client_secret, 'refresh_token': refresh_token}, headers={'Content-Type': 'application/x-www-form-urlencoded'})
And when I look at result it shows it has a 200 status code (success) but when I try to examine the response, there's nothing easy to read and I can't parse the result in JSON to get the access token. The other approach I tried was to spin up a Flask server using Google's suggested code: https://developers.google.com/identity/protocols/oauth2/web-server#python_5 but that doesn't work either because when I try to return the credentials from one of the functions (object that contains the access code) that won't return JSON no matter what. I'd prefer the post request method since it is cleaner and uses less code. Thanks!
In Python, one approach is to use requests-oauthlib to perform the Backend Application Flow. This is useful when you don't have a front-end to redirect someone to, in order to approve fetching a token.
This website (https://community.atlassian.com/t5/Bitbucket-questions/Refresh-Tokens-using-Python-requests/qaq-p/1213162) says solution could be something like this:
import requests
auth = ("<consumer_id>", "<consumer_secret>")
params = {
"grant_type":"refresh_token",
"refresh_token":"<your_refresh_token_here>"
}
url = "https://www.googleapis.com/oauth2/v4/token"
ret = requests.post(url, auth=auth, data=params) #note data=params, not params=params
Since none of the solutions above worked, I had to finally just give up and use a service account.

google oauth2 id_token vs refresh_token

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

Making an authenticated request to the Github API in GAE using Python + urlfetch

How do you make an authenticated request to the Github API once you've got the access token in GAE using Python and urlfetch?
Here is my code so far:
# Make an authenticated GET request to the Github API
url = 'https://api.github.com/user'
fields = {
"access_token" : access_token,
}
data = urllib.urlencode(fields)
result = urlfetch.fetch(
url=url,
payload=data,
method=urlfetch.GET,
)
And the error I get is:
{"message":"Requires authentication","documentation_url":"http://developer.github.com/v3"}
What am I doing wrong, and how can I fix this so it makes a correct authenticated request?
The solution to this one was pretty simply, although it took me quite a while to get to it.
Here is the code to make an authenticated request to the Github on Google App Engine using Python/Urlfetch:
# Make an authenticated request
url = 'https://api.github.com/user?access_token=' + str(access_token)
result = urlfetch.fetch(
url=url,
method=urlfetch.GET,
)

Categories