
Security News
vlt Launches "reproduce": A New Tool Challenging the Limits of Package Provenance
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
streamlit-ldap-authenticator
Advanced tools
A fast and easy way to handle the user authentication using ldap in your Streamlit apps.
streamlit-ldap-authenticator
let you add login form and execute authentication before your streamlit page app started.
Open a terminal and run:
pip install streamlit-ldap-authenticator
Create a new file secrets.toml in .streamlit folder.
You can learn more about secrets management streamlit documentation.
Require Configuration
If your organization email address is "@example.com", most likely your configuration will be as below
[ldap]
server_path = "ldap://ldap.example.com"
domain = "example"
search_base = "dc=example,dc=com"
attributes = ["sAMAccountName", "distinguishedName", "userPrincipalName", "displayName", "manager", "title"]
use_ssl = true
[session_state_names]
user = "login_user"
remember_me = "login_remember_me"
[auth_cookie]
name = "login_cookie"
key = "{any password for encryption}"
expiry_days = 1
auto_renewal = true
delay_sec = 0.1
Create a new file simple_login.py with the following code:
import streamlit as st
from streamlit_ldap_authenticator import Authenticate
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie']
)
# Login Process
user = auth.login()
if user is not None:
auth.createLogoutForm({'message': f"Welcome {user['displayName']}"})
# Your page application can be written below
st.write("# Welcome to my App! 👋")
st.write(user)
Run the streamlit app!
streamlit run simple_login.py
This is recommended if you are using http protocol as http protocol doesn't encrypt when exchanging information between server and client. So anyone in the network can see the user password if it is not encrypted.
Create a new file generateKeys.py
from streamlit_rsa_auth_ui import Encryptor
encryptor = Encryptor.generateNew(2048)
encryptor.save('rsa', 'authkey')
Run generateKeys.py
python script
python generateKeys.py
this will create a private key and public key pair
authkey
authkey.pub
├── rsa
│ ├── authkey
│ │ authkey.pub
add to the secrets.toml
[encryptor]
folderPath = "rsa"
keyName = "authkey"
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie'],
st.secrets['encryptor']
)
Configuration for your organization active directory
Name | Type | Description |
---|---|---|
server_path | str | Active directory server path. E.g. 'ldap://ldap.example.com' |
domain | str | Your organization domain. E.g. 'Example' |
search_base | str | Active directory base search. E.g. 'dc=example, dc=com' |
attributes | List[str] | Attribute avaliable in your organization active directory. You can reference in ADExplorer |
use_ssl | bool | Determine whether to use basic SSL basic authentication |
Configuration for streamlit Session State key names
Name | Type | Description |
---|---|---|
user | str | Key name to store user information |
remember_me | str | Key name to store remember_me checkbox selection |
Configuration to store user information to the cookie in client's browser. Thus even when user close the browser and reload the page, Reauthorization is possible with cookie.
Name | Type | Description |
---|---|---|
name | str | cookie name to store in client's browser |
key | str | encryption key to encrypt user information |
expiry_days | float | expiry date for the cookie |
auto_renewal | bool | Cookie will expire after defined days from the last activity when value is True . Cookie will expire after defined days from the last login when value is False . |
delay_sec | float | Delay in sec after set or delete cookie |
Configuration for encryption key location to encrypt user information at the client browser before send back to server.
Name | Type | Description |
---|---|---|
folderPath | str | Folder location where the encryption key is stored. (Make sure the key location is private) |
keyName | str | The name of the key |
Name | Type | Description |
---|---|---|
text | str | None | Optional title text |
size | 'smaller' | 'small' | 'medium' | 'large' | 'extraLarge' | None | Optional title size |
align | 'left' | 'center' | 'right' | None | Optional text alignment |
args | dict | None | Optional additional title properties can be reference in Ant Design Title |
Name | Type | Description |
---|---|---|
required | bool | True if the item is required |
message | str | None | Optional error message if violate the required rule |
warningOnly | bool | None | Warning only if True and will not block the form submit |
Name | Type | Description |
---|---|---|
pattern | str | Regex pattern |
message | str | None | Optional error message if violate the pattern rule |
warningOnly | bool | None | Warning only if True and will not block the form submit |
Name | Type | Description |
---|---|---|
placeholder | str | None | Optional placeholder for text input |
label | str | None | Optional label will be display left of text input in wide screen size and top of text input in small screen size |
width | str | None | Optional width of the input Reference |
required | RequiredRule | bool | dict | None | Optional required rule |
patterns | List[PatternRule | str | dict] | None | Optional pattern rules |
args | dict | None | optional additional input properties can be reference in Ant Design Input |
Name | Type | Description |
---|---|---|
label | str | None | label will be display right of checkbox |
width | str | None | Optional width of the checkbox Reference |
required | RequiredRule | bool | dict | None | Optional required rule |
args | dict | None | optional additional input properties can be reference in Ant Design Checkbox |
Name | Type | Description |
---|---|---|
label | str | None | Optional button label |
width | str | None | Optional width of the button Reference |
args | dict | None | Optional additional button properties can be reference in Ant Design Button |
Name | Type | Description |
---|---|---|
formType | 'default' | 'inline' | None | Will be 'default' if None |
labelSpan | int | None | Label Layout |
wrapperSpan | int | None | Layout of the input control |
maxWidth | int | None | Max form width |
align | 'left' | 'center' | 'right' | None | Horizontal form alignment |
title | TitleConfig | str | dict | None | Config for title control of the form |
submit | ButtonConfig | str | dict | None | Config for submit button of the form |
username | TextInputConfig | str | dict | None | Config for username input of the form |
password | TextInputConfig | str | dict | None | Config for password input of the form |
remember | CheckboxConfig | str | dict | None | Config for remember checkbox of the form |
args | dict | None | Optional addtional form properties can be reference in Ant Design Form |
Name | Type | Description |
---|---|---|
formType | 'default' | 'inline' | None | Will be 'default' if None |
maxWidth | int | None | Max form width |
align | 'left' | 'center' | 'right' | None | Horizontal form alignment |
title | TitleConfig | str | dict | None | Config for title control of the form |
submit | ButtonConfig | str | dict | None | Config for submit button of the form |
args | dict | None | Optional addtional form properties can be reference in Ant Design Form |
Addtional task can be executed upon successful login or logout
Login Process is as follow
additionalCheck
argument functioncallback
argument functionLogout Process is as follow
When user click Sign out
button
callback
argument function. If 'cancel'
is return, will not continueCreate a new file simple_login_callback.py with the following code:
import streamlit as st
from streamlit_rsa_auth_ui import SignoutEvent
from streamlit_ldap_authenticator import Authenticate, UserInfos
from typing import Optional, Union, Literal
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie']
)
def login(user: Union[UserInfos, str]) -> Optional[str]:
st.session_state.TestSs = {"login_successful": True}
def logout(event: SignoutEvent) -> Optional[Literal['cancel']]:
if 'TestSs' in st.session_state:
del st.session_state.TestSs
if 'TestSs' in st.session_state:
return 'cancel'
# Login Process
user = auth.login(callback=login)
if user is not None:
auth.createLogoutForm({'message': f"Welcome {user['displayName']}"}, callback=logout)
# Your page application can be written below
st.write("# Welcome to my App! 👋")
st.write(user)
Create a new file title_login.py with the following code:
import streamlit as st
from streamlit_ldap_authenticator import Authenticate, Connection, UserInfos
from typing import Optional
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie']
)
def checkUserByTitle(conn: Optional[Connection], user: UserInfos):
title = "Engineer"
if user['title'].__contains__(title): return True
return f"You are not a {title}. Not authorize to use this page."
# Login Process
user = auth.login(checkUserByTitle)
if user is not None:
auth.createLogoutForm({'message':f"Welcome {user['displayName']}"})
# Your page application can be written below
st.write("# Welcome to my App! 👋")
st.write(user)
Now run it to open the app!
streamlit run title_login.py
Create a new file report_login.py with the following code:
import streamlit as st
from streamlit_ldap_authenticator import Authenticate, Connection, UserInfos
from typing import Optional
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie']
)
def __isReportTo(user: UserInfos, conn: Optional[Connection], email: str, max_level = 3, current_level = 1):
if current_level > max_level: return False
manager = user['manager']
if type(manager) is str and type(conn) is Connection:
manager = auth.ldap_auth.getInfoByDistinguishedName(conn, manager)
user['manager'] = manager
if type(manager) is not dict: return False
if manager['mail'] == email: return True
return __isReportTo(manager, conn, email, max_level, current_level + 1)
def checkUserInOrganization(conn: Optional[Connection], user: UserInfos):
email = 'vbalamurugan@illumina.com'
return True if __isReportTo(user, conn, email) else f'You are not reported to {email}. Not authorize to use this page.'
# Login Process
user = auth.login(checkUserInOrganization)
if user is not None:
auth.createLogoutForm({'message':f"Welcome {user['displayName']}"})
# Your page application can be written below
st.write("# Welcome to my App! 👋")
st.write(user)
Now run it to open the app!
streamlit run report_login.py
Create a new file list_login.py with the following code:
import streamlit as st
from streamlit_ldap_authenticator import Authenticate, Connection, UserInfos
from typing import Optional
# Declare the authentication object
auth = Authenticate(
st.secrets['ldap'],
st.secrets['session_state_names'],
st.secrets['auth_cookie']
)
def checkUserInList(conn: Optional[Connection], user: UserInfos):
allowUsers = [ "nchen1@illumina.com" ]
if user['userPrincipalName'] in allowUsers: return True
return f"You are not in the authorized list. Not allowed to use this page"
# Login Process
user = auth.login(checkUserInList)
if user is not None:
auth.createLogoutForm({'message':f"Welcome {user['displayName']}"})
# Your page application can be written below
st.write("# Welcome to my App! 👋")
st.write(user)
Now run it to open the app!
streamlit run list_login.py
True
LdapConfig
expiry_days
and delay_sec
is not parse correctly from secrets.toml in CookieConfig.FAQs
Authenticate using ldap
We found that streamlit-ldap-authenticator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
vlt's new "reproduce" tool verifies npm packages against their source code, outperforming traditional provenance adoption in the JavaScript ecosystem.
Research
Security News
Socket researchers uncovered a malicious PyPI package exploiting Deezer’s API to enable coordinated music piracy through API abuse and C2 server control.
Research
The Socket Research Team discovered a malicious npm package, '@ton-wallet/create', stealing cryptocurrency wallet keys from developers and users in the TON ecosystem.