Cómo implementar autenticación de usuarios con Flask-Login paso a paso

Video thumbnail

La autenticación de usuarios es una de las funciones esenciales en cualquier aplicación web. En el ecosistema Flask, la extensión Flask-Login facilita todo el manejo de sesiones, el inicio y cierre de sesión y la opción de “recuérdame”.
Cuando construí mis primeros proyectos con Flask, probé varias extensiones como Flask-User y Flask-Security, pero terminé eligiendo Flask-Login porque ofrece un equilibrio perfecto entre simplicidad y control total sobre el flujo de autenticación.

Puede usar el módulo Flask-Login para controlar el acceso. Proporciona administración de sesiones de usuario para Flask: iniciar sesión, cerrar sesión y recordar sesiones.

¿Qué es Flask-Login y para qué sirve?

Flask-Login es una extensión oficial de Flask que gestiona la sesión de usuarios de manera sencilla y segura. Permite:

  • Iniciar y cerrar sesión fácilmente.
  • Proteger rutas mediante el decorador @login_required.
  • Implementar la función “remember me” para mantener al usuario autenticado.
  • Detectar al usuario actual con current_user.
  • Almacene la identificación del usuario activo en la sesión de Flask y le permitirá iniciar y cerrar sesión fácilmente.
  • Le permite restringir las vistas a los usuarios conectados (o desconectados). (Necesario iniciar sesión)
  • Manejar la funcionalidad "recuérdame", normalmente complicada.
  • Ayude a proteger las sesiones de sus usuarios para que no sean robadas por ladrones de cookies.

Su mayor ventaja es que no impone una base de datos ni un modelo de usuario específico. Tú decides cómo se almacena y valida el usuario (por ejemplo, con SQLAlchemy o MongoDB).

Sin embargo, no permitirá:

  • Imponerle una base de datos particular u otro método de almacenamiento. Usted está totalmente a cargo de cómo se carga el usuario.
  • Restringirle al uso de nombres de usuario y contraseñas, OpenID o cualquier otro método de autenticación.
  • Manejar permisos más allá de "iniciar sesión o no".
  • Gestionar el registro de usuarios o la recuperación de cuentas.

Sobre Flask Login

Flask-Login es una extensión para el framework web de Flask que proporciona la gestión de las sesiones de usuario, como el inicio de sesión, el cierre de sesión o logout y la persistencia de la sesión. Para usar Flask-Login, creamos un modelo para el usuario que defina los métodos y parámetros requeridos por esta extensión, como is_authenticated, is_active e is_anonymous, y luego inicialice la extensión en su aplicación Flask.

Flask-Login es provisto mediante un paquete excelente que nos permite manejar las tareas comunes de iniciar y cerrar sesión, además de recordar las credenciales por un largo tiempo.

Trabaja de una manera sencilla en la cual necesitamos un modelo de usuarios y a raíz de este poder comparar credenciales e iniciar sesión:

Con nuestro usuario autenticado podemos realizar operaciones como:

  1. Cerrar sesión fácilmente.
  2. Restringir la vista a los usuarios conectados (o desconectados).

Instalar Flask Login

Con nuestra aplicación creada, vamos a instalar el paquete con:

$ pip install flask-login

Lo primero que necesitamos, es instalar el paquete, ya que como debes de saber en este punto, Flask es un micro framework y trae lo mínimo y necesario para funcionar; en esencia, funciones básicas del core, ruteo, seguridad y un motor de plantilla para HTML; para todo lo demás, existe Mastercard o instalar paquetes de terceros ya sea de Python o propios del framework.

⚙️ Instalación y configuración básica del módulo

Antes de comenzar, asegúrate de tener tu entorno virtual activado:

$ pip install flask flask-login flask-wtf flask-sqlalchemy

El parámetro login_view indica la vista a la que se redirige el usuario si intenta acceder a una ruta protegida sin estar autenticado.

Cuando implementé esto por primera vez, me resultó útil imprimir los estados del current_user para entender cómo Flask-Login gestiona internamente las sesiones.

Vamos a ir a nuestro __init__ en proyect/app/:

from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app)

Y con esto ya estamos listos para usarlo.

Controladores y vistas: login, logout y registro

Vamos a tener un módulo o aplicación llamada app:

proyect/app/user en la cual crearemos el MVC típico en las aplicaciones en Flask:

from flask import Blueprint,session, render_template, request, redirect, url_for, flash, get_flashed_messages
from app.user.models import User
from app.user.forms import LoginForm, RegisterForm
from app import db, login_manager
from flask_login import current_user,login_user, login_required, logout_user
from werkzeug.security import generate_password_hash
userBp = Blueprint('user',__name__)
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)
@userBp.route('/login', methods=('GET', 'POST'))
def login():
   #print(current_user.name)
   form = LoginForm(meta={'csrf':False})
   if form.validate_on_submit():
      user = User.query.filter_by(username=form.username.data).first()
      if user and user.check_password(form.password.data):
         # registrar sesion
         login_user(user, remember=True)
         flash("Bienvenido de nuevo "+user.username)
         print("Vien")
         return redirect(url_for('chat.hello_world'))
      else:
         print("Malo")
         flash("Usuario o contraseña incorrectos",'danger')
   if form.errors:
      print(form.errors)
      flash(form.errors,'danger')
   return render_template('user/login.html',form=form)
@userBp.route('/logout')
@login_required
def logout():
   logout_user()
   return redirect(url_for('user.login'))
@userBp.route('/register', methods=('GET', 'POST'))
def register():
   print(session)
   print(current_user)
   form = RegisterForm(meta={'csrf':False})
   if form.validate_on_submit():
      if User.query.filter_by(username=form.username.data).first():
         flash("El usuario ya existe en el sistema",'danger')
      else:
         #crear usuario
         u = User()
         u.name = form.username.data
         u.username = form.username.data
         u.password = generate_password_hash(form.password.data)
         u.email = form.email.data
         login_user(u, remember=True)
         flash("Usuario creado con éxito")
         return redirect(url_for('user.register'))
   if form.errors:
      flash(form.errors,'danger')
   return render_template('user/register.html',form=form)
@login_required
def logout():
    logout_user()
    return redirect(url_for('user.login'))

Duelo incluir mensajes flash personalizados para mejorar la experiencia del usuario, algo tan simple como “¡Sesión iniciada con éxito!” ayuda mucho en pruebas de usabilidad.

Creando el modelo de usuario con SQLAlchemy

Define un modelo de usuario que herede de UserMixin, lo cual agrega los métodos necesarios (is_authenticated, get_id(), etc.):

from flask_login import UserMixin
from app import db
from werkzeug.security import check_password_hash,generate_password_hash
class User(db.Model,UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email= db.Column(db.String(100), unique=True)
    username= db.Column(db.String(100), unique=True)
    password= db.Column(db.String(400))
    name= db.Column(db.String(100))
    #__tablename__ = 'users'
    def check_password(self, password):
        return check_password_hash(self.password,password)

Formularios de login y registro con Flask-WTF

Los formularios son manejados con Flask-WTF, que simplifica la validación:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, HiddenField
from wtforms.validators import InputRequired, EqualTo

class LoginForm(FlaskForm):
    username = StringField('Usuario', validators=[InputRequired()])
    password = PasswordField('Contraseña', validators=[InputRequired()])
    
class RegisterForm(FlaskForm):
    username = StringField('Usuario', validators=[InputRequired()])
    email = StringField('Email', validators=[InputRequired()])
    password = PasswordField('Contraseña', validators=[InputRequired(),EqualTo('confirm')])
    confirm  = PasswordField('Repetir Contraseña')

Templates

Templates iniciar sesión, /app/templates/user/login

<form action="{{ url_for('user.login') }}" method="POST">
    <div class="form-group">
        {{ form.username.label }} 
        {{ form.username(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.password.label }} 
        {{ form.password(class="form-control") }}
    </div>
    <input class="btn btn-success" type="submit" value="Enviar">
</form>

Templates registrar, /app/templates/user/register

<form action="{{ url_for('user.register') }}" method="POST">
    <div class="form-group">
        {{ form.username.label }} 
        {{ form.username(class="form-control") }}
    </div>
    
    <div class="form-group">
        {{ form.email.label }} 
        {{ form.email(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.password.label }} 
        {{ form.password(class="form-control") }}
    </div>
    <div class="form-group">
        {{ form.confirm.label }} 
        {{ form.confirm(class="form-control") }}
    </div>
    <input class="btn btn-success" type="submit" value="Enviar">
</form>

Este ejemplo define un modelo de usuario que tiene un atributo ID también se define su vista y ruta para el inicio de sesión inicia sesión, registrarse entre otros; las rutas protegidas se definen mediante el decorador @login_required, que garantiza que solo los usuarios autenticados puedan acceder a la función. La ruta de cierre de sesión cierra la sesión del usuario y lo redirige a la página de inicio de sesión.

También puede personalizar el comportamiento de Flask-Login usando varias opciones de configuración, como puedes consultar en la documentación oficial.

Protegiendo rutas con @login_required

Una vez configurado Flask-Login, puedes proteger rutas críticas:

from flask_login import login_required

@app.route('/dashboard')
@login_required
def dashboard():
   return "Bienvenido al panel"

Esto garantiza que solo los usuarios autenticados puedan acceder. Si no lo están, Flask-Login los redirige automáticamente al login_view.

Recuerda que el código fuente del proyecto lo puedes ver aquí:

https://github.com/libredesarrollo/curso-flask-socketio

O aquí:

https://github.com/libredesarrollo/curso-flask-base

Y recuerda que no estamos empleando estilos:

Form Login
Form Login

Recuerda que este material forma parte de mi curso y libro completo sobre flask.

Recordar sesiones y buenas prácticas de seguridad

Flask-Login ofrece la opción remember=True en login_user(), lo que crea una cookie segura que mantiene la sesión activa aunque el navegador se cierre.

Buenas prácticas recomendadas:

  • Usar Flask-Talisman o Flask-SeaSurf para reforzar seguridad.
  • Cifrar contraseñas siempre con generate_password_hash.
  • Invalidar sesiones tras cambios de contraseña o logout.
  • Evitar almacenar información sensible en cookies.

Cuando desarrollé mi primer sistema de autenticación, aprendí que la simplicidad de Flask-Login no exime de aplicar medidas de seguridad; por eso siempre recomiendo acompañarlo de HTTPS y políticas de expiración de sesión.

Errores comunes y cómo depurarlos

Error    Causa probable    Solución
AttributeError: 'User' object has no attribute 'is_authenticated'    Falta heredar de UserMixin    Añadir UserMixin al modelo
login_user() no mantiene la sesión    No se inicializó LoginManager    Verificar login_manager.init_app(app)
Redirección infinita al login    No se configuró login_view    Definir login_manager.login_view = 'user.login'
CSRF Token missing    CSRF deshabilitado en formularios    Activar protección en Flask-WTF
Conclusión: por qué Flask-Login es mi opción preferida

Flask-Login es, sin duda, la forma más sencilla y flexible de añadir autenticación a tus proyectos Flask.
Permite construir sistemas robustos sin depender de configuraciones pesadas ni ORM específicos.

En mi experiencia, combinar Flask-Login + Flask-WTF + SQLAlchemy ofrece un flujo completo, seguro y totalmente personalizable.
Si buscas control total y claridad en tu código, Flask-Login es el punto de partida ideal.

❓ Preguntas frecuentes sobre Flask-Login

1. ¿Flask-Login maneja registro de usuarios?
No. Solo controla las sesiones y autenticación. El registro lo implementas tú.

2. ¿Cómo recuerdo sesiones de usuario?
Usa login_user(user, remember=True) para crear una cookie persistente.

3. ¿Puedo usar Flask-Login sin base de datos?
Sí, mientras tu modelo implemente los métodos requeridos por UserMixin.

4. ¿Cómo redirijo al usuario tras el login?
Usa redirect(url_for('ruta_deseada')) justo después de login_user().

Acepto recibir anuncios de interes sobre este Blog.

Aprenderemos a crear un sencillo modulo de login con Flask Login para el login y registro del usuario.

| 👤 Andrés Cruz

🇺🇸 In english