Adquisición de tokens

Hay muchas maneras de adquirir un token con MSAL Python. Algunos requieren interacción del usuario, mientras que otras no. El enfoque utilizado para obtener un token varía en función de si el desarrollador está desarrollando un cliente público (de escritorio o móvil) o una aplicación cliente confidencial (aplicación web, API web o un daemon, como un servicio de Windows).

Prerequisites

Antes de adquirir tokens con MSAL Python, obtenga información sobre los tipos de aplicación cliente.

Obtención de la cuenta de usuario

Una aplicación puede adquirir un token como sí mismo o en nombre de un usuario. Para adquirir un token en nombre de un usuario, la aplicación debe conocer la cuenta del usuario. MSAL Python proporciona el get_accounts método para obtener la cuenta del usuario. Este método está disponible en las PublicClientApplication clases y ConfidentialClientApplication . El método devuelve una lista de cuentas con las que el usuario ha iniciado sesión anteriormente, es decir, existe en la memoria caché.

accounts = app.get_accounts(username=user.get("preferred_username"))

La cuenta seleccionada por el usuario para el inicio de sesión se puede usar más adelante en acquire_token_silent() para buscar sus tokens.

Flujos de concesión de tokens

Hay varios flujos de autenticación que se pueden usar para adquirir tokens con MSAL Python. Puede encontrar más información sobre estos flujos en la documentación de Plataforma de identidad de Microsoft.

Warning

Use siempre MSAL para obtener tokens de seguridad y llamar a las API web protegidas en las aplicaciones. No recomendamos que implemente su propia lógica de adquisición de tokens. Estos flujos le ayudarán a comprender mejor cómo funcionan las cosas. Si va a proteger una aplicación web, recomendamos utilizar la biblioteca identity. Esta biblioteca no se mantiene oficialmente por Microsoft, pero implementa la mayoría de la lógica que necesita para adquirir tokens en aplicaciones web.

Interactivo frente a silencioso

MSAL Python admite la adquisición de tokens interactivas y silenciosas. La adquisición interactiva de tokens requiere interacción del usuario, mientras que la adquisición silenciosa de tokens no. Por lo general, los clientes públicos requieren interacción del usuario mientras que los clientes confidenciales se basan en credenciales aprovisionadas previamente, como certificados y secretos.

Use el acquire_token_silent_with_error método para adquirir un token de forma silenciosa. Este método busca un token de acceso válido de la memoria caché o un token de actualización válido de la caché y, a continuación, lo usa automáticamente para canjear un nuevo token de acceso. Si no se cumple ninguna de las dos, debe utilizar un método interactivo para obtener el token.

Si a su aplicación no le importa el error exacto al actualizar el token durante la búsqueda en la caché de tokens, se recomienda el método acquire_token_silent.

Un ejemplo de uso de este método es como se muestra en el siguiente fragmento de código.

if accounts:
    # If so, you could then somehow display these accounts and let end user choose
    chosen = accounts[0]
    result = app.acquire_token_silent(scopes=["your_scope"], account=chosen)
    
    # At this point, you can save you can update your cache if you are using token caching
    # check result variable, if its None then you should interactively acquire a token
    if not result:
        # So no suitable token exists in cache. Let's get a new one from Microsoft Entra.
        result = app.acquire_token_by_one_of_the_actual_method(..., scopes=["User.Read"])
    
    if "access_token" in result:
        access_token = result["access_token"]
    else:
        print(result.get("error"))  
        print(result.get("error_description"))
        print(result.get("correlation_id"))  # You may need this when reporting a bug

Hay varios métodos disponibles para la adquisición interactiva de tokens. El método que debe utilizarse depende del tipo de aplicación que esté desarrollando y del tipo de flujo de concesión de tokens aplicable a su caso.

Adquisición interactiva de tokens de clientes públicos

Las aplicaciones cliente públicas no pueden almacenar de forma segura un secreto y solo pueden autenticar al usuario que interactúa con el producto. MSAL Python expone la lógica de adquisición de tokens para las aplicaciones públicas a través de PublicClientApplication. A continuación se muestran los distintos métodos disponibles para que las aplicaciones cliente públicas adquieran tokens.

Flujo de código de dispositivo

El flujo de código de dispositivo se usa para adquirir tokens en aplicaciones que se ejecutan en dispositivos que no tienen acceso a un explorador web. Estas son aplicaciones conocidas como aplicaciones sin encabezado. Este flujo proporciona al usuario una dirección URL y un código. El usuario va a un explorador web en otro dispositivo, escribe el código e inicia sesión. En la autenticación correcta, Microsoft Entra devuelve un token al dispositivo sin explorador.

Primero, se llama al método initiate_device_flow.

flow = app.initiate_device_flow(scopes=config["scope"])
if "user_code" not in flow:
    raise ValueError(
        "Fail to create device flow. Err: %s" % json.dumps(flow, indent=4))

print(flow["message"])
sys.stdout.flush()  # Some terminal needs this to ensure the message is shown

# Ideally you should wait here, in order to save some unnecessary polling
# input("Press Enter after signing in from another device to proceed, CTRL+C to abort.")

A continuación, pase el objeto de diccionario de flujo al método acquire_token_by_device_flow para obtener el token. De forma predeterminada, este método bloquea el hilo actual. Puede seguir estas instrucciones para acortar el tiempo de bloqueo o incluso desactivar el comportamiento de bloqueo y, a continuación, seguir llamando acquire_token_by_device_flow en su propio bucle personalizado.

result = app.acquire_token_by_device_flow(flow)

if "access_token" in result:
    access_token = result["access_token"]
else:
    print(result.get("error"))  

Una respuesta satisfactoria es un diccionario con una clave access_token.

Obtener token de forma interactiva

MSAL Python también ofrece la posibilidad de que las aplicaciones cliente públicas (equipos de escritorio y dispositivos móviles) obtengan tokens en nombre del usuario. El usuario inicia sesión a través de la dirección URL de solicitud de autorización a través de un explorador web. Establezca el URI de redireccionamiento de su aplicación en http://localhost en el centro de administración de Microsoft Entra para el registro de su aplicación. Si decide usar broker durante la creación de PublicClientApplication, su aplicación también debe registrar ms-appx-web://Microsoft.AAD.BrokerPlugin/YOUR_CLIENT_ID como un URI de redirección.

result = app.acquire_token_interactive(  # It automatically provides PKCE protection
    scopes=config["scope"])

if "access_token" in result:
    access_token = result["access_token"]
else:
    print(result.get("error"))  

Nombre de usuario y contraseña

Warning

Esta API ha quedado en desuso para los flujos de cliente públicos debido a riesgos de seguridad, use un flujo más seguro. Siga esta guía para obtener instrucciones de migración.

No se recomienda usar este enfoque. También es posible obtener un token con un nombre de usuario y una contraseña. MSAL Python proporciona el acquire_token_by_username_password método para este caso de uso. No se recomienda porque la aplicación pedirá a un usuario su contraseña directamente, que es un patrón no seguro.

Hay flujos más seguros que puede usar. Obtenga más información en la guía de flujo de autenticación de nombre de usuario y contraseña .

result = app.acquire_token_by_username_password(
    username=config["username"], password=config["password"], scopes=config["scope"])

if "access_token" in result:
    access_token = result["access_token"]
else:
    print(result.get("error"))  

Adquisición de tokens interactivos de clientes confidenciales

Las aplicaciones cliente confidenciales pueden almacenar de forma segura un secreto y pueden autenticarse tanto en nombre de una aplicación como en nombre de un usuario determinado. MSAL Python proporciona a los desarrolladores varios métodos para adquirir tokens al desarrollar ConfidentialClientApplication.

Adquisición del token para el cliente

Obtenga un token como la propia aplicación usando credenciales de cliente, y no para un usuario. Por ejemplo, esto se puede usar en aplicaciones que procesan usuarios por lotes y no en un usuario determinado, como herramientas de sincronización. MSAL Python proporciona el acquire_token_for_client método para hacerlo. Dado que MSAL Python 1.23, este método busca automáticamente el token de la memoria caché y solo envía solicitudes al proveedor de identidades cuando se produce un error en la memoria caché.

result = app.acquire_token_for_client(scopes=config["scope"])

if "access_token" in result:
    access_token = result["access_token"]
else:
    print(result.get("error"))    

Adquisición del token en nombre de

En el caso de aplicaciones web o API web que llamen a otra API web posterior en nombre del usuario, utiliza el flujo «On Behalf Of» para obtener un token basado en una afirmación del usuario. Por ejemplo, SAML y JWT. La aplicación actual es un servicio de nivel intermedio al que se llamó con un token que representa a un usuario final. La aplicación actual puede usar este token, también conocido como aserción de usuario, para solicitar otro token para acceder a la API web de bajada en nombre de ese usuario. La aplicación de nivel intermedio no tiene ninguna interacción del usuario para obtener el consentimiento. Para obtener información sobre cómo obtener consentimiento por adelantado para la aplicación de nivel intermedio, consulte la documentación.

Este es un ejemplo de código que adquiere un token de acceso mediante el acquire_token_on_behalf_of método .

def get(self, request): # a web service endpoint receiving a request
    
    scopes = ["your-scopes"]
    downstream_api = "https://your-downstreamapi.com/resource" #your downstream API resource endpoint
    current_access_token = request.headers.get("Authorization", None)
    
    # initialize the app
    app = msal.ConfidentialClientApplication(...) # refer to initialization of the app documentation

    #acquire token on behalf of the user that called this API
    downstream_api_access_token = app.acquire_token_on_behalf_of(
        user_assertion=current_app_access_token.split(' ')[1],
        scopes=_scopes
    )

    if "access_token" in result:
        access_token = result["access_token"]
        # use access_token to call dowstream API e.g
        requests.get(downstream_api, headers={'Authorization': f'Bearer {downstream_api_access_token}'})
    else:
        print(result.get("error")) 

Adquisición de tokens por flujo de código de autorización

En el caso de las aplicaciones web que se autentican en el nombre de un usuario, adquiera tokens a través del código de autorización después de permitir que el usuario inicie sesión a través de la dirección URL de solicitud de autorización. Normalmente, este es el mecanismo usado por una aplicación que permite al usuario iniciar sesión y acceder a las API web para este usuario en particular.

En primer lugar, deberá iniciar el flujo de código de autenticación mediante .initiate_auth_code_flow Este método toma entre otros parámetros un URI de redirección y una cadena de estado. El valor del parámetro state también se incluye en la respuesta del token. Si este valor no está presente, MSAL Python generará automáticamente uno internamente. El URI de redireccionamiento proporcionado debe coincidir con el URI de redirección registrado en el Centro de administración Microsoft Entra. Este método devuelve el flujo de código de autenticación que es un diccionario que contiene auth_uri y state. auth_uri es la dirección URL que el usuario debe visitar para iniciar sesión.

flow = app.initiate_auth_code_flow(
    scopes=config["scope"], redirect_uri=config["redirect_uri"], state="your-state-value")

if "error" in flow:
    print(flow.get("error"))

# Save the response somewhere e.g in session
session["auth_flow"] = flow

# At this point, the app should guide the user to visit the auth ur (session["auth_flow"]["auth_uri"])

La respuesta obtenida al acceder a los endpoints del URI de autenticación se usa en el método acquire_token_by_auth_code_flow. El estado es un identificador único que puede usar para comprobar la respuesta del servidor de autorización. El usuario debe dar su consentimiento a los ámbitos durante el inicio de sesión.

# The uth_response value from visiting the auth_uri endpoint is passed as a query string
# You can change this by passing a value to the response_mode in the initiate_auth_code_flow method
try:
    result = app.acquire_token_by_auth_code_flow(session.get("flow", {}), auth_response)
    
    if "access_token" in result:
        access_token = result["access_token"]
    else:
        print(result.get("error"))
except ValueError:  # Usually caused by CSRF
    pass  # Simply ignore them

Almacenamiento en caché de tokens de MSAL Python

Tanto las aplicaciones cliente públicas como confidenciales admiten el almacenamiento en caché de tokens, controlado directamente por MSAL Python. Las aplicaciones deben intentar obtener un token de la memoria caché en primer lugar antes de confiar en cualquier otro medio. Para obtener más información, consulte patrón de adquisición de tokens recomendado.

Para poder conservar la memoria caché, los desarrolladores deben configurar la lógica de serialización de caché de tokens .