Accessing Azure User Credentials (using "/.auth/me") in Azure App Services using Streamlit

Hi, I have successfully deployed my app using Azure Web App, linked to a Azure DevOps git repo.

I have also added authentication using Microsoft Authentication Entra ID.

However, I would like to access the user_id.

According to this stackoverflow reply, I should be able to

However, how can I achieve this on streamlit?

My current code is something like this:


import streamlit.components.v1 as components

def get_auth_script():
    script = """
<script>
(async () => {
    try {
        const response = await fetch('/.auth/me');
        if (response.ok) {
            const authDetails = await response.json();
            if (authDetails && authDetails[0] && authDetails[0].user_id) {
                const userId = authDetails[0].user_id;
                window.parent.postMessage({ userId: userId, data: authDetails }, "*");
            } else {
                window.parent.postMessage({ error: 'No user_id found' }, "*");
            }
        } else {
            window.parent.postMessage({ error: 'Failed to fetch auth details' }, "*");
        }
    } catch (error) {
        window.parent.postMessage({ error: error.message }, "*");
    }
})();
</script>
    """
    return script


# Embed the script to fetch auth details
auth_script = get_auth_script()
components.html(auth_script, height=0, width=0)

# JavaScript to listen for window messages and send the data back to Streamlit
js_listen_script = """
<script>
window.user_data = null; // Initialize global variable
window.addEventListener("message", (event) => {
    const { userId, error, data } = event.data;
    if (userId) {
        window.user_data = {"user_id": userId, "error": "", "data": data};
        console.log(user_data);
    } else if (error) {
        window.user_data = {"user_id": null, "error": error, "data": null};
        console.log(user_data);
    }
}, false);
</script>
"""
components.html(js_listen_script, height=0, width=0)

user_id_placeholder = st.empty()


from streamlit_javascript import st_javascript
import random
import time
while True:
    user_data = st_javascript("parent.window.user_data", key=random.random())
    st.write(user_data)
    if user_data:
        break
    time.sleep(1)
if user_data.get("user_id"):
    user_id_placeholder.write(user_data.get("user_id"))
    user_id_placeholder.write("User data:",user_data)
elif user_data.get("error"):
    user_id_placeholder.error(user_data.get("user_id"))

But it’s not getting it right

Fixed. The issue is that components are in iframes, so need to call its parent.

Working code:

import streamlit as st
import streamlit.components.v1 as components
import time
import json

def get_auth_script():
    script = """
    <script>
    console.log("Auth Outside");
    (async () => {
        try {
            console.log("Auth inside");
            const response = await fetch('/.auth/me');
            if (response.ok) {
                const authDetails = await response.json();
                if (authDetails && authDetails[0] && authDetails[0].user_id) {
                    const userId = authDetails[0].user_id;
                    window.parent.postMessage({userId: userId, data: authDetails}, "*");
                } else {
                    window.parent.postMessage({error: 'No user_id found'}, "*");
                }
            } else {
                window.parent.postMessage({error: 'Failed to fetch auth details'}, "*");
            }
        } catch (error) {
            window.parent.postMessage({error: error.message}, "*");
        }
    })();
    </script>
    """
    return script

auth_script = get_auth_script()
# st.markdown(auth_script, unsafe_allow_html=True)
components.html(auth_script, height=0, width=0)

js_listen_script = """
<script>
console.log("Listen Outside");
parent.window.user_data = null;

parent.window.addEventListener("message", (event) => {
    console.log("Received message:", event.data);
    const {userId, error, data} = event.data;
    if (userId) {
        console.log("Listen inside if");
        parent.window.user_data = {"user_id": userId, "error": "", "data": data};
        console.log(parent.window.user_data);
    } else if (error) {
        console.log("Listen inside else");
        parent.window.user_data = {"user_id": null, "error": error, "data": null};
        console.log(parent.window.user_data);
    }
}, false);
</script>
"""
components.html(js_listen_script, height=0, width=0)

user_id_placeholder = st.empty()

from streamlit_javascript import st_javascript

user_data = None

with st.empty():
    for attempt in range(10):
        user_data_json = st_javascript(f"JSON.stringify(parent.window.user_data)", key=f"js_script_{attempt}")
        if user_data_json:
            user_data = json.loads(user_data_json)
            break
        time.sleep(1)

if user_data and user_data.get("user_id"):
    user_id_placeholder.write(("User data:", user_data))
elif user_data and "error" in user_data:
    user_id_placeholder.error(user_data.get("error"))
else:
    st.error("Unable to retrieve user data.")

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