You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
refresh_oauth2_token silently fails if can_refresh_access_token fails type validation #68
Discovered this issue when debugging refresh token issues with @RettBehrens .
If scope is passed as a str (or another type) rather than a list in the token set to the helper methodstore_xero_oauth2_token, then refresh_oauth2_tokenwill returnNone rather than the refreshed token set.
Steps to reproduce
Pass scopes as a space delimited string within the token set passed to an store_xero_oauth2_token
Call refresh_oauth2_token
Verify the return value of refresh_oauth2_token is None
What you expected would happen
Pass scopes as a space delimited string within the token set passed to an store_xero_oauth2_token
Call refresh_oauth2_token
can_refresh_access_token raises an error describing why the token cannot be refreshed: in this case, the error should state that scope must be a list of str
What actually happens
Pass scopes as a space delimited string within the token set passed to an store_xero_oauth2_token
Call refresh_oauth2_token
Since the return value of refresh_oauth2_token is not needed since store_xero_oauth2_token is called internally within refresh_oauth2_token, the issue is invisible and a silent failure occurs
The issue becomes known when the access token expires since it can never be refreshed due to failing type validation
This can't be intended behavior, right? When undergoing Xero's own oauth2 flow, the token is returned with it's scopes as a space delimited string, which causes refreshing to never work? I just came across this issue and after looking at the source code, it's as simple as relaxing the check on the scope value in can_refresh_access_token.
defcan_refresh_access_token(self):
""" Check current instance has all data required to perform refresh token API call. :return: bool """return (
self.refresh_tokenandisinstance(self.scope, (list, tuple))
andself.client_idandself.client_secret
)
I would make a push request to change that one line to and isinstance(self.scope, (list, tuple, str)) but to be honest I'm not sure what the original check might be guarding against. Regardless, it's wild that this is still an unexplained issue years later.
I'm pretty surprised that this is still an issue after so long. I'm not a maintainer, nor have touched this SDK in years, but I tried to trigger the Jira ticket creation GitHub action to make this issue more visible, though it looks like it only is triggered when new issues are created.
@j-osephlong I remember when I last spoke to one of the former maintainers, Xero was lacking sufficient resources to maintain the Python SDK and would welcome contributions. It looks like most pull requests get merged.
Running into the same issue. It worries me that the Python SDK is not maintained properly, we intend to hang a fairly large app on it. Any idea who I can contact? Can this PR be reviewed and approved? @manishT72@Raghunath-S-S-J
defcan_refresh_access_token(self):
""" Check current instance has all data required to perform refresh token API call. :return: bool """return (
self.refresh_tokenandisinstance(self.scope, (list, tuple))
andself.client_idandself.client_secret
)
but then in the TokenApi it expects a string again in the refresh_token method:
defrefresh_token(self, refresh_token, scope):
""" Call xero identity API to refresh auth2 access token using refresh token :param refresh_token: str auth2 refresh token :param scope: list of auth2 scopes :return: dictionary with new auth2 token """post_data= {
"grant_type": "refresh_token",
"scope": " ".join(scope),
"refresh_token": refresh_token,
"client_id": self.client_id,
"client_secret": self.client_secret,
}
So my final workaround is as follows (hoping @j-osephlong 's PR will be approved and merged.):
classCustomOAuth2Token(OAuth2Token):
defupdate_token(self, **kwargs):
valid_keys= {'access_token', 'refresh_token', 'token_type', 'expires_in', 'scope', 'expires_at'}
filtered_kwargs= {k: vfork, vinkwargs.items() ifkinvalid_keys}
super().update_token(**filtered_kwargs)
defcan_refresh_access_token(self):
""" Check current instance has all data required to perform refresh token API call. :return: bool """return (
self.refresh_tokenandisinstance(self.scope, (list, tuple, str))
andself.client_idandself.client_secret
)
Apologies for the delay and thanks for the PR. We are looking into the issue and will try to release the updated SDK soon. In the meanwhile, may I suggest the workaround of splitting scope string before storing it, just like @scottnri suggested.
Activity
scottnri commentedon Feb 23, 2022
I encountered this issue. My work around was to convert the scopes in the json to a list.
e,g. change
"scope": "email profile openid accounting.transactions offline_access"
to
"scope": ["email", "profile", "openid", "accounting.transactions", "offline_access"]
Seems to work fine now.
j-osephlong commentedon May 22, 2024
This can't be intended behavior, right? When undergoing Xero's own oauth2 flow, the token is returned with it's scopes as a space delimited string, which causes refreshing to never work? I just came across this issue and after looking at the source code, it's as simple as relaxing the check on the scope value in can_refresh_access_token.
I would make a push request to change that one line to
and isinstance(self.scope, (list, tuple, str))but to be honest I'm not sure what the original check might be guarding against. Regardless, it's wild that this is still an unexplained issue years later.benefacto commentedon May 23, 2024
I'm pretty surprised that this is still an issue after so long. I'm not a maintainer, nor have touched this SDK in years, but I tried to trigger the Jira ticket creation GitHub action to make this issue more visible, though it looks like it only is triggered when new issues are created.
@j-osephlong I remember when I last spoke to one of the former maintainers, Xero was lacking sufficient resources to maintain the Python SDK and would welcome contributions. It looks like most pull requests get merged.
That or perhaps one of the current maintainers could look into this? @manishT72 @Raghunath-S-S-J
j-osephlong commentedon May 23, 2024
First ever pull request! Wish me luck.
palunel commentedon Nov 26, 2024
Running into the same issue. It worries me that the Python SDK is not maintained properly, we intend to hang a fairly large app on it. Any idea who I can contact? Can this PR be reviewed and approved? @manishT72 @Raghunath-S-S-J
palunel commentedon Nov 26, 2024
I implemented this work around:
which made this pass:
but then in the
TokenApiit expects a string again in therefresh_tokenmethod:So my final workaround is as follows (hoping @j-osephlong 's PR will be approved and merged.):
manishT72 commentedon Dec 2, 2024
Apologies for the delay and thanks for the PR. We are looking into the issue and will try to release the updated SDK soon. In the meanwhile, may I suggest the workaround of splitting scope string before storing it, just like @scottnri suggested.
vigneshk-tw commentedon Mar 3, 2025
Hi, We've released a new SDK Version which fixes the issue.
Kindly check and confirm if we're good to close the issue.
Thanks,