I am trying to integrate SSO on streamlit app.
Packages -: google.oauth2, id_token ,google_auth_oauthlib.flow , Flow
how can we fetch token maintaining the session state (using gcp oauth as provider
)
To integrate Single Sign-On (SSO) with Google Cloud Platform (GCP) OAuth as the provider in your Streamlit app and fetch a token while maintaining the session state, you can follow these steps:
-
Install the necessary packages: Ensure that you have the required packages installed. You mentioned
google.oauth2
,id_token
,google_auth_oauthlib.flow
, andFlow
. Make sure you have them installed in your environment. -
Import the required modules: Import the necessary modules from the installed packages into your Streamlit app:
import streamlit as st
from google.oauth2 import id_token
from google_auth_oauthlib.flow import Flow
-
Configure the OAuth credentials: Create the OAuth client credentials for your application in the Google Cloud Console. Obtain the client ID and client secret, and store them securely. You can use Streamlit Secrets to manage and retrieve these credentials securely in your app.
-
Define the OAuth flow: Set up the OAuth flow in your Streamlit app, including the necessary scopes and redirect URL. Hereās an example:
# Set the client ID and client secret
client_id = st.secrets["client_id"]
client_secret = st.secrets["client_secret"]
# Define the scopes required for your app
scopes = ['openid', 'email', 'profile']
# Define the redirect URL after successful authentication
redirect_uri = 'http://localhost:8501/'
# Create the OAuth flow instance
flow = Flow.from_client_secrets_file(
'client_secret.json',
scopes=scopes,
redirect_uri=redirect_uri
)
Make sure to update "client_id"
, "client_secret"
, and the redirect URI with the appropriate values.
- Implement the authentication flow: In your Streamlit app, create a login button or a specific route where the user can initiate the authentication flow. Hereās an example:
if 'credentials' not in st.session_state:
st.session_state.credentials = None
if st.button('Login'):
authorization_url, state = flow.authorization_url(prompt='consent')
# Store the state in session state
st.session_state.state = state
# Redirect the user to the authorization URL
st.redirect(authorization_url)
- Handle the callback route: Set up a route or callback to handle the authentication callback from Google. Hereās an example:
if 'code' in st.session_state and 'state' in st.session_state:
flow.fetch_token(authorization_response=st.session_state.code)
# Verify the state to prevent CSRF attacks
assert st.session_state.state == st.session_state.token_response.get('state')
# Store the credentials in session state
st.session_state.credentials = flow.credentials
st.write('Successfully authenticated!')
Make sure to update the appropriate code to handle the authentication callback route.
- Access the token: Once the user is authenticated and the credentials are stored in the session state, you can access the token for API calls. Hereās an example:
if st.session_state.credentials:
token = st.session_state.credentials.token
# Use the token for API calls or other purposes
st.write('Access Token:', token)
Remember to handle any necessary error cases, edge cases, and secure token handling based on your specific requirements.
By following these steps, you should be able to integrate SSO with GCP OAuth as the provider in your Streamlit app and fetch a token while maintaining the session state.
Hi there. I am attempting to do a similar thing using Microsoft MSAL for python. Is there any way to follow a similar procedure to have a single sign on based authentication? I have already created something that did work using the device flow method of authentication but that requires a new page to open and can be tedious to have users enter the code and even deal with MFA. I would prefer if they could simply press one button and sign in if they are already signed into the same Active Directory elsewhere. I also need this to persist across pages but I think ive already got a system that should work and maintain states between pages.
i am also looking for multiple page solution and also a solution for when we are redirected from one streamlit app to another using URL from first app it should check the SSO token before redirecting , because i have multiple apps in one app structure.
Iāve been trying to use your solution, however, am receiving āError 400: redirect_uri_mismatchā as an error when trying to authenticate. Iāve triple checked that the redirect_uri in my script and GCP are the same, so Iām not sure why Iām getting this error.
Right now I have the redirect_uri set to the url of my app. Is this correct?
Did anyone got the proper solution to this? Adding SSO in multipage streamlit app
Hello Feromond,
I am facing an issue with MSAL authentication. It automatically opens a browser in server side where application hosted instead of client side. I am not sure whatās going here. Can you please give me an idea of how to resolve this issue?
To give you more context,
Following is a code for authenticating an user. THis code is placed under app.py in server. When user open thier browser and try to signup, user dont see authentication tab render in thier browser but instead it see browser on server side renders it.
Can you please help me with weird issue?
def authenticate_user():
"""
This function is used to authenticate application(python service). This function is used for Application Only authentiation workflow to get acccess token.
"""
try:
if 'access_token' not in st.session_state:
credential = InteractiveBrowserCredential(client_id=credentials['CLINETID'],
client_credential=credentials['CLIENTSECERET'],
tenant_id=credentials['TENANTID'])
access_token = credential.get_token(*credentials['SCOPES']).token
st.session_state["authentication_status"] = True
st.session_state['access_token'] = access_token
st.session_state['user_info'] = get_user()
st.rerun()
except Exception as ex:
logger.exception("Excecption occured in authenticate_user() --> app.py ")
st.error(ex)
That is expected. Code running in a computer cannot open a browser in another computer.
Can you give a hint of how to resolve this error?
I donāt think there is a way to use InteractiveBrowserCredential
un a server application. You probably need to use javascript and the components API.