0

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)

1 Answer 1

1

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')

5
  • When I execute the WebTool from within the portal (used in a WebMap) the user is logged into the portal. For me it looks like it is not possible to access the executing user in the GP Tool when executed as a WebTool. Commented Aug 29, 2022 at 12:53
  • I already tried the SignInToPortal method, but there I would need to store some admin user credentials within the code which looks not ideal. Commented Aug 29, 2022 at 12:55
  • There is no connection between the WebMap / WebApp being logged in and the WebTool that is running on a Server somewhere. Two independent processes.
    – KHibma
    Commented Aug 29, 2022 at 13:18
  • But when I make the request I can see the token is submitted with the request to the backend / IIS. So I guess the GP Tool must be able to identify the user which triggered the GP Tool, right? Commented Aug 29, 2022 at 13:59
  • 1
    No. You'd need to explicitly build that into the tool/workflow (getting a token as a parameter and have the calling application pass it in --even then, not sure you can 'share' a token like that). The GP Service framework does not log the user/identity (at least not in the way that those credentials are available internally to the code inside). I understand why you'd make that assumption, and it would be pretty cool if it did, but simply, this is not how it works.
    – KHibma
    Commented Aug 29, 2022 at 16:00

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.