Select to view content in your preferred language

Create token and access feature Layer

216
12
Monday
kapalczynski
Frequent Contributor

I have this code snip below.  

  • Trying to get a token 
  • return that token
  • and use gis.content.get(feature_layer_id) to secure access to a service

 

  • Line 14 The variable "custom_token" prints with no issues
  • Line 18 prints fine as well "Token successfully generated! Expires at timestamp: 1780364453189"
  • Line 21 prints back NONE
  • and Line 23 gives error: Exception: You do not have permissions to access this resource or perform this operation.
    (Error Code: 403)

The user Name and password are owner level permissions and have access to everything in our Enterprise... so im confused.

AND confused why line 21 returns NONE

The reson I am going this route is I need to increase the token expiration time... not sure how to do it any other way... 

otherwise I would just do this

if portal_username == '' and portal_password == '':
    gis = GIS(profile='Survey123_prof')
else:
    gis = GIS(portal_url, portal_username, portal_password)
    
token = gis._con.token
item_object = gis.content.get(feature_layer_id)

 

ANY thoughts?

 

token_url = f"{portal_url}/sharing/rest/generateToken"
payload = {
    "username": portal_username,
    "password": portal_password,
    "client": "referer",
    "referer": portal_url,
    "expiration": expiration_minutes,
    "f": "json"
}

response = requests.post(token_url, data=payload)
token_data = response.json()
custom_token = token_data["token"]
print("custom token " + custom_token)

gis = GIS(url=portal_url, credentials={"token": custom_token})

print(f"Token successfully generated! Expires at timestamp: {token_data['expires']}")

tokenvalue = gis._con.token
print(tokenvalue)

item_object = gis.content.get(feature_layer_id)
print(item_object)

 

 

 

0 Kudos
12 Replies
kapalczynski
Frequent Contributor

definitely has to do with permissions...

The username and password credentials I am using.... I tool that user and added it to a group and assigned the group to that Service and still did not work... 

once I made public it worked...  not sure why it has to be public if I have it shared to the Organization and I have a group with that user in it... 

0 Kudos
CodyPatterson
MVP Regular Contributor

Hey @kapalczynski 

I think this may be the way you're adding the token in, from the documentation here:

https://developers.arcgis.com/python/latest/api-reference/arcgis.gis.toc.html

It's showing that the way to use the token is like this:

gis = GIS(url=portal_url, token="token_if_string")

Just make sure if it's just a plain copy paste string then to surround with quotes, otherwise calling the variable should work just fine with token=token_var etc.

Let me know if this ends up getting you farther!

Cody

0 Kudos
kapalczynski
Frequent Contributor

Yea I had that originally and it did not work... was getting errors... google suggested the way I am doing it now.

I am going to test again and see what error it is throwing... 

kapalczynski_0-1780359674724.png

 

0 Kudos
kapalczynski
Frequent Contributor

Line 14 prints the token I am receiving... 

Line 16 seems to fail : gis = GIS(url=portal_url, token=custom_token)

BUT you can see from the error that the correct token is being printed... its a valid token

custom token xQiM4Ft72qRDLEmW9BOTojBmvVMHp2YGEwBXTyIHrf3eYJLpV9NrTUV2y_XzKBdsRaiME2Rc5UUmnMQYW3dv-aTOBSmb_GdLWMyguTSZyfAMn1d-LayS1w......................................c1rulv6_dMf0XW4qhLi2g..
Traceback (most recent call last):
File "C:\Users\xyzx\Desktop\~GIS_projects\~xyzx\~AttachmentsNotVisible_Processing\script.py", line 72, in <module>
gis = GIS(url=portal_url, token=custom_token)
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\__init__.py", line 550, in __init__
self._portal.get_properties(force=force_refresh)
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\_impl\_portalpy.py", line 1227, in get_properties
raise e
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\_impl\_portalpy.py", line 1207, in get_properties
resp = self.con.post(path, self._postdata(), ssl=True)
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\_impl\_con\_connection.py", line 1079, in post
force_bytes=kwargs.pop("force_bytes", False),
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\_impl\_con\_connection.py", line 625, in _handle_response
self._handle_json_error(data["error"], errorcode)
File "C:\Program Files\ArcGIS\Pro\bin\Python\envs\arcgispro-py3\lib\site-packages\arcgis\gis\_impl\_con\_connection.py", line 648, in _handle_json_error
raise Exception(errormessage)
Exception: Invalid token.
(Error Code: 498) 

 

token_url = f"{portal_url}/sharing/rest/generateToken"
payload = {
    "username": portal_username,
    "password": portal_password,
    "client": "referer",
    "referer": portal_url,
    "expiration": expiration_minutes,
    "f": "json"
}

response = requests.post(token_url, data=payload)
token_data = response.json()
custom_token = token_data["token"]
print("custom token " + custom_token)

gis = GIS(url=portal_url, token=custom_token)

print(f"Token successfully generated! Expires at timestamp: {token_data['expires']}")

tokenvalue = gis._con.token
print(tokenvalue)

token = custom_token
print(tokenvalue)

item_object = gis.content.get(feature_layer_id)
print(item_object)

 

 

0 Kudos
kapalczynski
Frequent Contributor

This works but the token does not stay alive long enough for me to run the script... 

if portal_username == '' and portal_password == '':
gis = GIS(profile='Survey123_prof')
else:
gis = GIS(portal_url, portal_username, portal_password)

token = gis._con.token
item_object = gis.content.get(feature_layer_id)

print(token)
print(item_object)
0 Kudos
CodyPatterson
MVP Regular Contributor

Hey @kapalczynski 

I didn't end up seeing the reply where you mentioned that the token doesn't stay alive long enough my apologies.

You had send an older expiry time, this one here 1780364453189 and it shows that it should expire June 02 GMT so it should be well old enough. Still I'd check your max token lifetime in the portal admin, then Portals > Self, and check the maxTokenExpirationMinutes, maybe temporarily set to 10080 for 7 days or more, then Update Organization.

Along with this, inside of your code, if it's super long running, you may put a token refresh function in that just recalls a new token, and adds the newer token to the gis object.

Cody

0 Kudos
CodyPatterson
MVP Regular Contributor

Hey @kapalczynski 

So in this case, I'm wondering if it's binding the referrer token to a URL that you're not meaning to use or the code is misinterpreting.

I personally would do some debugging prints, and check to see if anything pops up that isn't intended:

print("Portal: ", portal_url)
print("Referer: ", payload.get("referer"))
print("GIS Referrer: ", getattr(gis, '_referer', 'Not set'))

 

Does your portal URL end with /portal or just https://<fqdn>.com/

Cody

0 Kudos
kapalczynski
Frequent Contributor

@CodyPatterson  OK I will do some of that debugging and see... 
My URL ends with /portal    https://xyzxyz.xyzx.xyzxyz.gov/portal

0 Kudos
kapalczynski
Frequent Contributor

 

Code and Return

 

token_url = f"{portal_url}/sharing/rest/generateToken"
payload = {
    "username": portal_username,
    "password": portal_password,
    "client": "referer",
    "referer": portal_url,
    "expiration": expiration_minutes,
    "f": "json"
}

response = requests.post(token_url, data=payload)
token_data = response.json()
custom_token = token_data["token"]

print("custom token " + custom_token)

#gis = GIS(url=portal_url, token=custom_token)
gis = GIS(url=portal_url, credentials={"token": custom_token})

print(f"Token successfully generated! Expires at timestamp: {token_data['expires']}")

print("Portal: ", portal_url)
print("Referer: ", payload.get("referer"))
print("GIS Referrer: ", getattr(gis, '_referer', 'Not set'))

tokenvalue = gis._con.token
print(tokenvalue)

token = custom_token
print(tokenvalue)

item_object = gis.content.get(feature_layer_id)
print(item_object)

 

This is the return

NOTE:  The Portal and Referer are the same below.  They are both returning the same URL for my Portal instance

custom token hyLT0vo4pfs2oA3dJjPRJwRvgX-91bWD6TvS1ZZ8mOgu8aykXrL8GdoRe85kpIOvAm0BxtfXP-8IVTnjwdRelX697mjRZwhW.....UGSR3bL6jZMecwiSJT19wK4EAyw..
Token successfully generated! Expires at timestamp: 1780515639263
Portal:  https://ggg.g.ggg.gov/portal
Referer:  https://ggg.g.ggg.gov/portal
GIS Referrer:  None
None
None
<Item title:"DEV" type:Feature Layer Collection owner:xyz.xy@xy.xyzx.gov>
starting


 

0 Kudos