Hello !
I am Working on a simple streamlit app where i would like to add a Google Authentication before the user acess the app.
can anyone help me for doing that ?
Thank you all
- Create a new project on the Google Cloud Console:
- Go to the Google Cloud Console.
- Create a new project or select an existing one.
- Enable the Google Sign-In API:
- In the Google Cloud Console, navigate to the âAPIs & Servicesâ > âLibraryâ section.
- Search for âGoogle Sign-In APIâ and enable it for your project.
- Configure the OAuth consent screen:
- In the Google Cloud Console, navigate to the âAPIs & Servicesâ > âOAuth consent screenâ section.
- Choose an âExternalâ user type and click âCreateâ.
- Provide a name for your application, enter the authorized domain (e.g.,
localhost
for local development), and add any additional required information. - Save the changes.
- Create OAuth credentials:
- In the Google Cloud Console, navigate to the âAPIs & Servicesâ > âCredentialsâ section.
- Click âCreate Credentialsâ and select âOAuth client IDâ.
- Choose âWeb applicationâ as the application type.
- Enter a name for the OAuth client ID.
- Add the authorized JavaScript origins (e.g.,
http://localhost:8501
for Streamlitâs default development server). - Add the authorized redirect URI (e.g.,
http://localhost:8501/
). - Click âCreateâ to generate the OAuth client ID and client secret.
- Install the required Python libraries:
- Open a terminal or command prompt and install the
google-auth
library usingpip
:
- Open a terminal or command prompt and install the
pip install google-auth
- Implement the Google Authentication in your Streamlit app:
- Import the necessary libraries in your Python script:
import streamlit as st
from google.oauth2 import id_token
from google.auth.transport import requests
- Add the authentication logic in your Streamlit app:
def main():
st.title("Your Streamlit App")
# Google Authentication
st.subheader("Google Authentication")
client_id = "YOUR_CLIENT_ID" # Replace with your OAuth client ID
token = st.text_input("Enter your Google ID token", type="password")
if st.button("Authenticate"):
try:
idinfo = id_token.verify_oauth2_token(token, requests.Request(), client_id)
if idinfo['aud'] != client_id:
raise ValueError("Invalid client ID")
st.success(f"Authentication successful: {idinfo['name']}")
# Continue with the rest of your app logic here
except ValueError as e:
st.error("Authentication failed")
st.error(e)
# Other app content
# ...
if __name__ == "__main__":
main()
- Replace
"YOUR_CLIENT_ID"
with your OAuth client ID obtained from the Google Cloud Console.
- Run your Streamlit app:
- Open a terminal or command prompt and navigate to the directory where your Python script is located.
- Run your Streamlit app using the following command:
streamlit run your_script.py
Hello @AdryanSerage, thank you for the reply !
While looking for âGoogle Sign-In APIâ, I found that itâs deprecated (I think) here is where iâve read that Link .
Is that correct ? and is it âCloud Identity APIâ now ?
If Yes, is there more steps or modifications that i have to do ?
Use that instead : Overview  | Authentication  | Google Developers
Ok !
So as I understood, now , there is no API service to enable ?
You could use this : Authorizing for Web  | Authorization  | Google Developers
and read that : Python quickstart  | People API  | Google Developers
Hello,
I donât know if you can help me more, but here what iâve done until now :
- I followed these steps. At the end i got a json file with (âclient_idâ, âproject_idâ,âauth_uriâ,âtoken_uriâ, âauth_provider_x509_cert_urlâ, âclient_secretâ, âredirect_urisâ).
- I Enabled " People API" and followed these instructions, so created âquickstart.py.pyâ where i referred (in this line
flow = InstalledAppFlow.from_client_secrets_file('secret.json', SCOPES)
to the json file a got earlier.
When i run this script, a webpage with âgoogle prompts authorize accessâ opened, with this error : âErreur 400 : redirect_uri_mismatchâ.
I need to implement this into a streamlit app, but I still have some logic issues to understand correctly the process.
You have the right logic, just you have to check the redirect_uri_mismatch
thatâs mean that you didnât input the right redirect URL in google auth.
@AdryanSerage Can you please explain, where do I get Google ID token?
Iâve completed all steps, and tried to get the token from: OAuth 2.0 Playground but app keeps throwing an error: Wrong number of segments in token
What Iâm missing?
I am a bit confused, in the âauthorized redirect URIâ section (on my Google cloud account), I have written :
Thatâs because I am running it locally, but I still have the same error.
I also donât know how to implement it into a streamlit app. Maybe only copy and paste this code part and put it beginning of the main.py file ?
Hello guys Iâm trying to do the same thing!
So good to find this thread.
I have one question though. Iâm trying to use Firebase. How can I add a Google login (the same as here using âlogin with Googleâ) in a way that creates a user in the Firebaseâs user base?
Thanks in advance!
Best.
To obtain a Google ID token, you need to follow the correct steps. The error message you mentioned, âWrong number of segments in token,â typically indicates an issue with the token format. Hereâs a step-by-step guide to obtaining a Google ID token:
- Go to the Google API Console.
- Create a new project or select an existing project from the dropdown menu at the top.
- Enable the necessary APIs for your project. For obtaining an ID token, youâll likely need to enable the âGoogle Sign-In APIâ or any other relevant APIs based on your requirements.
- Once the APIs are enabled, click on the âCredentialsâ tab in the left menu.
- On the Credentials page, click the âCreate credentialsâ button and select âOAuth client ID.â
- Choose the application type that suits your needs. If youâre running the OAuth flow on a web server, select âWeb application.â Fill in the necessary details such as the authorized JavaScript origins and redirect URIs. Ensure that the redirect URI is correctly specified and matches the location where your application will receive the token.
- After creating the OAuth client ID, you should see it listed on the Credentials page. Under the âOAuth 2.0 client IDsâ section, locate the client ID you just created.
- Copy the client ID and paste it into the OAuth 2.0 Playground (OAuth 2.0 Playground).
- In the OAuth 2.0 Playground, click on the âOAuth 2.0 Configurationâ button on the right side. Paste your client ID in the âOAuth Client IDâ field.
- Scroll down to the âStep 1: Select & authorize APIsâ section in the Playground. Choose the desired scopes and click the âAuthorize APIsâ button.
- Follow the prompts to sign in with your Google account and grant the necessary permissions.
- After authorization, the Playground will display various API endpoints. You can select the relevant endpoint you want to test.
- Finally, click on the âExchange authorization code for tokensâ button. This should generate an access token and a refresh token. The access token is what you typically use for authentication purposes.
If youâre running your application locally on http://localhost:8501/
or http://localhost/
, the redirect URIs you provided should be correct. However, there are a few additional steps you need to follow in order to integrate the Google ID token retrieval into your Streamlit app.
Hereâs a step-by-step guide on how to implement Google ID token retrieval in a Streamlit app:
- Make sure you have the necessary dependencies installed. You can use the
google-auth
library to handle the authentication process. Install it using the following command:
shellCopy code
pip install google-auth
- In your Streamlit appâs Python file (
main.py
), import the required libraries:
pythonCopy code
import streamlit as st
from google.oauth2 import id_token
from google.auth.transport import requests
- Create a function to handle the token retrieval. This function will take the authorization code and client ID as input and return the ID token:
pythonCopy code
def get_google_id_token(auth_code, client_id):
try:
token = id_token.fetch_id_token(requests.Request(), auth_code, client_id)
return token
except ValueError as e:
st.error(f"Error retrieving ID token: {e}")
- In your Streamlit appâs main code, add a button or a link for users to initiate the authentication process. When the user clicks the button or link, they will be redirected to the Google Sign-In page:
pythonCopy code
# Your Streamlit app code
st.write("Welcome to My App!")
if st.button("Sign in with Google"):
# Redirect the user to the Google Sign-In page
auth_url = "https://accounts.google.com/o/oauth2/auth"
client_id = "YOUR_CLIENT_ID" # Replace with your actual client ID
redirect_uri = "http://localhost:8501/" # Replace with your redirect URI
scope = "openid" # Replace with the desired scopes
state = "state123" # Replace with a unique state value
auth_endpoint = f"{auth_url}?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&state={state}"
st.markdown(f'<a href="{auth_endpoint}">Click here to sign in with Google</a>', unsafe_allow_html=True)
- Once the user completes the Google Sign-In flow and is redirected back to your appâs redirect URI (
http://localhost:8501/
), you need to handle the callback. You can add the following code snippet to the top of yourmain.py
file to handle the callback route:
pythonCopy code
import streamlit.ReportThread as ReportThread
from streamlit.server.Server import Server
# Handle OAuth2 callback route
AUTHORIZATION_CODE = "code"
REDIRECT_URI = "http://localhost:8501/" # Replace with your redirect URI
if st._is_running_with_streamlit:
ctx = ReportThread.get_report_ctx()
session_id = ctx.session_id
session_info = Server.get_current()._session_info_by_id[session_id]
if session_info.ws.request_info.request_line == "GET /":
auth_code = session_info.ws.request_info.query_params[AUTHORIZATION_CODE]
get_google_id_token(auth_code, "YOUR_CLIENT_ID") # Replace with your actual client ID
# Continue with the rest of your app's logic
Make sure to replace "YOUR_CLIENT_ID"
with your actual client ID obtained from the Google API Console.
To add Google login functionality to your Firebase project and create a user in Firebaseâs user base, you can follow these steps:
- Set up Firebase:
- Go to the Firebase Console and create a new project or select an existing project.
- Set up your project by following the instructions provided in the Firebase Console.
- Enable Google Sign-In in Firebase:
- In the Firebase Console, go to the âAuthenticationâ section.
- Select the âSign-in methodâ tab.
- Enable the âGoogleâ sign-in provider and click on it to configure it.
- Follow the instructions to provide the necessary information, such as the web client ID (which you can obtain from the Google API Console) and any additional settings you require.
- Add the necessary Firebase and Google client libraries:
- In your projectâs HTML file (or template), include the Firebase SDK and the Google Sign-In client library.
- For the Firebase SDK, add the following script tag:
htmlCopy code
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.8/firebase-auth.js"></script>
- For the Google Sign-In client library, add the following script tag:
htmlCopy code
<script src="https://accounts.google.com/gsi/client" async defer></script>
- Initialize Firebase and Google Sign-In:
- In your JavaScript code, initialize Firebase with your projectâs Firebase configuration. You can obtain the configuration object from the Firebase Console.
- Initialize the Google Sign-In client with your Google client ID:
javascriptCopy code
const auth = firebase.auth();
// Initialize Google Sign-In
const googleProvider = new firebase.auth.GoogleAuthProvider();
googleProvider.setCustomParameters({ prompt: 'select_account' });
// Configure sign-in with Google button
const googleSignInButton = document.getElementById('google-sign-in-button');
googleSignInButton.addEventListener('click', () => {
auth.signInWithPopup(googleProvider)
.then((result) => {
// Handle successful sign-in
const user = result.user;
// User is now signed in with Firebase and you can access the user object
})
.catch((error) => {
// Handle error
console.error(error);
});
});
- Add the Google Sign-In button to your HTML:
- In your HTML file, add a button or any desired element that will trigger the Google Sign-In flow.
- Assign it an ID, such as âgoogle-sign-in-buttonâ:
htmlCopy code
<button id="google-sign-in-button">Sign in with Google</button>
- Handle user creation in Firebase:
- After a successful sign-in, the
result.user
object will contain the user information, including the userâs unique identifier (uid
). - You can use this information to create or update a user in Firebaseâs user base, if needed.
With these steps, you can integrate Google Sign-In with Firebase and create a user in Firebaseâs user base when a user signs in with Google.
Hello!
Iâm working on Google Oauth authentication for a streamlit app, but the problem arises that both external and internal accounts are allowing login from any Google account and not just the emails listed as a test user. This issue is also discussed here Google Issue Tracker
Has anyone here ever gone through this?
hello @AdryanSerage, thank you for this step by step code.
I want to ask about the last step (to handle the callback route) :
I think that these imports are no longuer available in streamlit :
- import streamlit.ReportThread as ReportThread
- from streamlit.server.Server import Server
is there a n other way to handle the callback ?
Thank you !
Hey guys, I donât know if your already solve this problem but. I would like to give my contribution:
based on the preview comments and on this guide (Using OAuth 2.0 for Web Server Applications):
I created this simple code that works fine for me:
import os
import google_auth_oauthlib.flow
from googleapiclient.discovery import build
import streamlit as st
import webbrowser
redirect_uri = os.environ.get("REDIRECT_URI", "http://localhost:8501/")
def auth_flow():
st.write("Welcome to My App!")
auth_code = st.query_params.get("code")
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
"client_secret.json", # replace with you json credentials from your google auth app
scopes=["https://www.googleapis.com/auth/userinfo.email", "openid"],
redirect_uri=redirect_uri,
)
if auth_code:
flow.fetch_token(code=auth_code)
credentials = flow.credentials
st.write("Login Done")
user_info_service = build(
serviceName="oauth2",
version="v2",
credentials=credentials,
)
user_info = user_info_service.userinfo().get().execute()
assert user_info.get("email"), "Email not found in infos"
st.session_state["google_auth_code"] = auth_code
st.session_state["user_info"] = user_info
else:
if st.button("Sign in with Google"):
authorization_url, state = flow.authorization_url(
access_type="offline",
include_granted_scopes="true",
)
webbrowser.open_new_tab(authorization_url)
def main():
if "google_auth_code" not in st.session_state:
auth_flow()
if "google_auth_code" in st.session_state:
email = st.session_state["user_info"].get("email")
st.write(f"Hello {email}")
if __name__ == "__main__":
main()
Thanks for your solution! I tried implementing it, and it works!
but I have a concern; after I set the login, I want my usual flow or app to display.
I have a chart and a table to display in my app, but the whole view got shrunk from container width to reduced width.
Are there any best practices to follow to have your app flow work as usual after the authentication?
Hey,
I would create a function with the rest of your flow, and replace here:
if "google_auth_code" in st.session_state:
main_flow()
Thanks! I did exactly this, but even though I was using container_width = True
in my table and chart, the view changed to a reduced view towards the center of my screen.
I will check if the login buttons or the display logged in information changed that or not.