How to extract headers in streamlit app

We have a portal where we are using streamlit embedded in iframe to display some charts, dashboards etc…, also we have Nginx configured to route this iframe request to streamlit. For authentication & authorisation of streamlit app we decided to use session id(created and stored in cookies when user login to our portal) which is passed through header from our portal frontend. How can I extract this header in streamlit app so that I can authenticate or authorise the requests

I referred few github issues but seems like they are outdated for my streamlit version == 1.13.0

It would be really helpful if some one guides me here

3 Likes

Sorry this is a side question - but can you tell me why you’re embedding? Also are you embedding a Streamlit Cloud deployed app or one you’ve deployed yourself? We’re looking into how to support embedding better, and I’d love to know more about your use case!

1 Like

We have deployed streamlit app by ourselves.

Our use case is, we have a platform which helps ecommerce store owners in increasing their sales. We have built tables and charts of number of orders, abandoned checkouts etc… that can have dynamic filters. So whenever store owner log in to our portal they can use this tables and charts to know more about their store performance.

So we built this entire analytics part in streamlit and embedded this in iframe on UI

2 Likes

Hi @Swastik_K :wave:

We have a new “internal” (i.e.: subject to change without deprecation!) API to access a copy of the headers from the current session’s incoming WebSocket request.:

import streamlit as st
from streamlit.web.server.websocket_headers import _get_websocket_headers

headers = _get_websocket_headers()
access_token = headers.get("X-Access-Token")
if access_token is not None:
  # authenticate the user or whatever
  ...

Please take a look at the following pull request to learn how to update your code:

2 Likes

thank you @snehankekre for the help, will try this

1 Like

hey @snehankekre I couldn’t find websocket_headers.py under /streamlit/web/server/ package. I’ve installed streamlit using

pip3 install streamlit==1.13.0

This api not available in 1.13.0 version?.

Is there any other way to get headers?

The fix was created after the 1.13.0 release. You will have to either wait for the next release on the 27th or try to see if the fix is available in streamlit-nightly.

The last option is to try workarounds described in this GitHub issue:

But I would wait for the next release or check streamlit-nightly.

1 Like

Will wait till next release :smiley:. Thank you

1 Like

Is this little hack useful?

1 Like

Hi all,

I’m currently facing some issue with accessing custom request headers and not able to get logged-in user details in my streamlit app which I need further to implement role-based access for the user. I’m using streamlit==1.20.0 and my virtualhost config to host the app on the portal looks like below. Can someone please help? Thanks in advance!

HI there,

locally this approach works for me and the header is read correctly, but on a deployed app (in streamlit cloud), the header is not read by streamlit and shows

I think I have to add the websocket stuff to the requirements.txt but I do not know how.
Any ideas?

In the meantime we managed to get the _get_websocket_headers() working. We can extract and dispay the received HTTP headers. But we face the problem that a local installation receives our custom http header (X-Access-Token) but if the the app is deployed on streamlit community cloud then the header is not included in the http headers. Does streamlit community cloud somehow filter the transmitted headers? Can we add a configuration for farwarding all headers ?

I don’t understand why you would recommend a hack that may be removed in the next release.

I think it is a very important feature. I am sad that Streamlit is not prioritizing such an important feature.

2 Likes

Gist showing how to use the unspported _get_websocket_headers, just in case if anyone interested

1 Like

Hey - for anyone else looking in the future, here is an example of extracting the users email address from the headers that aws cognito gives you;

from streamlit.web.server.websocket_headers import _get_websocket_headers
import jwt
def process_session_token():
    '''
    WARNING: We use unsupported features of Streamlit
             However, this is quite fast and works well with
             the latest version of Streamlit (1.27)
             Also, this does not verify the session token's
             authenticity. It only decodes the token.
    '''
    headers = _get_websocket_headers()
    if not headers or "X-Amzn-Oidc-Data" not in headers:
        return {}
    return jwt.decode(
        headers["X-Amzn-Oidc-Data"], algorithms=["ES256"], options={"verify_signature": False}
    )

session_token = process_session_token()
st.write('Welcome: ', session_token['email'])

The discussion and code snippets posted here was very helpful for me, so I hope this is helpful to someone else in the future =)

2 Likes

Please please please make this part of the public API :pray::pleading_face:

Getting the request headers is such an essential thing, that I’m actually really surprised that this is not part of the public API yet. It basically prevents a streamlit app to be deployed behind an authentication proxy (such as oauth2-proxy).

4 Likes

I don’t know why Streamlit Cloud filter all headers from request, a wise way is to just remove the ones that are considered sensitive to them.

I try to build a demo of authentication which works well locally, but it fails on Streamlit Cloud due to

  1. Headers are not passed down.
  2. Cannot open login url due to github.com refuse to connect error.

For anyone who stumbles across this, v1.37.0 introduces st.context.header so no need for this workaround any longer! Thank you Streamlit Team! :heart:

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.