Tutorial: Incorporación de inicio de sesión a una aplicación web de Python Flask
Este tutorial es la tercera parte de una serie de tutoriales que muestra cómo compilar una aplicación web de Python Flask desde cero e integrar la autenticación mediante la plataforma de identidad de Microsoft. En este tutorial, agregará código para autenticar a los usuarios en la aplicación que ha compilado.
- Importación de los módulos y la configuración necesarios
- Creación de una instancia de una aplicación web de Flask
- Configuración del middleware proxyFix para el desarrollo local
- Agregar código para iniciar sesión y cerrar la sesión de los usuarios
- Definición de un punto de entrada para la aplicación web
Importación de paquetes y configuraciones necesarios
La aplicación web que va a compilar usa el paquete de identity.web
basado en MSAL Python para autenticar a los usuarios en aplicaciones web. Para importar el paquete de identity.web
, el marco de Flask, los módulos de Flask, la sesión de Flask y las configuraciones de la aplicación definidas en el tutorial anterior, agregue el código siguiente a app.py:
import identity.web
import requests
from flask import Flask, redirect, render_template, request, session, url_for
from flask_session import Session
import app_config
En este fragmento de código, importas redirect
, render_template
, request
, session
y url_for
, funciones y objetos para manejar las solicitudes y sesiones web en Flask. También importa app_config
, que contiene las opciones de configuración de la aplicación.
Creación de una instancia de la aplicación web de Flask
Después de importar los módulos necesarios, inicializamos la aplicación web mediante las configuraciones de app-config
. Para crear una instancia de la aplicación web, agregue el siguiente fragmento de código a app.py
:
app = Flask(__name__)
app.config.from_object(app_config)
assert app.config["REDIRECT_PATH"] != "/", "REDIRECT_PATH must not be /"
Session(app)
En el fragmento de código anterior, inicializa una nueva aplicación de Flask y carga las opciones de configuración mediante app.config.from_object(app_config)
. Usando from_object
, la aplicación hereda las configuraciones especificadas en (app_config)
.
También realiza una verificación para asegurarse de que la ruta de redirección de la aplicación no está establecida en la ruta raíz ("/"). Session(app)
inicializa la administración de sesiones para la aplicación, lo que permite controlar sesiones y almacenar datos como estados de autenticación de usuario en varias solicitudes.
Configuración del middleware proxyFix para el desarrollo local
Dado que la aplicación web de ejemplo se ejecuta en el host local, usamos el middleware ProxyFix
para corregir el esquema de dirección URL y la información del host en los encabezados de solicitud. Agregue el código siguiente a app.py
para aplicar ProxyFix:
from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
Inicialización de un objeto de autenticación
A continuación, inicializa un objeto de autenticación mediante la creación de una instancia de la clase identity.web.Auth
. También se pasan los parámetros session
, authority
, client_id
y client_credential
en el constructor al inicializar el objeto Auth, como se indica a continuación:
app.jinja_env.globals.update(Auth=identity.web.Auth) # Useful in template for B2C
auth = identity.web.Auth(
session=session,
authority=app.config["AUTHORITY"],
client_id=app.config["CLIENT_ID"],
client_credential=app.config["CLIENT_SECRET"],
)
En este fragmento de código, app.jinja_env.globals.update(Auth=identity.web.Auth)
agrega una nueva variable global denominada Auth
y la asigna al valor de identity.web.Auth
. Esto hace que Auth
sea accesible en todas las plantillas representadas por la aplicación Flask.
Inicio de sesión de usuarios
El flujo de autorización que construyes en esta aplicación consta de dos etapas. En la primera fase, se invoca la función auth.log_in
para iniciar sesión a los usuarios, como se muestra a continuación:
@app.route("/login")
def login():
return render_template("login.html", version=__version__, **auth.log_in(
scopes=app_config.SCOPE, # Have user consent to scopes during log-in
redirect_uri=url_for("auth_response", _external=True), # Optional. If present, this absolute URL must match your app's redirect_uri registered in Microsoft Entra admin center
prompt="select_account", # Optional.
))
Cuando un usuario navega a la URL de /login
en tu aplicación, Flask invoca la función de vista que controla la solicitud para renderizar la plantilla de login.html
. Dentro de login()
, se llama a la función auth.log_in
con una lista de ámbitos a los que el usuario debe dar su consentimiento durante el proceso de inicio de sesión. También proporciona redirect_uri
en los parámetros, que deben coincidir con el URI de redirección de la aplicación i el Centro de administración de Microsoft Azure.
Opcionalmente, puede agregar parámetros como prompt
, que controla el comportamiento del mensaje de inicio de sesión solicitando la reautenticación, el consentimiento del usuario o la selección de la cuenta entre cuentas con sesiones activas.
En la segunda etapa del flujo de autorización, controlará la respuesta de autenticación llamando a la función auth.complete_log_in
dentro del controlador redirect_uri, como se muestra:
@app.route(app_config.REDIRECT_PATH)
def auth_response():
result = auth.complete_log_in(request.args)
if "error" in result:
return render_template("auth_error.html", result=result)
return redirect(url_for("index"))
La función complete_log_in()
recibe el diccionario auth_response
entrante como parámetros de la consulta. Si se ejecuta correctamente, la función redirige al usuario a la ruta "index" mediante redirect(url_for("index"))
. Esto significa que el usuario ha iniciado sesión correctamente, y su información está disponible como un diccionario que contiene afirmaciones de un token de identificación ya validado.
Si el resultado contiene un error determinado por la condición if "error" in result:
, muestre la plantilla "auth_error.html"
al usuario.
Cerrar sesión de usuarios
Para cerrar la sesión de los usuarios de la aplicación de Flask, invoque el método auth.log_out()
de la siguiente manera:
@app.route("/logout")
def logout():
return redirect(auth.log_out(url_for("index", _external=True)))
Cuando un usuario navega a la ruta de URL /logout
en la aplicación, Flask invoca la función de cierre de sesión que cierra la sesión de la aplicación actual. También se especifica la página a la que deben redirigirse los usuarios después de cerrar sesión. En el fragmento de código, redirigemos a los usuarios a la página principal de la aplicación mediante url_for("index", _external=True).
Definición de un punto de entrada para la aplicación web
Después de implementar la lógica de inicio de sesión y cierre de sesión, agregue un punto de entrada a la página principal de la aplicación mediante la creación de la función index()
como se indica a continuación:
@app.route("/")
def index():
if not (app.config["CLIENT_ID"] and app.config["CLIENT_SECRET"]):
# This check is not strictly necessary.
# You can remove this check from your production code.
return render_template('config_error.html')
if not auth.get_user():
return redirect(url_for("login"))
return render_template('index.html', user=auth.get_user(), version=__version__)
La función index()
se invoca cuando un usuario navega a la dirección URL raíz de la aplicación("/"). Controla las comprobaciones de configuración y valida la autenticación del usuario antes de representar la página principal de la aplicación. Comprueba si faltan el identificador de cliente y el secreto de cliente en la configuración y, si falta cualquiera de los dos valores o ambos, Flask muestra la plantilla de "config_error.html"
.
La función también llama a auth.get_user()
para comprobar si el usuario está autenticado o no. Si el usuario no está autenticado, los redirige a la ruta "login"
. Si se autentica, Flask representa la plantilla "index.html" y pasa el objeto de usuario (recuperado de auth.get_user()
) para su representación.