How to hit an API which is PingIdentity authenticated via Python requests?

Question:

I have this API, something like this:

https://baseurl.com/endpoint

It is a GET API endpoint and has PingIdentity’s OIDC + Auth2.0 authentication & authorization (enabled at KONG API GATEWAY level) mechanism.

The first time I hit this API via my browser, it redirects me to a sign-in page, which—on successful sign-in—successfully triggers this API and shows me the output JSON on the browser. For the next 1 hour, whenever I hit this API again, it doesn’t ask for a sign-in again. After that, I again have to sign in once.

Now, I need to hit this API via Python. The problem is, in response, it gives an HTML output, which is basically that sign-in page that the browser was redirecting me to.

Here is what I have tried:

I wrote this API using FastAPI in Python, and when I requested it on the browser, I recorded its headers in FastAPI via request.headers. Here is what the headers contained:

'host':
'keep-alive':
'connection':
'x-forwarded-for':
'x-forwarded-proto':
'x-forwarded-host':
'x-forwarded-port':
'x-forwarded-path':
'x-forwarded-prefix':
'x-real-ip':
'cache-control':
'sec-ch-ua':
'sec-ch-ua-mobile':
'sec-ch-ua-platform':
'upgrade-insecure-requests':
'user-agent':
'accept':
'sec-fetch-site':
'sec-fetch-mode':
'sec-fetch-user':
'sec-fetch-dest':
'referer':
'accept-encoding':
'accept-language':
'cookie': {contained my organization specific data, which I am sure are not essential}
'username':
'client_id':
'oidc-access-token': {it is a JWT token, which I have confirmed with my teammates, is the access token from PingIdentity}

However, when I set these same headers when using Python requests library to hit this same API, it is again returning me the HTML content of the sign-in page and is not giving me the result! I also tried copying headers from the NETWORKS tab in the Debugger tool in browser and setting those same parameters in my requests in python, but nothing works still!

Here is how I am hitting the API in python:

import requests
hit_my_api = requests.get("https://baseurl.com/endpoint", headers={<The ones I mentioned above>})

How to get around with this?

Asked By: raghavsikaria

||

Answers:

Option 1

You should add the JWT token to the Authorization header, as shown below (see here as well):

r = requests.get('<API_URL>', headers={'Authorization': 'access_token <MY_TOKEN>'})

EDIT

If the above doesn’t work, try this:

r = requests.get('<API_URL>', headers={ 'Authorization': 'Bearer <MY_TOKEN>'})

Option 2

Since your API supports authorization using cookies as well, you could use Session Objects, similar to this answer. The Session object allows you to persist cookies across all requests made from the Session instance. Related answers to this context can be found here, here, as well as here and here. Example:

import requests

url = 'http://127.0.0.1:8000/login'
url_protec = 'http://127.0.0.1:8000/protected'
data = {'username': 'john', 'password': '123'}

with requests.Session() as s:
    r = s.post(url, data=data)
    print(r.content)
    r = s.get(url_protec)
    print(r.content)

Answered By: Chris