Automatically refresh access token with django-social-auth (omab) - python

I am currently using django-social-auth to manage oauth2 registration with google-oauth2 for access to Google Drive. I have added offline access to my extra_arguments. Therefore Google returns a refresh token and it is stored by django-social-auth. The problem is that django-social-auth never uses this refresh token to update the access token. Therefore the access token expires after one hour, and I can't use it to perform offline requests. I want to keep the access_token valid 24/7 so I can keep my database synced with each users Google Drive.
GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {'access_type':'offline'}
GOOGLE_OAUTH_EXTRA_SCOPE = ['https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/userinfo.profile']
SOCIAL_AUTH_USER_MODEL = 'accounts.GoogleDriveUser'
SOCIAL_AUTH_EXTRA_DATA = True
SOCIAL_AUTH_SESSION_EXPIRATION = False
Is there a way to force django-social auth to update the access_token every time it expires using the refresh_token. I would love to see an example of how this problem could be solved.

It looks like UserSocialAuth objects now have a .refresh_token() method, which allows you to use .tokens and get the updated token.

There's no way directly implemented in django-social-auth at the moment (I've raised a ticket to track it https://github.com/omab/django-social-auth/issues/492), meanwhile this snippet will do the work, it just need to be improved a little to suite your needs.

Related

Salesforce API - This session is not valid for use with the REST API - Invalid Session ID

For over a year, I have connected to Salesforce using the simple_salesforce package in order to pull some data from various objects and load it to a data lake.
I have used the authentication method using username / password / security token.
client = Salesforce(
username="****************",
password="*************",
security_token="****************"
)
On the 1st of February came the enforcement of multi factor auth. Starting on that day, I consistently hit the same error over and over.
[{'message': 'This session is not valid for use with the REST API', 'errorCode': 'INVALID_SESSION_ID'}]
After some research, I tried to add a permission set with API Enabled and then API Only user. Result: still the same error, but now I am locked out of the UI.
Has anyone else encountered similar issues and could point me towards the right resources, please? Thanks!
MFA shouldn't matter for API access according to https://help.salesforce.com/s/articleView?id=000352937&type=1 (Ctrl+F "API"), it's probably something else your admin did.
Username, password+token sounds like you're use SOAP login method.
See if you can create a "connected app" in SF to use the OAuth2 login method, more natural for REST API. I wrote a bit about it in https://stackoverflow.com/a/62694002/313628. In the connected app you should be able to allow API access, even full if needed. No idea if Simple has natural place for the keys though, it's bit rubbish if you'll have to craft raw http requests yourself.
Simple's documentation also mentions using JWT to log in (and that requires connected app anyway), basically instead of username + pass you go username + certificate + the fact admin preauthorised this user... You'll be fine until certificate expires.
The text part of https://gist.github.com/booleangate/30d345ecf0617db0ea19c54c7a44d06f can help you with the connected app creation; sample code's probably not needed if you're going with Simple

Storing access and refresh token in python self.sessions doesn't work

I am currently developing integration for users and groups through Azure AD. I have set up everything to retrieve an access and refresh token upon login, I am only having trouble storing both of them in the sessions. I am assigning the tokens to a session and trying to retrieve them as shown below.
self.session["access_token"] = json.dumps(access_token)
self.session["refresh_token"] = json.dumps(refresh_token)
then I am fetching both tokens on another page, using
access_token = json.loads(self.session.get('access_token'))
refresh_token = json.loads(self.session.get('refresh_token'))
I can only for some reason get the access_token inside the other page, the refresh token is always None. For reference I am using the BaseHandler module on both pages.I was thinking of storing both in the database being a solution, but I want to know if it is possible to configure it in some way to work with self.session. Any help is greatly appreciated!

Django: Pulling data from Quickbooks Online and Storing it into MySQL database

I recently have a Django project that requires me to pull data from Quickbooks Online and then storing it in MySQL database for later uses.
Following a tutorial that I found in https://github.com/sidecars/python-quickbooks, I was able to get my access and refresh token using
quickbooks-cli -p 8000 <Client ID> <Client Secret> 2
Here come a few questions I like to ask:
Is there any implications setting http://localhost:8000 as one of my Redirect URIs in the Intuit Developer's Key section?
What should I do with the access and refresh token? I think I need to continue from the "Accessing the API" section in https://github.com/sidecars/python-quickbooks but I have no idea which files to put the code mentioned in the documentation (I do not touch API in the past so some guidance is appreciated)
I noticed there is a duration before the access and refresh token expires, so does it mean I have to change them every once in a while?
Thanks in advance.
Is there any implications setting http://localhost:8000 as one of my Redirect URIs in the Intuit Developer's Key section?
You won't be able to go live with that set (Intuit won't let you). But for development, it's fine.
Eventually you should swap that out for your production URL.
What should I do with the access and refresh token?
Here's what the docs you linked to them say:
"Store access_token and refresh_token for later use."
Also, you'll need to use the access token to access data via the API. From the docs:
session_manager = Oauth2SessionManager(
client_id=realm_id,
client_secret=CLIENT_SECRET,
access_token=AUTH2_ACCESS_TOKEN,
)
from quickbooks import QuickBooks
client = QuickBooks(
sandbox=True,
session_manager=session_manager,
company_id=realm_id
)
from quickbooks.objects.customer import Customer
customers = Customer.all(qb=client)
This is shown in the docs here: https://github.com/sidecars/python-quickbooks#accessing-the-api
I noticed there is a duration before the access and refresh token expires, so does it mean I have to change them every once in a while?
You have to refresh them, yes:
session_manager = Oauth2SessionManager(
client_id=QUICKBOOKS_CLIENT_ID,
client_secret=QUICKBOOKS_CLIENT_SECRET,
base_url=callback_url,
)
session_manager.refresh_access_token()
From the docs here: https://github.com/sidecars/python-quickbooks#refreshing-access-token

How can I get oauth_access_token for facebook-sdk

I want to code that post facebook. So I decided to use python-sdk (https://github.com/pythonforfacebook/facebook-sdk).
Then I hit a problem.
graph = facebook.GraphAPI(oauth_access_token)
How can I get this "oauth_access_token"?
You need to use an authorization flow. Access tokens are the keys used after getting proper authorization.
An access token is an opaque string that identifies a user, app, or
page and can be used by the app to make graph API calls. Access tokens
are obtained via a number of methods, each of which are covered later
in this document. The token includes information about when the token
will expire and which app generated the token. Because of privacy
checks, the majority of API calls on Facebook need to include an
access token.
There are various ways to obtain an access token all explained in https://developers.facebook.com/docs/facebook-login/access-tokens/
For testing, one must create an app at https://developers.facebook.com/apps and can be issued an access token at https://developers.facebook.com/tools/access_token
Here is a way to get the user access token :
instance = UserSocialAuth.objects.get(user=request.user, provider='facebook')
token = instance.tokens
graph = facebook.GraphAPI(token['access_token'])
Maybe you've already figured this out, just in case somebody else is looking for it

Getting invalid_grant when trying to refresh token

When an OAuth2Credential object tries to refresh its access_token, sometimes it gets an error of invalid_grant and then it becomes unable to be refreshed. The code I used is based on Google's python API and Mirror API examples.
Background:
Using oauth2client module for authentication and OAuth2Credential object.
Storing the OAuth2Credential object pickled and base64'd into the database like Google's own example code
Using apiclient module to make calls to the Mirror API
This code runs on 3 different servers, all exhibiting the same issue when trying to send
The scopes I ask for are "https://www.googleapis.com/auth/glass.timeline" and "https://www.googleapis.com/auth/userinfo.profile"
I can confirm that access_type is set to "offline"
I ask for approval_prompt to be "force" just in case
Here is the code that is being used to call the mirror API:
from apiclient.discovery import build
http = credential.authorize(http=httplib2.Http())
service = build("mirror", "v1", http=http)
payload = <JSON_PAYLOAD_HERE>
service.timeline().insert(body=payload).execute()
When the service is called, there is the potential for it to issue a 401 which means the access_token needs to be refreshed. It then calls the refresh method which excepts with AccessTokenRefreshError with the error invalid_grant. At this point, the credential is as good as bunk, since the access_token is expired and the refresh_token will only give the same error.
I have seen pages that say this can happen due to either NTP problems, but I have confirmed (and even switched NTP servers) that my servers are in sync. The other documented possibility is that only 25 refresh tokens can exist before they get recycled, but I have implemented a store() method on the Credential object so when it is refreshed, the new credentials are saved in place (I can confirm that this works as I see new information in the database when it is refreshed).
Since I can't get a user's credentials to start exhibiting this problem on demand, I can't explain any other conditions to recreate the issue other than "waiting some time". I have seen the issue happen soon after authenticating and sending one call, all the way to a week's worth of time after a hundred calls.
The only way for now to get the issue to be resolved is to ask the user to reauthorize, but that isn't a solution since I am expecting to use the api's offline without user interaction. I'd also have no way to notify the user that they need to reauthorize.
Answer from the comment thread: the user had toggled off the Glassware from the MyGlass website which resulted in the token being revoked.
The user needs to go through the authorization flow again in order to be able to use the Glassware by either visiting the Glassware authorization endpoint or toggling it back "on" on MyGlass if available.

Categories

Resources