Open gcassimi opened 1 year ago
Hi Mstaal,
Same here, I tried to make this work for hours now ...
I've register an application on Azure portal with :
I managed to have the login popup showing after clicking you button, going trough the oauth process (email + password) in that popup, but when it returns to my streamlit app (at http://localhost:8501/) the token is always None
.
Can you share some tips to sort this out ? My goal is to get access to O365 (python-O365) from within my streamlit app and read some emails and calendar events. Thanks !
import streamlit as st
from msal_streamlit_authentication import msal_authentication
tenant_id:str = "****"
client_id:str = "****"
client_secret:str = "****"
login_token = None
# Setup MSAL authentication
login_token = msal_authentication(
auth={
"clientId": client_id,
"authority": f"https://login.microsoftonline.com/{tenant_id}",
"redirectUri": "http://localhost:8501", # Modify this if your app's redirect URI is different
"postLogoutRedirectUri": "/" # Modify this if your app's post logout redirect URI is different
},
cache={
"cacheLocation": "sessionStorage",
"storeAuthStateInCookie": False
},
login_request={
"scopes": [f"{client_id}/.default"]
},
logout_request={}, # Modify this if you need to specify a logout request
login_button_text="Login", # Optional, defaults to "Login"
logout_button_text="Logout", # Optional, defaults to "Logout"
class_name="css_button_class_selector", # Optional, defaults to None. Corresponds to HTML class.
html_id="html_id_for_button", # Optional, defaults to None. Corresponds to HTML id.
key=1 # Optional if only a single instance is needed
)
print(login_token)
st.write("Recevied login token:", login_token)
Ok, I finally find the answer on st's forum : https://discuss.streamlit.io/t/adding-azure-active-directory-sign-in-sign-out-using-msal-python-handling-redirects/37032/9?u=lionpeloux
@lionpeloux : Yes, I have read many claim they need to register the app accordingly in AD. Does it all work now?
@gcassimi : Have you tried to see if this also resolves your issue? Or have you managed to get it to work?
Hi @mstaal, thanks for getting back to me.
Yes it is working now, since I've registered a SPA application in AAD according to the forum's thread I've pointed to.
However, it is not clear to me what should be in a standard MSAL acces_token. If I inspect what's in your login_token
I get :
{
"authority":"https://login.microsoftonline.com/1e71a412-cdf9-.../"
"uniqueId":"f809778d-598b-..."
"tenantId":"1e71a412-cdf9-f36df6e5c428"
"scopes":[...]
"account":{...}
"idToken":"eyJ0eXAiOiJKV1QiL..."
"idTokenClaims":{...}
"accessToken":"eyJ0eXAiOiJKV1QiLCJub..."
"fromCache":false
"expiresOn":"2023-06-28T10:20:45.000Z"
"correlationId":"ab4a1746-..."
"requestId":"2f5bd415-..."
"extExpiresOn":"2023-06-28T11:29:05.000Z"
"familyId":""
"tokenType":"Bearer"
"state":""
"cloudGraphHostName":""
"msGraphHost":""
"fromNativeBroker":false
}
My goal is to use streamlit
+ python-0365
to make an app that builds complex standardized emails.
python-0365
can work with a pre-existing token (see TokenBackend) but it is not clear to me in what shema/shape this token is expected.
It seems it is a python dict with not only the access_token
field but some more informations, scopes
for instance.
Also, can you expose the refresh_token
in your login_token
?
This is the token I got when I'm authenitifcating with the python-O365
console flow :
{
"token_type": "Bearer",
"scope": [
"profile",
"openid",
"email",
"https://graph.microsoft.com/Calendars.ReadWrite",
"https://graph.microsoft.com/Calendars.ReadWrite.Shared",
"https://graph.microsoft.com/Contacts.ReadWrite",
"https://graph.microsoft.com/Contacts.ReadWrite.Shared",
"https://graph.microsoft.com/Mail.ReadWrite",
"https://graph.microsoft.com/Mail.ReadWrite.Shared",
"https://graph.microsoft.com/Mail.Send",
"https://graph.microsoft.com/Mail.Send.Shared",
"https://graph.microsoft.com/User.Read"
],
"expires_in": 3724,
"ext_expires_in": 3724,
"access_token": "eyJ0eXAiOiJKV1...",
"refresh_token": "0.AS8AEqRxHvnN9k...",
"expires_at": 1687728646.671638
}
Ok, I finally made it by providing a token with an empty refresh token string :
token = {
"token_type": login_token["tokenType"],
"scope": login_token["scopes"],
"access_token": login_token["accessToken"],
"refresh_token": "", # requiered by python-O365
}
Hi @lionpeloux, Sorry for reaching back so late. I am glad that you got it to work! I have been a little busy. I am not sure if I can expose the refresh token, but I can look into it. I would imagine, though, that it is in a sense "outside the scope" of the MSAL library. The purpose of a refresh token is to securely allow for an OAuth 2 / Open ID Connect session to be kept alive, and MSAL should take care of that for itself. In other words, I do not think you would like to extend the refresh token to some external vendor.
From my point of view, the purpose of the token received to you as either a simple authentication mechanism for streamlit to "know who is logged in", or you can use it to pass the token over to (for instance) a backend of your choice that you tell to trust tokens issued by the token provider. Does that make sense?
I will look int the library you use. It looks interesting!
Hello! Great work with the lib, it is really helpful.
I am having some problems in the login function. It is not returning the correct token, and therefore not opening up my app. The logic I am using for storing the session state works, but for some reason after I go through the whole process of login the token is not returned.
Do you know what could be causing this issue?
This is the function I built:
def login(): if "logged_in" not in st.session_state: CLIENT_ID = os.getenv("CLIENT_ID") CLIENT_SECRET = os.getenv("CLIENT_SECRET") TENANT_ID = os.getenv("TENANT_ID")