Consider implementing additional options for login control and providing support for logging out
Opened this issue · 12 comments
Example case:
- Implementing idpHint login options to allow for better control of idp preferences.
- Providing an in-place logout function for a more seamless user experience.
I have already implemented these changes in my forked branch. If they are well-received, I would be happy to create a pull request to merge them into the upstream branch.
master...pragmatic-streamlit:streamlit-keycloak:feat/allow-logout
Great stuff, I would happily merge this in. For the logout functionality, we could also go all the way:
- use the keycloak-js createLogoutUrl method
- accept logoutOptions
- expose the logout_url in the keycloak dataclass on the python side
Hi, I can see that this feature is merged into the branch feature/logout, and we are working on something that highly depend on using additional login options (basically setting the idp hint option during login). Is it possible to get this functionality out as a beta package or something soon? Maybe even in the master branch?
Would providing the id token be enough for that? If so, I can merge that into master first.
I was looking at the logout functionality as well, but had some issues getting keycloak-js to generate working logout urls.
edit: and also the login_options of course
Merged the changes into master, should have done that earlier. I will look at the logout functionality soon.
Hi again, I'm trying to use the login_options but it doens't seem to work.
So this is the input to the streamlit keycloak login:
keycloak = login(
url=settings.url,
realm=settings.realm,
client_id=settings.client_id,
login_options={
"idpHint": settings.kc_idp_hint,
"loginHint": "myemail@gmail.com",
},
auto_refresh = True
)
I'm expecting the 'kc_idp_hint' query parameter to be provided with the login url to keycloak, including the login hint. However none of the parameters are provided in the login url. I've double checked the streamlit keycloak code and I cannot find the reason to the problem. Are you able to understand why it doesn't work?
Thanks a lot for your contributions.
Could you elaborate on how to log out?
I second the Logout question.
@CHerSun @michal-sensestreet
The following example demonstrates the login and logout of streamlit keycloak, the entire experience is very smooth.
import os
from urllib.parse import urlencode
import streamlit as st
from streamlit.runtime import Runtime
from streamlit.runtime.scriptrunner import get_script_run_ctx
from streamlit_keycloak import login
st.title("Streamlit Keycloak Login & Logout example")
def _get_session_id():
context = get_script_run_ctx()
if not context:
return
return context.session_id
def _get_current_request():
session_id = _get_session_id()
if not session_id:
return None
runtime = Runtime._instance
if not runtime:
return
client = runtime.get_client(session_id)
if not client:
return
return client.request
def get_web_origin():
request = _get_current_request()
return request.headers["Origin"] if request else os.getenv("WEB_BASE", "")
keycloak_endpoint = "https://example.com"
keycloak_realm = "example"
if not st.session_state.get("keycloak_user_info"):
keycloak = login(
url=keycloak_endpoint,
realm=keycloak_realm,
client_id="example_client",
init_options={"checkLoginIframe": False},
)
if keycloak.authenticated:
st.session_state.keycloak_id_token = keycloak.id_token
st.session_state.keycloak_user_info = keycloak.user_info
if st.session_state.get("keycloak_user_info"):
params = urlencode(
{
"post_logout_redirect_uri": get_web_origin(),
"id_token_hint": st.session_state.keycloak_id_token,
}
)
st.json(st.session_state.keycloak_user_info)
st.markdown(
f'Switch account by <a target="_self" href="{keycloak_endpoint}/realms/{keycloak_realm}/protocol/openid-connect/logout?{params}">Logout</a>',
unsafe_allow_html=True,
)
thanks @mapix , works like a charm.
@mapix thank you! Awesome, love the target="_self"
too to make everything work in the same tab.
Do you maybe know if it's possible to login using same tab only too? I.e. without popup on desktop browsers (mobile browsers seem to utilize same tab).
> if keycloak.authenticated:
> st.session_state.keycloak_id_token = keycloak.id_token
> st.session_state.keycloak_user_info = keycloak.user_info
>
Is it keycloak.id_token (or) keycloak.access_token?