When connecting to my organizational AGOL account via the Python API, I have found lately that while the login appears to succeed, I do not have the same level of access to my items that I have when accessing them through the AGOL browser interface or ArcGIS Pro.
Setup
First, I import my packages:
from arcgis.gis import *
from IPython.display import display
My organizational account must be authenticated via OAuth 2.0. I have followed the instructions here for authenticating with OAuth 2.0. I have created an application called Python and used the following code to login.
gis = GIS("https://{{ MY_ORG }}.maps.arcgis.com", client_id='{{MY_APP_ID}}')
print("Successfully logged in as: " + gis.properties.user.username)
This appears to work with no problem as there are no errors returned and the following statement is printed:
Successfully logged in as: {{ MY USERNAME }}
However, problems arise when I try to access any of my items. Note, by "my items" I mean those for which I am the item owner. For the sake of example, let's say I try to access an item by its item number:
item = gis.content.get('{{SOME ITEM ID}}')
display(item)
This throws the following error
You do not have permissions to access this resource or perform this operation.
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-3-faf871f03a5b> in <module>()
----> 1 gis.content.get('{{ SOME ITEM ID }}')
~\Miniconda3\envs\arcpython\lib\site-packages\arcgis\gis\__init__.py in get(self, itemid)
2653 return None
2654 else:
-> 2655 raise re
2656
2657 if item is not None:
~\Miniconda3\envs\arcpython\lib\site-packages\arcgis\gis\__init__.py in get(self, itemid)
2648 """
2649 try:
-> 2650 item = self._portal.get_item(itemid)
2651 except RuntimeError as re:
2652 if re.args[0].__contains__("Item does not exist or is inaccessible"):
~\Miniconda3\envs\arcpython\lib\site-packages\arcgis\_impl\portalpy.py in get_item(self, itemid)
1206 ================ ========================================================
1207 """
-> 1208 return self.con.post('content/items/' + itemid, self._postdata())
1209
1210 def get_item_data(self, itemid, try_json=True):
~\Miniconda3\envs\arcpython\lib\site-packages\arcgis\_impl\connection.py in post(self, path, postdata, files, ssl, compress, is_retry, use_ordered_dict, add_token, verify_cert, token, try_json, out_folder, file_name, force_bytes, add_headers)
1154 verify_cert=verify_cert, is_retry=True)
1155
-> 1156 self._handle_json_error(resp_json['error'], errorcode)
1157 return None
1158
~\Miniconda3\envs\arcpython\lib\site-packages\arcgis\_impl\connection.py in _handle_json_error(self, error, errorcode)
1175
1176 errormessage = errormessage + "\n(Error Code: " + str(errorcode) +")"
-> 1177 raise RuntimeError(errormessage)
1178
1179 class _StrictURLopener(request.FancyURLopener):
RuntimeError: You do not have permissions to access this resource or perform this operation.
(Error Code: 403)
I have tested this process under a few different scenarios and not had these permission errors arise:
Has anyone encountered this issue before? Any thoughts on how to troubleshoot?
Hi Ryan, I was having the same frustrations as you and I ended up calling ESRI for assistance. Basically, it doesn't matter what your organization privileges are or even if you own the data. The item must be shared publicly in order to be accessible via gis.content.get
Even the analyst on the phone agreed with me that seems to restrict the ability to use the API as an organizational administrator but that is how the API is currently written.
Thanks for sharing your experience. I have managed to use gis.content.get to access private items using the username and password of a public account associated with our organization. Not really ideal because almost nobody in our organization authenticates this way. Especially since our org is going all-in on AGOL, it's frustrating to find out that ownership doesn't really mean ownership.
The following code displays private items for me:
from IPython.display import display
from arcgis.gis import GIS
ItemId = 'bc9f80dd6ea341f9b420i1998c07ec05'
PortalUserName = 'myCaseSensitiveUsername'
PortalPassword = 'myPassword'
PortalUrl = 'https://www.arcgis.com'
PortalCertVerification = True
gis = GIS(PortalUrl, PortalUserName, PortalPassword, verify_cert=PortalCertVerification)
itemObject = gis.content.get(ItemId)
display(itemObject)
As you mentioned it is absolutely possible to access, display and modify private content via the API, and you have it working in various environments.
However this particular case is a little different because of the kind of authentication you are using. When you login using OAuth this way by registering an application, you don't gain access to all content owned by the user - there are various built in limitations, as documented here (also listed below):
This is most likely the cause of the permissions message you are getting, and is by design. In order to access private content, you will have to work with one of the other authentication schemes available with the API.
Thank you for your response, Michael. We use ADFS to authenticate, so the example you've include unfortunately doesn't apply to my organization. I have tried adapting the the Active Directory instructions on the link you included, but have been unable to successfully authenticate. I've had trouble determining what the webadapter name and domain are. Regardless OAuth through an app is the only authentication scheme I've gotten to work.
Is there an explanation for why this restriction on tokens obtained by applications exists? I'm just a little confused as to why this sort of authentication is sufficient for me to access premium content available through my organizations ELA, but not enough for me to access items that are mine.
Following up on my attempt to authenticate using the Active Directory.
Here's what is listed on the website about authenticating using the Python API:
from arcgis.gis import GIS
gis = GIS("https://portalname.domain.com/webadapter_name", "AVWORLD\\Publisher", "password")
I have to admit I don't have the language to speak to the difference between Portal and...well I'm not sure what else...but what I can say is all our data, maps, and apps are on ArcGIS Online as a part of our Organization. As for domain, I have used the one found under my Windows system information:
So based on the template above, I thought I'd be able to authenticate with the following:
gis = GIS("https://ral.maps.arcgis.com/arcgis", "ci.raleigh.nc.us\\{USERNAME}", "{PASSWORD}")
However, I just get a 404 error.
I've spoken with our IT/GIS department and they seemed to thing I was using the correct web adaptor and domain names, but still no dice. Any recommendations?
Hi Ryan,
I think you're nearly there. The Portal URL you are providing does not exist (hence the 404), you need something like this (note 'home' vs 'arcgis'):
from arcgis.gis import GIS
PortalUsername = 'ci.raleigh.nc.us\\yourUsername'
PortalPassword = 'yourPassword'
PortalUrl = 'https://ral.maps.arcgis.com/home'
gis = GIS(PortalUrl, PortalUsername, PortalPassword)
print("Logged in as: " + gis.properties.user.username)
Any joy with this? An alternative would be to use an ArcGIS Online Named User which doesn't use ADFS.
The aim of app logins is to allow the use of premium content in ArcGIS Online without having to sign in. Essentially it is an authentication mechanism which allows the use of premium services publically (credits are consumed by the app login user where appropriate). It is not intended to grant access to content owned by the user in question. It is typically used in combination with various API's/SDK's.
Mikie
I would also suggest you try connecting via ArcGIS Pro:
gis = GIS("pro")
This will use the active user in ArcGIS Pro.
Ryan - what did you end up doing to get this to work for you? I'm in the same boat with ADFS as the enterprise standard.
Heather-
I wish I had better news, but unfortunately I was never able to successfully authenticate using the Python API via ADFS.