Summary
I’m trying to enable authentication to my app via OneLogin. I have my client_id, client_secret, etc and can programmatically get a token, but in the app It never progresses beyond showing the login screen. I realize this is ugly, and incomplete - but I’ve tried several things and this is just what I have at the moment.
Steps to reproduce
Code snippet:
import streamlit as st
import requests
from urllib.parse import urlparse, parse_qs, quote
authorization_base_url = 'https://mydomain.onelogin.com/oidc/2/auth'
token_url = 'https://mydomain.onelogin.com/oidc/2/token'
scope = 'openid email name groups profile'
client_id = 'my_redacted_client_id'
client_secret = 'my_redacted_client_secret'
redirect_uri = 'https://myapp.mydomain.com'
class LoginHandler:
def __init__(self, client_id, client_secret, redirect_uri, scope):
self.client_id = client_id
self.client_secret = client_secret
self.redirect_uri = redirect_uri
self.scope = scope
def get_authorization_url(self):
params = {
'response_type': 'code',
'client_id': self.client_id,
'redirect_uri': self.redirect_uri,
'scope': self.scope,
}
auth_url = f"{authorization_base_url}?{'&'.join([f'{k}={quote(str(v))}' for k, v in params.items()])}"
return auth_url
def authenticate_user(self, code):
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
data = {
'grant_type': 'authorization_code',
'code': code,
'client_id': self.client_id,
'client_secret': self.client_secret,
'redirect_uri': self.redirect_uri,
'scope': self.scope,
}
response = requests.post(token_url, headers=headers, data=data, verify=False)
st.write(response.json()) # Add this line to print out the response
if response.status_code == 200:
return response.json()
else:
return None
handler = LoginHandler(client_id, client_secret, redirect_uri, scope)
st.write('Click below to log in')
if st.button('Login'):
auth_url = handler.get_authorization_url()
st.write('Opening authentication URL:', auth_url)
st.experimental_set_query_params(request_uri=auth_url)
st.stop()
if 'request_uri' in st.experimental_get_query_params():
parsed_url = urlparse(st.experimental_get_query_params()['request_uri'][0])
query_params = parse_qs(parsed_url.query)
if 'code' in query_params:
code = query_params['code'][0]
st.write('Received code:', code)
tokens = handler.authenticate_user(code)
st.write('Response:', tokens)
if tokens:
st.write('Authentication successful!')
st.write(tokens)
else:
st.write('Authentication failed.')
else:
st.write('Authentication failed: Code not found in query parameters.')
If applicable, please provide the steps we should take to reproduce the error or specified behavior.
Expected behavior:
User clicks ‘login’ and is authenticated and the app is run
Actual behavior:
The page just reloads in a new tab, with login displayed
Debug info
- Streamlit version: 1.9.2
- Python version: 3.10.6
- OS version: Ubuntu 22.04 LTS
- Browser version: Chrome 112.0.5615.137
Additional information
The app is behind nginx where I’m terminating SSL and forwarding to myapp:8501
When I load this app, I’m presented with a ‘login’ button. When that button is clicked, the generated AUTH URL is displayed. When that link is clicked, a new browser window opens (with the address containing the returned ‘code’ from OneLogin) but the page just has the login button again instead of either the authentication success/fail message.
Ideally, I’d like a button that, when clicked, sends all the correct queries to OneLogin, gets the token/auth’s my user and then displays the actual app. Any help greatly appreciated.