DOI-BLM / requests-arcgis-auth

Authentication handler for using Esri ArcGIS for Server and Portal (ArcGIS Online) Token Authentication with Python Requests
22 stars 1 forks source link

Cannot obtain an access_token a second time (no refresh_token is available) for Portal SAML Auth #16

Open pfoppe opened 7 years ago

pfoppe commented 7 years ago

On the first request to a portal with SAML Authentication, it receives a response with a refresh_token and an access_token. This is stored in the self._token_data field.

When the access token is expired, the code will use the refresh_token to obtain a new access_token. The response does not provide a new refresh_token and the original refresh_token is lost. The code cannot acquire a second access_token.

# Setup auth handler to capture the request history...  make a request and re-set the expiration to force it to make a request to generate a new access_token
s.auth = ArcGISPortalSAMLAuth(client_id,verify=False,capture_request_history = True)
r = s.get(r'https://ORG.maps.arcgis.com/sharing/rest/portals/self?f=json')
s.auth._token_data['expires_in'] = 1
r = s.get(r'https://ORG.maps.arcgis.com/sharing/rest/portals/self?f=json')

# Check the request history to confirm we are requesting a new access_token the way the article describes
s.auth.history[-1].request.url
'https://ORG.maps.arcgis.com/sharing/rest/oauth2/token'
s.auth.history[-1].request.headers
{'Content-Length': '558', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.13.0', '
Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded'}
s.auth.history[-1].request.body
'grant_type=refresh_token&refresh_token=<OBSCURED>&client_id=123456789'

# Token data does not have a new refresh token
s.auth._token_data
{u'access_token': u'<OBSCURED>', u'username': u'username@email_ORG', u'expires_in': 1800}

# Attempting to acquire a new access_token fails since the refresh_token was lost.  
s.auth._token_data['expires_in'] = 1
r = s.get(r'https://ORG.maps.arcgis.com/sharing/rest/portals/self?f=json')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\tmp\_PYTHON\virtual_envs\blmpydev2\lib\site-packages\requests\sessions.py", line 501, in get
    return self.request('GET', url, **kwargs)
  File "C:\tmp\_PYTHON\virtual_envs\blmpydev2\lib\site-packages\requests\sessions.py", line 474, in request
    prep = self.prepare_request(req)
  File "C:\tmp\_PYTHON\virtual_envs\blmpydev2\lib\site-packages\requests\sessions.py", line 407, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "C:\tmp\_PYTHON\virtual_envs\blmpydev2\lib\site-packages\requests\models.py", line 306, in prepare
    self.prepare_auth(auth, url)
  File "C:\tmp\_PYTHON\virtual_envs\blmpydev2\lib\site-packages\requests\models.py", line 543, in prepare_auth
    r = auth(self)
  File "requests_arcgis_auth\arcgis_saml_auth.py", line 73, in __call__
    return self._add_token_to_request(prepared_request)
  File "requests_arcgis_auth\arcgis_saml_auth.py", line 265, in _add_token_to_request
    raise TokenAuthenticationWarning("Unable to add the access_token to the request;")
requests_arcgis_auth.arcgis_exceptions.TokenAuthenticationWarning: Unable to add the access_token to the request;

The vendor doc (http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Authentication/02r30000009z000000/) states:

You can exchange a valid refresh_token for an access_token using the same /token endpoint​ ​...​ It yields the same response, returning a fresh access_token and refresh_token that can be subsequently used. If the refresh_token has expired, it will result in an error response and the app will be required to prompt the user to log in again.

pfoppe commented 3 years ago

Issue is still there. New Vendor Doc Link - https://developers.arcgis.com/rest/users-groups-and-items/authentication.htm From the vendor doc -

you can exchange a valid refresh_token for an access_token using the same /token endpoint ... It yields the same response, returning a fresh access_token and refresh_token that can be subsequently used

Test today showed the token was not returned: image