google oauth2 id_token vs refresh_token - python

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

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.

How to debug error 403 on Rest API with valid token with Python Requests package

I'm new to using APIs and I'm trying to access an Adobe Rest API using the Requests package.
I have managed to get a token but I get a 403 error (logged out) with any request I attempt.
I have performed the OAuth Authentication successfully and, Using a Legacy Application Flow (required by Adobe), I've fetched a token that grants me read and write access. I've tried a few get requests get the 403, session expired error.
I've looked up online and tried to clear my cookies before generating a new token, with the same results. However the token generated works fine with Postman and I can do get requests from there, so it doesn't seem to have anything to do with authentification/credentials/session.
Adobe helpdesk have no clue as to why this is happening either!
Here is the token I get back after identification:
{'access_token': 'some-encoded-string',
'expires_at': 1552652569.358807,
'expires_in': 3599,
'refresh_token': 'some-encoded-string',
'scope': ['read', 'write'],
'token_type': 'bearer'}
Here is the request and error:
r = requests.get('https://url-endpoint')
r : <Response [403]>
r.json()
{'code': 'ACCESS_DENIED',
'message': 'Your session has expired. Please proceed to the login page'}
I'm at a loss as to why this isn't working or even where to start!
#Devesh Kumar Singh yes that's the right idea, I forgot one step - in the end I used
client = OAuth2Session(client_id, token=token)
and from there
r = client.get('https://url-endpoint', params=params) works perfectly.

Refreshing google access tokens with the refresh tokens

How can I refresh the access tokens in google with the refresh token in python ? I have the refresh token, client id and client secret with me
I have tried with the following code for generating the access token (after expiry)
params = {
"grant_type": "refresh_token",
"client_id": client_id,
"client_secret": client_secret,
"refresh_token": refresh_token
}
authorization_url = "https://www.googleapis.com/oauth2/v4/token"
r = requests.post(authorization_url, data=params)
print(r.text)
if r.ok:
return r.json()['access_token']
else:
return None
I got an error in response like this:
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
But I need to generate the access token.
These are the three top reasons for it not to be working. I am not a Python dev so cant test your code sorry.
Send parms as a string
Check your parms make sure they are sent as a single string separated with &.
Post https://accounts.google.com/o/oauth2/token
client_id={ClientId}&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token
content type header
Also i think you need to set the content type header to something like application/x-www-form-urlencoded.
Change endpoint
If that doesnt work
Also try using https://accounts.google.com/o/oauth2/token instead of https://www.googleapis.com/oauth2/v4/token I remember there being some issue with one or the other of them sometimes

gae appengine + auth0 localhost

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.

Django OAuth Toolkit invalid_grant error

I have a bit of a problem, I have a django application that is using Django OAuth Toolkit and I can't get the access token from the server when using Authorization Code flow. Implicit flow works fine. I haven't find anything regarding my problem on stack so I'm really sorry if this is a duplicate of another question.
I can authorize with this url and get the request come back, if i understand it correctly the request token is past in the code param.
http://mydomain.se/o/authorize?scope=read+write&state=kalle&redirect_uri=mycallbakurls&response_type=code&client_id=myclientid
when i then try to do a post to http://mydomain.se/o/token/
with:
grant_type = authorization_code
code = code from authorize call
client_id = my clientId
client_secret = my client secret
redirect_uri = my callback url
i get "error" : "invalid_grant" back.
Can someone please point me in the right direction what the problem can be?
Best regards Markus
This can happen if the code is expired. They expire pretty quickly by default. You can look up your code in the Django admin under Grants and change the expiration date to far in the future.
I faced the same problem when my client type is confidential rather than public in o/application. Here's how I solved it.
Failed error message is {"error": "invalid_grant"}
curl -X POST -d "client_id=17U5rPQM1HDtF3hR8sIRP6pmzn033EbnwJJ6lNCx& client_secret=D6bSgR8qyIwDl5SyF4kJ0wBJq56NXMUY9LVjD6NZTxnAh4ylTD2YBJxDBaLahpabZMGowWpVTYn6UW8Yq1GB6nAwm7euXZZxXaCxQLKK2KDNrfz4JSavFCKekc1LOCQz&grant_type=authorization_code&code=EaBVzVEjqbsU0GKl5gXK7ArrfsSiTJ&redirect_uri=http%3A%2F%2Flocalhost%2Foauth_client%2F" http://localhost:8080/o/token/
{"error": "invalid_grant"}
Then changed my client type to public and got Success.
curl -X POST -d "client_id=17U5rPQM1HDtF3hR8sIRP6pmzn033EbnwJJ6lNCx&client_secret=D6bSgR8qyIwDl5SyF4kJ0wBJq56NXMUY9LVjD6NZTxnAh4ylTD2YBJxDBaLahpabZMGowWpVTYn6UW8Yq1GB6nAwm7euXZZxXaCxQLKK2KDNrfz4JSavFCKekc1LOCQz&grant_type=authorization_code&code=1ZxQjLN4QbpjaWgbztnOIe3K4bgxKj&redirect_uri=http%3A%2F%2Flocalhost%2Foauth_client%2F" http://localhost:8080/o/token/
{"access_token": "KstIqSnt9Mj4ITmCGRJpTYW3W59nRv", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "uJzJal9YSpirSax6vW2Di43ojRGvRV", "scope": "read write groups"}
Again changed back to Confidential and send my username and password in curl request.
curl -X POST -d "client_id=17U5rPQM1HDtF3hR8sIRP6pmzn033EbnwJJ6lNCx&client_secret=D6bSgR8qyIwDl5SyF4kJ0wBJq56NXMUY9LVjD6NZTxnAh4ylTD2YBJxDBaLahpabZMGowWpVTYn6UW8Yq1GB6nAwm7euXZZxXaCxQLKK2KDNrfz4JSavFCKekc1LOCQz&grant_type=authorization_code&code=UJnq1xfKULOUD0m2Oxb26NYmnuxKMn&redirect_uri=http%3A%2F%2Flocalhost%2Foauth_client%2F" -u'admin:pass' http://localhost:8080/o/token/
{"access_token": "VhMgx59x4PHUPOgSTKMGewsM8JfT58", "token_type": "Bearer", "expires_in": 36000, "refresh_token": "T0BhP1lFvyiS9c5rH6xHqt4uBItAS1", "scope": "read write groups"}
I Found that I can't do the request separately. When I built my own client and tested all worked fine for me.
Check to verify that you set your details correctly. For instance in my case my client_id was wrong.

Categories