Arcpy – How to Access User Calling a Web Tool in ArcGIS Enterprise

arcgis-enterprisearcgis-python-apiarcgis-serverarcpygeoprocessing-service

I am currently developing a GP Tool / WebTool for ArcGIS Enterprise. Main goal of the tool is to write what3word tags to point features.

Workflow is as follows:

  1. User selects a layer in the webmap
  2. Run the tool
  3. Tool checks if certain attributes are available in the layer (w3w, w3w_last_edited_date and last_edited_date – editor tracking must be enabled)
  4. If w3w_last_edited_date and last_edited_date do not match the w3w field gets updated using the w3w endpoint like https://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={key}

Running the tool from ArcGIS Pro is working fine. But when I publish it as a WebTool on ArcGIS Enterprise I get a long error message – the important part is Exception: Unable to generate token. 'token' must be specified in the request, for server token.

As you can see in my code I am using the GetSigninToken method from arcpy. But it looks like this is not what I want. My question is – is it possible to access the token of the user who runs the GP Tool / WebTool so the tool can make all the requests / updates using the user token?


from arcpy import GetSigninToken, GetParameterAsText, AddMessage, AddError
from arcgis.features import FeatureLayer, FeatureCollection
from platform import node
from datetime import datetime
import requests

# Main Function
def ScriptTool(featureLayerUrl):
  # W3W Key
  W3WKEY = "********"

  # Check for token
  tokenDict = GetSigninToken()
  if tokenDict is not None:
    token = tokenDict["token"]

    # Load Layer
    layerUrl = f'{featureLayerUrl}/0?token={token}'
    featureLayer = FeatureLayer(layerUrl)

    # Check if mandatory fields exist
    mandatoryFieldNames = ["w3w", "w3w_last_edited_date", "last_edited_date"]
    existingFieldNames = [f["name"] for f in featureLayer.properties["fields"]]
    for mandatoryFieldName in mandatoryFieldNames:
      if mandatoryFieldName not in existingFieldNames:
        AddError(f'Missing mandatory field: {mandatoryFieldName}!')
        return

    # Iterate over all items 
    # If w3w_last_edited_date and last_edited_date are different update w3w
    fc = FeatureCollection.from_featureset(featureLayer.query(out_sr=4326))
    updates = []
    for feature in fc.query():
      # Access properties
      w3w_last_edited_date = feature.attributes["w3w_last_edited_date"]
      last_edited_date = feature.attributes["last_edited_date"]
      lat = feature.geometry["y"]
      lng = feature.geometry["x"]

      # Check if date changed
      if w3w_last_edited_date != last_edited_date:
        try:
          res = requests.get(f'https://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={W3WKEY}')
          w3w = res.json()["words"]
          feature.attributes["w3w"] = w3w
          feature.attributes["w3w_last_edited_date"] = last_edited_date
          updates.append(feature)
          AddMessage(f'Updated location at Lat: {lat}, Lng: {lng}')
        except:
          AddError("Error updating w3w")
    
    update_result = featureLayer.edit_features(updates=updates)
    AddMessage(update_result)
    return 

# This is used to execute code if the file was run but not imported
if __name__ == '__main__':
  
  # Parameter 1 is the layer on which the w3w tag should be set
  featureLayerUrl = GetParameterAsText(0)
  ScriptTool(featureLayerUrl)

Best Answer

The key point here can be found in the help of the GetSignInToken tool

The GetSigninToken function will return the token and expiration information when signed in to a portal. If the application is not signed in, the function will return None

This tool is to be used from within ArcGIS Pro, where you have already signed in to the Portal. Your web tool is not signed in. The GetSigninToken tool is able to take advantage of the already established connection and grab the token for you. You would need to sign in when the tool is run. The session (and being signed in) does not persist from one web tool execution to another. I'd look into using the SignInToPortal tool to establish that connection. I'll caution: depending on the authentication requirements of your Portal, it's possible this may not work. The next caution is you'll need to hard code username and passwords into the tool. If you aren't comfortable doing this, you'll need to look into other ways to authenticate (such as the ArcGIS Python API, as this offers different ways to 'login')

Related Question