When using OAuth2, FilesManager methods, such as upload_file, return a XeroForbidden error, with status code 403 and message "AuthenticationUnsuccessful".
Error details
Using django 2.2.8 locally (together with django-sslserver==0.22, in order to be able to test OAuth2 over https as Xero requires), I successfully set up the credentials (credentials in code below) and am able to successfully read contacts using a new Xero instance.
After setting up a FilesManager instance, I attempt to upload test.pdf:
File "XXXX/xero_testing/env/lib/python3.9/site-packages/xero/filesmanager.py", line 100, in wrapper
raise XeroForbidden(response)
xero.exceptions.XeroForbidden: {"Type":null,"Title":"Forbidden","Status":403,"Detail":"AuthenticationUnsuccessful","Instance":"XXXX","Extensions":{}}
Other FileManager methods produce a similar error.
A solution could be to remove the current line 77 from xero/filesmanage.py, auth=self.credentials.oauth,, and replace line 76 something similar to the following, in accordance with Xero's OAuth2 documentation specifications:
Summary of error
When using OAuth2,
FilesManager
methods, such asupload_file
, return aXeroForbidden
error, with status code 403 and message "AuthenticationUnsuccessful".Error details
Using django 2.2.8 locally (together with django-sslserver==0.22, in order to be able to test OAuth2 over https as Xero requires), I successfully set up the credentials (
credentials
in code below) and am able to successfully read contacts using a newXero
instance. After setting up a FilesManager instance, I attempt to uploadtest.pdf
:The error returned is:
Other FileManager methods produce a similar error.
Analysis of problem
It seems that when making requests, FileManager methods incorrectly submit OAuth2 credentials as an
auth
keyword argument, as if they were OAuth1 credentials (e.g. https://2.python-requests.org/en/master/user/authentication/#oauth-1-authentication). See line 77 ofxero/filesmanage.py
here:https://github.com/freakboy3742/pyxero/blob/35173e9bf5d20a61c37dc1d78710f6d9b34abc84/xero/filesmanager.py#L77
However, according to the Xero OAuth2 documentation, the credentials need to be submitted as request headers (see step 6, '6. Call the API', at https://developer.xero.com/documentation/oauth2/auth-flow).
Possible solution
A solution could be to remove the current line 77 from
xero/filesmanage.py
,auth=self.credentials.oauth,
, and replace line 76 something similar to the following, in accordance with Xero's OAuth2 documentation specifications:Doing so resolves issues on my machine and the
test.pdf
successfully uploads.