st.login, st.logout y st.experimental_user para autenticación nativa

Intermedio
Streamlit
Streamlit
Actualizado: 05/05/2026

Autenticación nativa en Streamlit 1.41+

Desde Streamlit 1.41, la plataforma incluye soporte nativo de autenticación OAuth sin necesidad de librerías externas como streamlit-authenticator. Los componentes principales son:

  • st.login(provider) - botón/flujo de inicio de sesión con un proveedor OAuth
  • st.logout() - cierra la sesión del usuario actual
  • st.experimental_user - objeto con los datos del usuario autenticado
sequenceDiagram
    participant U as Usuario
    participant App as App Streamlit
    participant Auth as Provider OAuth Google GitHub
    participant Cookie as Cookie firmada
    U->>App: Visita página protegida
    App->>App: st.experimental_user.is_logged_in?
    alt No autenticado
        App->>U: Muestra st.login provider
        U->>Auth: Autoriza con credenciales
        Auth->>App: redirect_uri con token
        App->>Cookie: Crea cookie firmada
        Cookie->>U: Guarda en navegador
    else Autenticado
        App->>U: Sirve contenido protegido
        U->>App: Click st.logout
        App->>Cookie: Elimina cookie
    end
    Note over App,Cookie: cookie_secret en secrets.toml

Configurar el proveedor OAuth en secrets.toml

Antes de usar st.login, configura las credenciales del proveedor en .streamlit/secrets.toml:

# .streamlit/secrets.toml

[auth]
redirect_uri = "http://localhost:8501/oauth2callback"
cookie_secret = "una_clave_secreta_larga_y_aleatoria_min_32_chars"

[auth.google]
client_id = "TU_CLIENT_ID.apps.googleusercontent.com"
client_secret = "TU_CLIENT_SECRET"
server_metadata_url = "https://accounts.google.com/.well-known/openid-configuration"

[auth.github]
client_id = "TU_GITHUB_CLIENT_ID"
client_secret = "TU_GITHUB_CLIENT_SECRET"
server_metadata_url = "https://token.actions.githubusercontent.com/.well-known/openid-configuration"

En Streamlit Community Cloud, estos secretos se añaden en el panel Secrets del proyecto (ver tutorial de despliegue).

st.login: botón de inicio de sesión

import streamlit as st

st.title("Bienvenido a la aplicación")

if not st.experimental_user.is_logged_in:
    st.info("Inicia sesión para acceder al contenido.")

    col1, col2 = st.columns(2)
    with col1:
        if st.button("Entrar con Google", icon="🔑", type="primary"):
            st.login("google")
    with col2:
        if st.button("Entrar con GitHub", icon="🐙"):
            st.login("github")
else:
    st.success(f"¡Hola, {st.experimental_user.name}!")

También puedes llamar a st.login() directamente sin botón para redirigir de inmediato al proveedor:

import streamlit as st

if not st.experimental_user.is_logged_in:
    st.login("google")  # Redirige automáticamente al flujo OAuth de Google

st.experimental_user: datos del usuario autenticado

Una vez autenticado, st.experimental_user expone los atributos del usuario devueltos por el proveedor:

import streamlit as st

usuario = st.experimental_user

if usuario.is_logged_in:
    col_avatar, col_info = st.columns([1, 4])

    with col_avatar:
        if usuario.picture:
            st.image(usuario.picture, width=80)

    with col_info:
        st.subheader(usuario.name or "Usuario")
        st.caption(usuario.email or "Sin email")

    st.write("**Datos del proveedor OAuth:**")
    st.json({
        "name": usuario.name,
        "email": usuario.email,
        "email_verified": usuario.email_verified,
        "picture": usuario.picture,
        "sub": usuario.sub,  # Identificador único del proveedor
    })

Atributos estándar de st.experimental_user:

| Atributo | Descripción | |----------|-------------| | is_logged_in | True si el usuario está autenticado | | name | Nombre completo del usuario | | email | Dirección de correo | | email_verified | Si el email fue verificado por el proveedor | | picture | URL del avatar del usuario | | sub | ID único del usuario en el proveedor OAuth |

st.logout: cerrar sesión

import streamlit as st

if st.experimental_user.is_logged_in:
    st.write(f"Sesión activa: **{st.experimental_user.email}**")

    if st.button("Cerrar sesión", icon="🚪"):
        st.logout()

st.logout() invalida la sesión y redirige al usuario a la página de inicio de la aplicación.

Proteger páginas completas con guard pattern

El patrón habitual es verificar is_logged_in al inicio de cada página protegida:

# pages/dashboard.py
import streamlit as st

# Guard de autenticación
if not st.experimental_user.is_logged_in:
    st.warning("Debes iniciar sesión para acceder a esta página.")
    if st.button("Iniciar sesión"):
        st.login("google")
    st.stop()  # Detener la ejecución del resto de la página

# Contenido protegido
st.title("📊 Dashboard privado")
st.write(f"Bienvenido, {st.experimental_user.name}")

Integración con st.navigation

# app.py
import streamlit as st

login_page = st.Page("pages/login.py", title="Iniciar sesión", icon="🔑")
inicio = st.Page("pages/inicio.py", title="Inicio", icon="🏠", default=True)
dashboard = st.Page("pages/dashboard.py", title="Dashboard", icon="📊")
perfil = st.Page("pages/perfil.py", title="Mi perfil", icon="👤")
admin = st.Page("pages/admin.py", title="Admin", icon="🔧")

# Controlar qué páginas son visibles según el estado de autenticación
if not st.experimental_user.is_logged_in:
    pg = st.navigation([login_page])
elif st.experimental_user.email in ["admin@empresa.com", "cto@empresa.com"]:
    # Usuarios administradores: acceso completo
    pg = st.navigation({
        "Principal": [inicio, dashboard],
        "Cuenta": [perfil],
        "Sistema": [admin]
    })
else:
    # Usuarios estándar: sin acceso a admin
    pg = st.navigation({
        "Principal": [inicio, dashboard],
        "Cuenta": [perfil]
    })

pg.run()
# pages/login.py
import streamlit as st

st.title("🔑 Acceso a la aplicación")
st.write("Inicia sesión con tu cuenta corporativa para continuar.")

if st.button("Entrar con Google", type="primary", use_container_width=True):
    st.login("google")

Aplicación completa con autenticación OAuth

# app.py
import streamlit as st

st.set_page_config(page_title="Mi App Segura", page_icon="🔐", layout="wide")

# Definir páginas
login_page = st.Page("pages/login.py", title="Inicio de sesión", icon="🔑")
home = st.Page("pages/home.py", title="Inicio", icon="🏠", default=True)
analytics = st.Page("pages/analytics.py", title="Analítica", icon="📈")
settings = st.Page("pages/settings.py", title="Ajustes", icon="⚙️")

# Navegación condicional
if st.experimental_user.is_logged_in:
    with st.sidebar:
        st.image(st.experimental_user.picture or "https://via.placeholder.com/50", width=50)
        st.caption(st.experimental_user.email)
        if st.button("Cerrar sesión", icon="🚪"):
            st.logout()

    pg = st.navigation({
        "Aplicación": [home, analytics],
        "Sistema": [settings]
    })
else:
    pg = st.navigation([login_page])

pg.run()
# pages/home.py
import streamlit as st

if not st.experimental_user.is_logged_in:
    st.switch_page("pages/login.py")

st.title(f"Hola, {st.experimental_user.name} 👋")
st.write("Selecciona una sección en el menú lateral para comenzar.")

col1, col2 = st.columns(2)
with col1:
    with st.container(border=True):
        st.metric("Sesiones hoy", "1.204", "+12%")
with col2:
    with st.container(border=True):
        st.metric("Usuarios activos", "342", "+5%")

Contexto: el antes y el después de la autenticación nativa

Durante años, la forma habitual de añadir autenticación a una app Streamlit fue integrar streamlit-authenticator, una biblioteca de terceros que gestionaba usuarios, hashes de contraseñas y cookies de sesión. Ese enfoque funcionaba, pero tenía varios inconvenientes: había que mantener una base de datos propia de usuarios, gestionar el hashing de contraseñas manualmente y confiar en una dependencia no oficial para un aspecto crítico como la seguridad.

Desde Streamlit 1.41, el equipo oficial proporciona st.login y st.logout como primitivas nativas integradas con el framework OAuth 2.0 / OpenID Connect. Esto permite delegar la autenticación a proveedores establecidos (Google, GitHub, Microsoft, Auth0...) sin necesidad de gestionar contraseñas. La ventaja es doble: menos código propio y una superficie de ataque mucho menor, ya que no almacenas credenciales de usuario en tu infraestructura.

Explicación línea por línea del flujo OAuth

  1. El usuario llega a la app y Streamlit comprueba st.experimental_user.is_logged_in. Si es False, muestra el botón de login.
  2. Al pulsar el botón, st.login("google") redirige al navegador a la URL de autorización de Google con el client_id configurado en secrets.toml.
  3. El usuario se autentica en Google y concede permisos. Google redirige al redirect_uri configurado (por ejemplo, http://localhost:8501/oauth2callback) con un código de autorización.
  4. Streamlit intercambia ese código por un token de acceso usando el client_secret y obtiene los datos del usuario (nombre, email, avatar).
  5. Estos datos se almacenan en una cookie firmada con cookie_secret para mantener la sesión entre recargas.
  6. A partir de ahí, st.experimental_user.is_logged_in devuelve True y el resto del script puede acceder a los atributos del usuario.

Tabla de configuración de secrets.toml

| Sección | Clave | Descripción | |---------|-------|-------------| | [auth] | redirect_uri | URL de callback de OAuth (debe coincidir con la configurada en el proveedor) | | [auth] | cookie_secret | Clave secreta aleatoria de al menos 32 caracteres para firmar cookies | | [auth.google] | client_id | ID de cliente OAuth de Google Cloud Console | | [auth.google] | client_secret | Secreto del cliente OAuth | | [auth.google] | server_metadata_url | URL del documento de configuración OIDC | | [auth.github] | client_id | ID de la OAuth App de GitHub |

Errores comunes

redirect_uri no coincide. El proveedor OAuth rechazará la petición si la URL de callback configurada en su panel no coincide exactamente con la de secrets.toml. Asegúrate de incluir el puerto (:8501) en local y la URL completa en producción.

cookie_secret débil o reutilizada. Esta clave firma las cookies de sesión. Si es corta o está hardcodeada en un repositorio público, cualquiera puede falsificar sesiones. Genera una clave aleatoria con python -c "import secrets; print(secrets.token_urlsafe(32))".

Olvido del st.stop() tras el guard. Si compruebas is_logged_in al principio de una página pero no llamas a st.stop(), el código posterior se seguirá ejecutando y el usuario no autenticado verá contenido protegido.

Atributos de usuario distintos según el proveedor. Google devuelve picture pero GitHub devuelve avatar_url. Si combinas varios proveedores, normaliza los atributos con una función helper antes de usarlos en la UI.

Localhost vs. HTTPS en producción. Muchos proveedores OAuth exigen HTTPS en URLs de callback de producción. Si despliegas en Community Cloud o un dominio personalizado, recuerda actualizar redirect_uri en ambos sitios (el panel del proveedor y secrets.toml).

Mejores prácticas

  • Usa un proveedor OAuth establecido (Google, GitHub, Microsoft) en lugar de gestionar contraseñas propias.
  • Implementa el patrón "guard" al principio de cada página protegida: comprueba is_logged_in y usa st.stop() si no lo está.
  • Controla la autorización (qué usuarios pueden acceder a qué páginas) con listas blancas basadas en email o dominio, no solo con el hecho de estar autenticado.
  • Muestra el avatar y el email del usuario en el sidebar con un botón de logout claramente visible.
  • Para aplicaciones B2B, considera restringir el acceso al dominio corporativo comprobando usuario.email.endswith("@empresa.com").
  • No guardes datos sensibles del usuario en st.session_state más allá de lo necesario: Streamlit los mantiene en memoria del servidor y podrían filtrarse si hay un bug de aislamiento entre sesiones.
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Streamlit es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Streamlit

Explora más contenido relacionado con Streamlit y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Configurar un proveedor OAuth en secrets.toml para autenticación con Google o GitHub. Mostrar el botón de inicio de sesión con st.login y cerrar sesión con st.logout. Acceder a los datos del usuario autenticado mediante st.experimental_user. Proteger páginas verificando st.experimental_user.is_logged_in. Combinar la autenticación nativa con st.navigation para controlar el acceso por página.