3

I have a feature layer that I query from a python script using the ARCGIS REST API. I also call the Geoprocessing service to create buffers, etc. all using a token generated via my [portal_root]/oauth2/token endpoint. The APP ID and Secret that I use were generated in the same portal. All queries work fine, even if the services are not published publicly.

data = {
 'client_id':os.environ['CLIENT_ID'],
 'client_secret':os.environ['CLIENT_SECRET'],
 'grant_type':'client_credentials'
}
response = requests.post('{}/{}'.format(os.environ['PORTAL_ROOT'],'oauth2/token'), data=data, verify=True)
if response.ok== False:
 raise Exception("Could not authenticate to arcgis")
else:
 content = json.loads(response.content)
 token = content["access_token"]
 print('][==Authenticated==][')

I can then do things like:

apiEndpoint='Utilities/Geometry/GeometryServer/buffer'
data = {
 'geometries':json.dumps(quoteLocationGeometry),
 'inSR':4326,
 'outSR':102100,
 'distances':2000,
 'unit':9001,
 'token':token,
 'f':'json'
}
response = requests.post('{}/{}'.format(os.environ['SERVER_ROOT'],apiEndpoint), data=data, verify=True)
# Sprint(response.text)
if response.ok== False:
 raise Exception("Could not get Buffer",response.text)
else:
 quoteLocationBuffer = json.loads(response.content)

This all works fine. The last step in my script is to write some data back to a feature service/layer:

apiEndpoint = 'Hosted/SavedQuotes/FeatureServer/0/addFeatures'
feat = solvedRoutes['routes']['features'][0]
data = {
 'token':token,
 'f':'json',
 'features':json.dumps([{
 'attributes':{
 'details':feat['attributes']['Name'],
 'total_cost':feat['attributes']['Total_Cost'],
 'total_length':feat['attributes']['Total_Length'],
 'SHAPE__Length' : feat['attributes']['Shape_Length'],
 'origin_latitude' : lat,
 'origin_longitude' : lon,
 'rid':args.rid,
 'creator_userid' : 'some user ID or email',
 'creator_email' : '[email protected]',
 'creation_date': int(time.time())*1000
 },
 'geometry':{
 'spatialReference':solvedRoutes['routes']['spatialReference'],
 'paths':feat['geometry']['paths']
 }
 }])
 }
print(json.dumps(data))
response = requests.post('{}/{}'.format(os.environ['SERVER_ROOT'],apiEndpoint), data=data, verify=True)
if response.ok== False:
 raise Exception("Could not Save Quote",response.text)
print(response.content)

This call fails with a:

'{"error":{"code":500,"message":"User does not have the privilege to perform this operation.","details":[]}}

If I make the Feature layer public, the write works fine, so I know the API call is formatted correctly. I have a valid Auth token, and all READ operations work fine using this token. I opened a ticket with ESRI and it was closed with "sorry, you can't write to a feature layer using OAuth. The layer has to be public. I 100% cannot believe this to be the case. Why can't I write to a feature layer using the REST API + OAuth? The ESRI rep kept sending me docs on the Portal Administration REST api, even after me sending the script and describing in detail what I am trying to do, he just keeps saying it's not possible. He did say I could call the generateToken endpoint with a username and password, but the docs state that interface is superseded by OAuth, and we use OAuth everywhere. It's not adding up.

asked Mar 22, 2022 at 18:55

1 Answer 1

0

Looks like you don't get full owner privileges to your account resources unless you go through the full OAuth process. For example:

from urllib.parse import urlencode
import requests
import webbrowser
portal_root = 'https://www.arcgis.com/sharing/rest'
params = {
 'client_id': 'YOUR_CLIENT_ID',
 'response_type': 'code',
 'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
 'expiration': 1440
}
auth_url = portal_root + '/oauth2/authorize?' + urlencode(params)
webbrowser.open(auth_url)
auth_code = input('Enter Approval Code: ')
data = {
 'client_id': 'YOUR_CLIENT_ID',
 'grant_type': 'authorization_code',
 'code': auth_code,
 'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob',
 'f': 'json'
}
auth_response = requests.post(portal_root + '/oauth2/token', data)
token_data = auth_response.json()
answered Jun 16, 2022 at 19:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.