oauth2client.client - Received token response with no refresh_token. Consider reauthenticating with prompt='consent' - google-api

I received google auth code from mobile app and use python oauth2client to exchange to access token and refresh token as follow:
credentials = client.credentials_from_clientsecrets_and_code(
app.config.get('GG_APP_SECRET'),
['profile'],
authCodeFromMobileApp,
redirect_uri='http://example.com')
Then I received:
Received token response with no refresh_token. Consider
reauthenticating with prompt='consent'.
Based on this it said that I have to set: access_type=offline But I'm not really sure where/how in oauth2client to set this?
Anyone here ever solve this issue before?
Addition:
I have tried below as well:
flow = client.flow_from_clientsecrets(app.config.get('GG_APP_SECRET'),
['profile'],
message=None,
cache=None,
redirect_uri='http://example.com',
device_uri=None)
flow.params['access_type'] = 'offline'
credentials = flow.step2_exchange(req_gg_code, http=None)
But still having the same unexpected result...

flow_from_clientsecrets method has parameter called prompt which you can pass a value "consent"
flow = client.flow_from_clientsecrets(
app.config.get('GG_APP_SECRET'),
['profile'],
message=None,
cache=None,
redirect_uri='http://example.com',
device_uri=None,
prompt='consent'
)
Now, it will ask for Users consent every time, and you would get a refresh_token every time to use.

Related

Epic EMR FHIR refresh_token FHIR.OAuth2.Authorize()

I am following example by https://www.patient.dev/2021/01/12/build-a-fhir-app-for-epic-ehr-systems/
Example works nicely in various variations.
I am trying to extend the example such that after first time user Authenticates/Authorizes, Epic would return back refresh token. My intent is that repeat Authorizations/Authentications would not be needed.
I modify Epic App at https://fhir.epic.com/Developer/Apps to request refresh_token, copy and save the provided client secret.
Next I call on launch.html:
FHIR.oauth2.authorize({
'client_id': 'xxxxxxxxxxxxxxmyclientidxxxxxxxx',
'client_secret': 'yyyyyyyymyclientsecret',
'scope': 'PATIENT.READ, PATIENT.SEARCH, OBSERVATION.READ, OBSERVATION.SEARCH',
'redirect_uri': 'https://myapp.myrepl.repl.co/app.html'
});
Observations:
There is no difference in behavior whether I add 'client_secret' or no.
Both cases login to Epic works, after login I land on page that asks me to do the normal authorizations plus define how long an access do I grant.
Succeeding redirect to .../app.html then leads to unsuccessful call :
FHIR.oauth2.ready().then(function(client){
myApp.smart = client
doRequests()
})
Question:
Is is wrong hypothesis to expect that Epic returns refresh_token to redirect uri page ?
If yes, should I modify call to FHIR.oauth2.authorize() ?
Or is it totally undoable with smart.js functions and I should write my own GET/POST calls for stepwise authorization & authentication?
Thank you for your support, Beibian

Separate invalid token responses

Currently, if user tries to reset password using link which was built using reset token, at certain point validateReset function inside PasswordBroker.php is called. In the body of this function, validation of token itself is done, and if it is not valid static::INVALID_TOKEN will be returned. The problem is that from this response I can not know if the token was invalid because token string was wrong or because the token has expired.
My question is if it is possible to override this function to act differently for this two cases, specifically, I want to display informing message to user if token has expired and send him an email containing new reset link.

Jmeter token refreshing

I find the topic Refreshing Auth Token while keep the requests running in JMeter 3.3. I faced with same task - token refreshing each x time and other request sending at the same time. I've seen that author has find the solution. But I would be really appreciated if you could share the logic. I tried with global property in Jmeter, but it seems that I set one token for all users. The timer was allso added, but I'm getting one token for sessions. Probably we have a new solution for Jmeter 5.x. Thanks.
The solution would be the same, you just need to amend it a little bit and use __threadNum() function in order to create thread (virtual user)-specific properties.
Something like:
${__setProperty(token_${__threadNum},variable containing the token,)}
will generate the following JMeter properties:
token_0=token for the first virtual user
token_1=token for the second virtual user
etc.
which can be accessed similarly using __P() function like:
${__P(token_${__threadNum},)}
More information: Here’s What to Do to Combine Multiple JMeter Variables
Thank you so much! I have implemented my script using the following logic in one thread group:
Set var “Trigger” = 60 seconds (token refreshing interval, per minute);
Login user;
Get Token request; and execute actions:
Extract Token and save to vars;
Save “TokenTime” to vars (where “Login” from CSV is the name of property);
Calculate “TokenDiffTime” = “TimeNow- TokenTime” -> Save as property with unique name (the unique name can be the string “Login”+”TimeDiff”- where “Login” is dynamic Login from CSV and “TimeDiff” – just static string; the example of property name is “User1TimeDiff”).
Loop controller with logic:
If Controller (Is token Actual? -> check “TokenDiffTime” >=“Trigger”) -> Call Refresh Token request; Extract actual token.
Invoke App request; using actual token.
If Controller (Is token Actual? -> check “TokenDiffTime” >=“Trigger”) -> Call Refresh Token request; Extract actual token.
Invoke App request; using actual token.
So, such logic takes into account the response time delays and a new app request is invoking with actual token. “Trigger” is flexible value to set token refreshing interval. Hope such topic could be useful to someone.

How to logout user when he changes password from all browsers (Django-rest-auth, JWT)?

First of all, i am new with django-rest-framework so please excuse me if I'm wrong.
I'm working with django-rest-auth and django-restframework-jwt to authenticate users. I'm saving the jwt token in localStorage everytime the user logs in.
The problem That I'm facing now is that when I log in with same credentials in two browsers and then I change password in one of them, the other account still valid and user still can navigate and see all pages even though the password has changed.
I wanted to make his JWT token invalid when he changes password so that he will be automatically logged out. But I couldn't find a way to expire his token in official documentation of Django REST framework JWT
I tried to track the moment of changing password by generating manually a new JWT token for user, but this is not working (maybe because the existing token is still valid)
#receiver(signals.pre_save, sender=User)
def revoke_tokens(sender, instance, **kwargs):
existing_user = User.objects.get(pk=instance.pk)
if getattr(settings, 'REST_USE_JWT', False):
if instance.password != existing_user.password:
# If user has changed his password, generate manually a new token for him
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(instance)
payload['orig_iat'] = timegm(datetime.utcnow().utctimetuple())
instance.token = jwt_encode_handler(payload)
After reading some documenations and posts, it seems that this is not quite easy with only jwt since it's stateless, But could somebody point me the direction where to go?
Should I remove JWT authentication?
Is there a work around that can help me on this ?
Thanks a lot.
EDIT:
I found a comment in a similar post on SO by #Travis stating that
A common approach for invalidating tokens when a user changes their
password is to sign the token with a hash of their password. Thus if
the password changes, any previous tokens automatically fail to
verify. You can extend this to logout by including a last-logout-time
in the user's record and using a combination of the last-logout-time
and password hash to sign the token. This requires a DB lookup each
time you need to verify the token signature, but presumably you're
looking up the user anyway
I'm trying to implement that ..I will update my post if it worked.
Otherwise, I still open to suggestions.
After days of work, I ended up by overriding the JWT_PAYLOAD_HANDLER and adding the last digits of the user's hash of password in the payload of JWT token (since adding all the hash of password in the payload is not a good practice)
and then creating a custom middleware that intercepts all requests.
in every request I check from jwt token if the hash of the password matches the existing user's hash (if not that means that the user has changed his password)
if they are different then I raise an error and logout the user with old hash of password.
in config file :
'JWT_PAYLOAD_HANDLER': 'your.path.jwt.jwt_payload_handler',
and in the root stated in the config file :
def jwt_payload_handler(user):
username_field = get_username_field()
username = get_username(user)
payload = {
'user_id': user.pk,
'username': username,
'pwd': user.password[-10:],
'exp': datetime.utcnow() + api_settings.JWT_EXPIRATION_DELTA
}
if hasattr(user, 'email'):
payload['email'] = user.email
if isinstance(user.pk, uuid.UUID):
payload['user_id'] = str(user.pk)
payload[username_field] = username
return payload
and then this is the custom middleware :
from django.http.response import HttpResponseForbidden
from django.utils.deprecation import MiddlewareMixin
from rest_framework_jwt.utils import jwt_decode_handler
from config.settings.base import JWT_AUTH
from trp.users.models import User
class JWTAuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
jwt_user_pwd = self.get_jwt_user_pwd(request)
# check if last digits of password read from jwt token matches the hash of the current user in DB
if jwt_user_pwd is not None:
if jwt_user_pwd['pwd'] != jwt_user_pwd['user'].password[-10:]:
return HttpResponseForbidden()
#staticmethod
def get_jwt_user_pwd(request):
token = request.META.get('HTTP_AUTHORIZATION', None)
# Remove the prefix from token name so that decoding the token gives us correct credentials
token = str(token).replace(JWT_AUTH['JWT_AUTH_HEADER_PREFIX'] + ' ', '')
if token:
try:
payload = jwt_decode_handler(token)
authenticated_user = User.objects.get(id=payload['user_id'])
except Exception as e:
authenticated_user = None
payload = {}
if authenticated_user and payload:
return {'user': authenticated_user, 'pwd': payload.get('pwd')}
return None
To logout the user I have read the status code of the request 'in this case 403' from front end : (I'm using Angular in my case) and then logout the user
I hope it helps someone in the future .
Well,
It is all about token expiry time - If you keep this short (like 10-15 minutes) - you can no bother with invalidating it when a password or some permissions will change. Token will be invalidated always after some short period of time and a new one will be issued.
If you are using JWT as long living token (which is not good practice) - you will have problems.
Because actions like changing a password and invalidating other tokens (different session) (or force recreate) needs to be stored somewhere else (like some NoSQL store) - and checked for each session that some special action is required - and then you are losing the stateless advantage of JWT.

Inapppurchases: get api query failed "code":400,"message":"Invalid Value" "code":500,"message":null

I get access_token by this way :https://developers.google.com/android-publisher/authorization
1.use google account allow acess get code
2.use code to get refresh_token
3.use refresh_token get access_token
when use this api
$url_purchase = "https://www.googleapis.com/androidpublisher/v1.1/applications".
"/$packageName/inapp/$productId/purchases/$token?access_token=".
$return_data->access_token;
$return_purchase = http_get($url_purchase);
some billing return
{"error":{"code":500,"message":null}}
some billing return
{"error":{"errors":[{"domain":"global","reason":"invalid","message":"Invalid Value"}],"code":400,"message":"Invalid Value"}}
but some billing can success return
{"kind":"androidpublisher#inappPurchase","purchaseTime":"1395035642794","purchaseState":0,"consumptionState":1}
I think the access_token is right, why some billing failed . someone can help me ?thanks very much.
Are there any other way to check billing valid on the server?

Resources