Exportar (0) Imprimir
Expandir todo

Implementación de aplicaciones web para varios inquilinos con Azure AD

Actualizado: mayo de 2014

noteNota
Esta muestra está obsoleta. Sus instrucciones de tecnología, métodos y/o interfaz de usuario se han reemplazado por características más recientes. Para ver una muestra actualizada que cree una aplicación similar, vea WebApp-MultiTenant-OpenIdConnect-DotNet.

En el primer documento de Azure AD para series de desarrolladores, aprendió como aprovechar el inquilino de Azure AD para permitir a sus usuarios disfrutar del inicio de sesión web con sus aplicaciones de línea de negocio (LoB), de forma local y en la nube. Lea al respecto aquí: Adición de inicio de sesión en su aplicación web con Azure AD

El segundo documento, creado a partir del primero, muestra cómo habilitar su aplicación LoB para consultar información de directorios a través de la API de gráficos. Lea al respecto aquí: Uso de la API Graph para realizar consultas a Azure AD

El documento que está leyendo ahora le proporcionará unos conocimientos más profundos de Azure AD, ya que le mostrará cómo desarrollar aplicaciones de software como servicio (SaaS) diseñadas para trabajar con varios inquilinos y automatizar la incorporación de nuevos clientes, todo mientras aprovecha las características de Azure AD que aprendió a utilizar en los dos primeros documentos.

En lo que respecta a identidad y acceso, los problemas comunes a los que se enfrenta un desarrollador de aplicaciones SaaS son principalmente la incorporación de los clientes y el acceso a la infraestructura de identidad del cliente. Cada cliente potencial tiene una solución de inicio de sesión web distinta, lo que dificulta mucho la estandarización de un proceso de incorporación que resulte sencillo para el cliente y fácil de administrar para la aplicación; asimismo, cada cliente potencial mantiene datos de directorios y de identidad en la infraestructura a los que no se puede obtener acceso desde aplicaciones en la nube.

Azure AD ofrece una solución simple para ambos problemas. En el primer documento, aprendió cómo su administrador puede usar el portal de administración de Azure para registrar las aplicaciones que desarrolle para tener acceso a su inquilino del directorio. En este tutorial, verá que las mismas aplicaciones se pueden configurar para que también puedan obtener acceso a ellas otros inquilinos de Azure AD. Azure AD ofrece un mecanismo mediante el cual las mismas aplicaciones pueden pedir a los administradores de posibles clientes que les concedan acceso a sus inquilinos de directorios. Esto se consigue mediante el portal de administración de Azure AD para presentar al administrador del cliente una interfaz de usuario de consentimiento: la experiencia no es muy distinta a los gestos de concesión de consentimiento que son ahora comunes para todas las aplicaciones web sociales más habituales.

Este documento le mostrará cómo modificar la entrada en Azure AD de la aplicación MVC 4 que ha desarrollado en los dos primeros documentos para hacer la aplicación disponible para varios inquilinos de Azure AD. Asimismo, le guiará por los cambios de código que debe aplicar a la aplicación para pasar de una solución diseñada para conectarse a un solo inquilino a una solución completa para varios inquilinos que pueda integrar varias organizaciones de clientes. Las instrucciones del tutorial estarán intercaladas con explicaciones de conceptos más específicos, necesarios para entender cómo Azure AD más allá del ámbito de la aplicación de ejemplo descrita aquí.

Cabe reiterar que las tareas descritas aquí son todas incrementales en lo que respecta a la solución desarrollada en los dos primeros documentos: no debe empezar a leer este documento si no ha leído los dos primeros y seguido las instrucciones descritas en ellos.

Este documento está organizado en las secciones siguientes:

  • Requisitos previos: esta sección enumera todos los requisitos que deben cumplirse para completar el tutorial.

  • Arquitectura de la solución: esta sección proporciona una introducción detallada de un modo de estructurar una aplicación SaaS para aprovechar Azure AD.

  • Promoción de la entrada de la aplicación en Windows AD para estar disponible de forma externa: esta sección volverá a visitar la entrada de la aplicación LOB en el portal de Azure, y le mostrará qué cambiar para ampliar la disponibilidad de la aplicación existente para inquilinos de directorios distintos al suyo.

  • Preparar el proyecto de la aplicación en VS para administrar varios inquilinos: esta sección le mostrará cómo modificar el código fuente de su aplicación MVC 4, que actualmente está diseñada para realizar el inicio de sesión web y el acceso a los gráficos con un solo inquilino de directorio, para usar un conjunto dinámico de inquilinos de Azure AD. Trabajará en varias subsecciones, que abordarán a su vez distintos aspectos de la administración de identidades de la aplicación que deben generalizarse en el caso de varios inquilinos.

  • Agregar capacidades de suscripción a la aplicación: esta sección le mostrará cómo modificar el código fuente de su aplicación MVC 4, que actualmente está diseñada para realizar el inicio de sesión web y el acceso a los gráficos con un solo inquilino de directorio, para usar un conjunto dinámico de inquilinos de Azure AD. Trabajará en varias subsecciones, que abordarán a su vez distintos aspectos de la administración de identidades de la aplicación que deben generalizarse en el caso de varios inquilinos.

  • Opcional: Crear una suscripción de prueba: la suscripción de Azure creada en el primer tutorial contiene un solo directorio, el suyo; no obstante, para probar cómo funciona su aplicación en cargas de trabajo de varios inquilinos, necesita obtener acceso a un inquilino de Azure AD distinto del suyo. Esta sección le sugerirá una estrategia para obtenerlo.

  • Probar la aplicación: esta sección le mostrará cómo se realizan todas las tareas del tutorial para crear una experiencia completa y uniforme para su aplicación SaaS.

Los siguientes requisitos previos son necesarios para completar el tutorial:

Arquitectura de la solución para una aplicación de varios inquilinos

Las aplicaciones tradicionales de línea de negocio están adaptadas para que puedan obtener acceso a ellas y mantenerlas los usuarios de una misma organización que la han desarrollado e implementado por primera vez. Las aplicaciones empresariales ofrecidas como software como servicio (SaaS), por el contrario, son desarrolladas y operadas por un proveedor de software independiente, y están diseñadas para que las utilicen organizaciones de terceros. Es frecuente que estas aplicaciones se compilen como recursos de varios inquilinos: una aplicación compartida por varias organizaciones de clientes (inquilinos) en las que cada inquilino experimenta la aplicación como si fuera su único cliente.

Como se ha mencionado en la introducción, Azure AD ofrece una forma mediante la cual puede hacer que una aplicación LOB existente esté disponible para otros administradores de inquilinos de Azure AD (sus clientes potenciales) para usarla en su organización. Todo lo que tiene que hacer el administrador del cliente potencial es dirigirse a una dirección URL especial e iniciar sesión en su inquilino de Azure AD. Llegará a una página que describe la aplicación, su publicador y el nivel de acceso que requiere en su directorio (SSO, SSO y acceso de solo lectura, SSO y lectura/escritura). El administrador del cliente puede usar los controles de la página para otorgar consentimiento a la aplicación para obtener acceso a su directorio de Azure, en cuyo caso el portal de administración registrará automáticamente el inquilino de Azure AD del cliente sin requerir ningún trabajo adicional.

La aplicación MVC 4 creada en el tutorial de LOB contiene referencias directas al inquilino de Azure AD con el que estaba configurado para integrarse: es decir, configuró la aplicación para redirigir cualquier solicitud autenticada a la dirección de inicio de sesión específica del inquilino y para aceptar solo los tokens que provengan de ese inquilino específico. La mayor parte del trabajo que realizará en este tutorial consiste en generalizar la lógica de administración de identidad de la aplicación, para que la aplicación esté lista para controlar llamadas de API de gráficos y de inicio de sesión web con cualquiera de los inquilinos de clientes registrados. Otra área funcional importante será agregar la capacidad de dirigir los clientes potenciales a la página de consentimiento descrita anteriormente, así como procesar los resultados para aumentar de forma dinámica la lista de inquilinos de Azure AD aceptados como autoridades válidas. Todo esto se realizará aprovechando el modelo de extensibilidad de WIF en unas cuantas áreas estratégicas.

El componente central de la arquitectura de la aplicación modificada es MultiTenantIssuerNameRegistry (MTINR a partir de ahora) y el almacén persistente de sus inquilinos.

MTINR mantiene una lista de todos los inquilinos de Azure AD que deben considerarse como fuentes de autenticación válidas. Características de la lista:

  • Se consulta en el momento de inicio de sesión. Solo los tokens emitidos por inquilinos registrados se consideran válidos.

  • Se actualiza en el momento de la suscripción. Cuando un cliente potencial otorga consentimiento a la aplicación para obtener acceso a su directorio, el portal de administración redirige al usuario a su aplicación con el identificador de inquilino asociado. El tutorial le mostrará cómo procesar ese mensaje mediante programación para agregar al nuevo cliente a la lista MTINR.

MTINR también mantiene la clave que debe usarse para comprobar las firmas de los tokens que provienen de Azure AD; este documento le mostrará cómo modificar la lógica de actualización de claves automatizadas para garantizar que su aplicación realiza un seguimiento de todos los eventos de rotación de claves en el servicio y minimizar el tiempo de inactividad.

La adición de un paso de inicio de sesión conlleva que su aplicación ahora debe poder ofrecer interfaz de usuario a los usuarios autenticados; aprenderá cómo cambiar la configuración de WIF para aplicar los requisitos de inicio de sesión web de forma selectiva en sus controladores, en contraposición a la directiva de protección global mostrada en el tutorial de aplicaciones LoB.

En primer lugar, debe permitir a Azure AD saber que quiere hacer que su aplicación esté disponible para otros inquilinos de Azure AD. Hará esto cambiando la configuración de la aplicación en el portal de administración de Azure.

Vaya al portal de administración de Azure e inicie sesión con la misma cuenta que usó para los tutoriales de LoB y de API de gráficos. Vaya a la pestaña Active Directory, seleccione su directorio, haga clic en el encabezado Aplicaciones, localice la entrada de la aplicación que ha creado en el tutorial de LoB y haga clic en ella.

Llegará a la misma página de Inicio rápido que se le mostró al final del proceso de registro; haga clic en el encabezado Configurar.

noteNota
Si, durante los últimos tutoriales, activó la casilla “Omitir Inicio rápido en la próxima visita”, se le mostrará la pantalla Configurar directamente.

Acceso externo

A mitad de la página, encontrará un interruptor denominado Acceso externo.

La posición predeterminada del interruptor es OFF (desactivado): en el momento de la creación, las aplicaciones se configuran para estar accesibles solo por usuarios desde el mismo inquilino de Azure AD en que se crearon.

Al activar External Access, se hace posible para otros inquilinos el aprovisionamiento de la aplicación en sus propios directorios. En concreto, esto significa que Azure AD activará la URL de consentimiento del cliente, que puede usarse por los administradores de otros inquilinos para conceder permiso de la aplicación para obtener acceso a sus propios directorios. Al dar el consentimiento a su aplicación, se activa el aprovisionamiento en sus propios inquilinos de Azure AD de una entrada que describe la aplicación, a la vez que establecerá los parámetros de la aplicación (URI del id. de aplicación, URL de aplicación, claves usadas para obtener acceso a la API de gráficos, etc.) en su página.

ImportantImportante
La activación del acceso externo para una aplicación does not cambia ninguno de los permisos existentes que la aplicación ya tiene sobre your own inquilino de Azure AD. Asimismo, la desactivación del acceso externo para una aplicación not afectará a los niveles de acceso ya concedidos en sus inquilinos o los de otro usuario mientras estaba disponible. En otras palabras, este interruptor solo afecta a la disponibilidad de la experiencia de consentimiento y al mecanismo de aprovisionamiento asociado para clientes externos; no afecta a las entradas de la aplicación que ayudó a crear.

Haga clic en el lado ON del interruptor. Verá que el interruptor cambia a morado, y que la barra de comandos de la parte inferior de la pantalla ahora incluye un botón Guardar. Intente hacer clic en el botón Guardar: no funcionará, pero es importante que se familiarice con el mensaje de error que aparece.

Error en la actualización de la configuración

Error en la operación de actualización. Haga clic en el icono Detalles para solucionar el problema.

No se pudo obtener detalles

El mensaje señala que el formato de URI del id. de aplicación no es válido para esta operación.

Dado que las aplicaciones externamente disponibles estarán accesibles para un gran número de usuarios, posiblemente sin vínculos comerciales anteriores con la organización que ofrece la aplicación, Azure AD impone algunos requisitos adicionales para este tipo de aplicaciones que harán más fácil su identificación.

Mientras que las aplicaciones LoB pueden tener cualquier URI como valor de URI de id. de aplicación, con un único nivel de inquilino como restricción, las aplicaciones necesitan reunir los siguientes requisitos para establecerse como externamente disponibles:

  • Solo los URI que usen https:// como esquema de protocolo son aceptables.

  • La parte del host del URI must corresponde a un dominio verificado asociado a su inquilino de Azure AD.

Si tiene un dominio personalizado que desee usar con Azure AD, puede seguir las instrucciones detalladas aquí para verificarlo. Puede encontrar los dominios personalizados ya verificados en el encabezado Dominios, homólogo del encabezado Aplicaciones en las páginas del portal de administración de Azure de su inquilino.

Si no tiene o no desea usar un dominio personalizado, puede aprovechar el dominio predeterminado de tres niveles que se asigna a cada inquilino de Azure AD, del formulario<tenantname>.onmicrosoft.com. Dado que es una opción de seguridad predeterminada, esta es la estrategia que seguiremos aquí.

Desplácese hasta la parte inferior de la página, a la sección de inicio de sesión único. Edite el URI del id. de aplicación especificando el valor https://<tenantname>.onmicrosoft.com/ExpenseReport, sustituyendo la cadena <tenantname> por el nombre de su inquilino de Azure AD. Haga clic en Guardar de nuevo.

Dado que el formato URI del id. de aplicación es el esperado, esta vez la operación de actualización se realizará correctamente. El portal de administración lo notificará con un mensaje en la parte inferior de la pantalla; no obstante, podrá saberlo también por un par de cambios clave en la configuración de la aplicación, como se muestra en la siguiente figura.

Dirección URL de concesión de acceso

El interruptor de acceso interno ahora está totalmente en la posición ON. Asimismo, observará que hay un nuevo cuadro de texto denominado Dirección URL de concesión de acceso. Es la dirección URL del extremo que sus clientes potenciales usarán para conceder a su aplicación acceso al directorio; examinaremos la estructura de la dirección URL con detalle más adelante en el tutorial, cuando integraremos la funcionalidad del inicio de sesión en el código de la aplicación.

En lo que respecta a su inquilino de Azure AD, en este punto su aplicación está lista para funcionar con la capacidad de varios inquilinos: ahora necesita modificar el código de la aplicación en consecuencia.

noteNota
Este tutorial aún funciona en la fase de desarrollo del ciclo de vida de la aplicación. Una vez que su aplicación esté lista para producción, volverá a esta pantalla para perfeccionar la apariencia de la aplicación en la página del consentimiento (cargando un logotipo adecuado) y cambiar la dirección URL de respuesta de la aplicación a su dirección de producción. Por último, puede usar las mismas instrucciones proporcionadas en la sección “Implementación de la aplicación en sitios web de Azure” en el tutorial de la aplicación de LOB: los pasos de implementación reales variarán en función de su entorno de destino, pero las instrucciones para actualizar la entrada de la aplicación en el portal de administración pueden aplicarse de ese modo.

Abra en Visual Studio 2012 el proyecto de MVC 4 que creó en los tutoriales anteriores.

Como se anticipó en la sección “Arquitectura de la solución”, necesitará aplicar varios cambios específicos para agregar la capacidad de varios inquilinos a la aplicación LoB que creó en los dos primeros tutoriales. Vamos a aplicar estos cambios de forma incremental, por área funcional; en línea con el resto de tutoriales de la serie, el objetivo principal es ayudarle a comprender lo que está sucediendo para poder aplicar lo que aprende en sus propias aplicaciones.

noteNota
Los cambios propuestos aquí también intentan minimizar la reestructuración del código que ha creado hasta ahora. Esto producirá cierta redundancia (por ejemplo, la creación de nuevos controladores, en lugar de la consolidación de varias características en una más genérica), que hará que el tutorial sea más fácil de seguir. No obstante, siéntase libre de reestructurar y normalizar la funcionalidad cuando la aplique a sus propios proyectos.

Lo primero que haremos será actualizar las coordenadas de WS-Federation en Web.config para reflejar los nuevos ajustes. Localice el archivo Web.config en el explorador del proyecto y ábralo.

noteNota
Si no leyó la sección avanzada “Configuración de WIF en detalle” en el tutorial de LoB, este sería un buen momento para hacerlo. Algunas de estas tareas podrían realizarse con la herramienta de identidad y acceso, pero elegimos explicar cómo hacerlo editando directamente el archivo Web.config, ya que muestra con mayor claridad los cambios necesarios.

Desplácese hasta la sección <system.identityModel>. Observará que el elemento identityConfiguration/AudienceURI aún contiene el valor antiguo de URI del id. de la aplicación: cámbielo al nuevo valor que especificó en el portal de administración de Azure, como se muestra a continuación.

<system.identityModel>
    <identityConfiguration>
      <audienceUris>
        <add value=”https://<tenantname>.onmicrosoft.com/ExpenseReport” />
      </audienceUris> 

Esto garantizará que la aplicación acepte como válidos los tokens del nuevo URI del id. de la aplicación.

Desplácese más, hasta el elemento <wsFederation> de system.identityModel.Services/federationConfiguration.

Aquí necesitará aplicar dos cambios:

  • Modifique el valor del atributo realm con el mismo URI del id. de aplicación que utilizó para la sección <audienceUris> anterior.

  • Edite el valor del atributo issuer sustituyendo el GUID de tenantID por la cadena common.

<federationConfiguration>
   <cookieHandler requireSsl="false" />
   <wsFederation passiveRedirectEnabled="true" issuer="https://login.windows.net/common/wsfed" realm="https://<tenantname>.onmicrosoft.com/ExpenseReport" requireHttps="false" />
</federationConfiguration> 

El valor realm corresponde al valor del parámetro wtrealm de WS-Federation, que se incluye en los mensajes de inicio de sesión para la autoridad (el proveedor de identidad) para indicar el destinatario del token solicitado; tiene que coincidir con el valor que identifica a la aplicación en el inquilino de Azure AD de destino.

El valor issuer indica el extremo que debería recibir solicitudes de inicio de sesión. Mientras que en el primer tutorial eso correspondía a su inquilino de Azure, ahora no podemos saber de antemano de qué inquilino provendrá el siguiente usuario (entre todos los que concedieron consentimiento a la aplicación). Azure AD ofrece un extremo especial, que suele conocerse como el extremo independiente del inquilino, que permite a la aplicación diferir la decisión sobre qué inquilino debería usarse en el momento en que el usuario especifique su nombre de usuario. Dado que el nombre de usuario incluye información del domino, en ese punto el inquilino elegido se determinará de forma exclusiva y la autenticación se realizará de la forma habitual.

noteNota
Es importante recordar que Azure AD emitirá un token al usuario solo si la aplicación del destinatario (indicada por el parámetro realm como se ha descrito anteriormente) ha obtenido acceso en el inquilino de Azure AD del usuario. El uso del extremo independiente del inquilino no debilita las restricciones de acceso establecidas en el nivel del directorio; solo aporta generalidad al proceso de inicio de sesión.

De nuevo en el archivo Web.config, desplácese hasta el elemento IssuerNameRegistry.

Recordará del primer tutorial que este elemento está diseñado para registrar los parámetros que definen un token válido: la huella digital del certificado X.509 que debe usarse para validar la firma del token, y el valor del emisor que identifica el inquilino de Azure AD de confianza.

Esa información sigue siendo relevante en el caso de varios inquilinos: la principal diferencia es que, en lugar de tener un solo valor, hay una lista de emisores aceptables que corresponden a los inquilinos de cliente de la aplicación. La clase usada para implementar IssuerNameRegistry, ValidatingIssuerNameRegistry (VINR), puede trabajar con varias entradas en su elemento <validIssuers>. No obstante, una aplicación para varios inquilinos puede adquirir nuevos clientes mientras está en ejecución y aprovisiona a los existentes, y la edición de Web.config tendría consecuencias no deseadas en la disponibilidad de la aplicación.

Para evitar este problema, en este tutorial almacenaremos la información del inquilino en un archivo externo y crearemos una implementación de VINR personalizada para usar el archivo externo como fuente de coordenadas de validación.

noteNota
Este tutorial implementa el mínimo estricto para demostrar el rol funcional del almacenamiento. En el rendimiento de la aplicación en la vida real, la disponibilidad y la solidez del almacenamiento serían aspectos clave de la solución.

Empecemos creando el almacenamiento externo. En la carpeta Contenido, cree un nuevo archivo XML (en el Explorador de soluciones, haga clic con el botón secundario en Contenido, Agregar nuevo elemento, elija la categoría Datos a la izquierda y seleccione el archivo XML) y llámelo tenants.xml.

Edite el archivo copiando lo siguiente:

<?xml version="1.0" encoding="utf-8" ?>
<authority>
  <tenants>
    <tenant id="95ca3807-2313-4cfe-93b3-20ef9f46ae88" />    
  </tenants>
  <keys>
    <key id="3A38FA984E8560F19AADC9F86FE9594BB6AD049B" />
  </keys>
</authority>

Puede dejar los elementos <tenants> y <keys> en blanco, o puede proporcionarles los valores thumbprint y tenantID del IssuerNameRegistry actual; después de todo, la aplicación ya tiene derechos de acceso a su inquilino de Azure AD.

Ahora que tiene el repositorio externo, creemos la implementación de VINR personalizada usando su validación de origen.

Cree una carpeta nueva AADUtils en la raíz del proyecto. Haga clic con el botón secundario en ella, seleccione Agregar... y haga clic en Nuevo elemento, seleccione el código de las categorías a la izquierda, haga clic en Clase y, a continuación, nombre el archivo MultiTenantIssuerNameRegistry.

Agregue lo siguiente mediante directivas:

using System.IdentityModel.Tokens;
using System.Xml.Linq;

Haga que la nueva clase sea una implementación de VINR; agregue un par de propiedades estáticas para realizar un seguimiento de la ruta y el contenido de tenants.xml y, a continuación, agregue un constructor predeterminado estático (todos nuestros métodos serán estáticos) para inicializarlos en el momento de la creación.

namespace ExpenseReport.AADUtils
{
    public class MultiTenantIssuerNameRegistry: ValidatingIssuerNameRegistry
    {
        private static XDocument doc;
        private static string filePath;

        static MultiTenantIssuerNameRegistry()
        {
            filePath = HttpContext.Current.Server.MapPath("~/Content/tenants.xml");
            doc = XDocument.Load(filePath);
        }
    }
}

Agregue métodos para probar si el repositorio tiene presencia de tenantID o claves:

public static bool ContainsTenant(string tenantId)
{
    return 
    doc.Descendants("tenant").Where(x => x.Attribute("id").Value == tenantId).Any();
}

public static bool ContainsKey(string thumbprint)
{
    return 
    doc.Descendants("key").Where(x => x.Attribute("id").Value == thumbprint).Any();
}
noteNota
Ambos métodos siguen el mismo principio, basado en la sintaxis concisa de LINQ: seleccionan todos los elementos del tipo de destino, “tenant” o “key”, y comprueban si uno coincide con el valor de entrada; en caso afirmativo, la llamada a Any() en el conjunto de resultados devolverá true.

Por último, puede agregar la anulación de la lógica de validación como en el siguiente ejemplo:

protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
    string issuerID = issuer.TrimEnd('/').Split('/').Last();

    if (ContainsTenant(issuerID))
    {
        if (ContainsKey(thumbprint))
            return true;
    }
    return false;
}

Al recibir un token, WIF llama automáticamente al método; su lógica es muy sencilla, comprueba que el inquilino de emisión esté presente en la lista y que el token se haya firmado con el certificado registrado.

Deberá agregar más métodos a MultiTenantIssuerNameRegistry, pero en lo que concierne a la validación, la clase ya tiene todo lo que necesita.

Para garantizar que se activará en el momento adecuado de la canalización de autenticación, se agregar en el archivo Web.config en lugar de en el IssuerNameRegistry predeterminado.

Abra el archivo Web.config, localice el elemento <issuerNameRegistry> y sustitúyalo por lo siguiente:

<issuerNameRegistry type="ExpenseReport.AADUtils.MultiTenantIssuerNameRegistry, ExpenseReport" />

El primer tutorial introdujo en la aplicación cierta lógica que actualiza las coordenadas del emisor (el emisor y la huella digital del certificado X.509 usado para comprobar la firma del token) cada vez que se inicia la aplicación. Puede encontrar todos los detalles en la sección “Adición de actualización automática de metadatos”.

Ahora que conservamos la información de inquilino y de claves en un archivo distinto a Web.config, ya no estamos obligados a realizar la actualización en el evento Application_Start(): no obstante, es un buen momento en el ciclo de vida de la aplicación, y por tanto en este tutorial lo seguiremos manteniendo.

Sin embargo, necesitamos abordar un par de detalles:

  • El método ValidatingIssuerNameRegistry.WriteToConfig() funciona con la entrada de config original, y la espera en Web.config: no funcionará con nuestro MTINR personalizado.

  • La lista de inquilinos aceptados ya no proviene de los metadatos de un solo inquilino.

Ambos aspectos son bastante fáciles de resolver. Solo tiene que agregar otro método estático a MTINR, que solo actualiza las claves en tenants.xml. Aquí está el código del método, que se agregará a la clase MultiTenantIssuerNameRegistry en el archivo correspondiente MultiTenantIssuerNameRegistry.cs.

public static void RefreshKeys(string metadataAddress)
{
    IssuingAuthority ia = 
           ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataAddress);

    bool newKeys = false;
    foreach (string thumbp in ia.Thumbprints)
        if (!ContainsKey(thumbp))
        {
            newKeys = true;
            break;
        }

    if (newKeys)
    {                
        XElement keysRoot = 
             (XElement)(from tt in doc.Descendants("keys") select tt).First();
        keysRoot.RemoveNodes();
        foreach (string thumbp in ia.Thumbprints)
        {
            XElement node = new XElement("key", new XAttribute("id", thumbp));
            keysRoot.Add(node);
        }
        doc.Save(filePath);           
    }
} 

Este método puede dividirse en tres tareas:

  • La llamada a GetIssuingAuthority(), un método estático ofrecido por ValidatingIssuerNameRegistry, extrae de un documento de metadatos las claves anunciadas por el servicio como las que deberían usarse para verificar los tokens entrantes.

  • El primero de cada bloque comprueba si las claves encontradas en el documento de metadatos ya están presentes en tenants.xml.

  • Si no se ha encontrado ninguna información nueva en los metadatos, el método existe sin cambios; en caso contrario, las claves del archivo actual tenants.xml se borran y se sustituyen por las nuevas del documento de metadatos.

noteNota
Aquí también se aplican las mismas advertencias sobre la validación del extremo de HTTPS de la sección “Adición de actualización automática de metadatos” del primer tutorial.

Esta es toda la lógica que necesita para implementar la actualización automática de claves: el siguiente paso es modificar el archivo Global.asax para llamar a RefreshKeys en lugar de la rutina basada en Web.config. Localice el archivo Global.asax y modifique RefreshValidationSettings de la siguiente manera:

protected void RefreshValidationSettings()
{
    string metadataAddress = 
           ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
    AADUtils.MultiTenantIssuerNameRegistry.RefreshKeys(metadataAddress);
}
noteNota
Puede que haya observado que el método aún se basa en la dirección de metadatos de su inquilino de Microsoft Azure AD, es decir, del inquilino en el que se desarrolló por primera vez la aplicación, según lo capturado por la primera ejecución de la herramienta de identidad y acceso, en lugar de pasar a un extremo independiente de inquilino. De hecho, los dos son bastante equivalentes: la entrada de la aplicación en Azure AD está unida a su inquilino; por tanto, el funcionamiento del extremo de los metadatos correspondiente está garantizado. Por otra parte, pasar al extremo independiente de inquilino haría que el código fuera más fácil de usar como punto inicial para otras aplicaciones. Puede elegir cualquier enfoque, aunque el tutorial ha optado por el que requiere menos cambios en el código.

En una aplicación clásica de LoB, todos los usuarios provienen de la misma autoridad, por lo que el flujo de la autenticación puede decidir, en cualquier momento y de forma inequívoca, si enviar usuarios autenticados. Asimismo, con frecuencia los usuarios ya tienen una sesión activa con la autoridad (piense que los usuarios ya han iniciado sesión mediante las solicitudes de su estación de trabajo en el dominio local de AD) y, por tanto, la fase de autenticación puede realizarse de forma transparente, sin ninguna interrupción desde que se escribe la dirección de la aplicación en el explorador hasta que se obtiene acceso a su interfaz de usuario. Este es el comportamiento predeterminado de las aplicaciones web configuradas para usar protocolos de inicio de sesión como WS-Federation.

En una aplicación para varios inquilinos, los usuarios pueden, por definición, venir de distintos inquilinos: estos son llamados a participar en el proceso de establecimiento de lo que debe implicar la autoridad en la autenticación, en lo que se conoce como Home Realm Discovery (HRD). En Azure AD, esa fase está administrada por el extremo independiente de inquilino, que se encargará de guiar al usuario por la experiencia que corresponda. No se requieren cambio de códigos para esto. Dicho esto, como se muestra a continuación, hay otros aspectos más allá de HRD que pueden requerir cierto trabajo específico.

La aplicación para varios inquilinos suele incluir experiencias que están disponibles para usuarios anónimos; por ejemplo, las páginas de aterrizaje, las características de onboarding, los foros públicos, los de noticias, los puntos de entrada para pruebas gratuitas, etc. El enfoque de protección global no es adecuado para estas características. Esta sección le mostrará cómo cambiar la configuración de WIF para aplicar requisitos de autenticación más específicos, controlador por controlador.

Cambiar el archivo Web.config

  1. Abra Web.config y localice el elemento <authorization> en <system.web> justo debajo del bloque de comentarios denominado “Commented by Identity and Access VS Package”.

    noteNota
    No confunda este elemento por los homónimos de los bloques <location>.

  2. La configuración actual, <deny users="?" />, indica a ASP.NET que solo los usuarios autenticados pueden solicitar recursos desde esta aplicación. Ya no queremos abordar esto desde el archivo Web.config: abordaremos el elemento de autorización completo.

    <!--<authorization>
      <deny users="?" />
    </authorization>-->
    
    Lo que queremos es tener la posibilidad de administrar directamente cómo se controla la autenticación. Conseguiremos esto revirtiendo a la autenticación de formularios: haremos saber a ASP.NET que, cuando sea necesaria la autenticación, debe redirigir a una dirección específica; después, administraremos la solicitud a esa dirección con un nuevo controlador, encargado de activar la autenticación federada.

  3. Localice el elemento <authentication>, coméntelo y copie el siguiente elemento en Web.config, justo debajo del bloque de comentarios que acaba de crear.

    <!--<authentication mode="None" />-->
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    
  4. Desplácese hasta el elemento <system.webServer> y localice la lista <modules>. Verá que hay una directiva <remove> para el módulo FormsAuthentication: coméntelo según se muestra a continuación.

    <modules>
          <!--<remove name="FormsAuthentication" />-->
    
  5. Por último, desplácese al final de Web.config. En el elemento <wsFederation>, que ya ha modificado anteriormente en este tutorial, establezca passiveRedirectEnable como false.

    <wsFederation passiveRedirectEnabled="false" 
    issuer="https://login.windows.net/common/wsfed" realm="https://<your-tenant-name>.onmicrosoft.com/ExpenseReport" requireHttps="false" />
    
    noteNota
    De forma predeterminada, los módulos WIF examinarán todos los códigos de devolución 401 desde la aplicación y, si hay una autoridad configurada correctamente, la transformará en 302 redirecciones que lleven mensajes a la autoridad de confianza. Esta última configuración indica a WIF que ignore los 401 salientes, para que puedan redirigirse a las configuraciones de autenticación de formularios en su lugar (en este caso, a nuestro controlador personalizado).

Crear controlador de la cuenta

  1. La aplicación ya está configurada para redirigir a ~/Account/LogOn en tiempo de autenticación. Creemos un controlador que controle esa ruta específica.

    Haga clic con el botón secundario en la carpeta Controladores, haga clic en Agregar y en Agregar controlador, y denomínelo AccountController.

  2. Agregue lo siguiente mediante directivas:

    using System.IdentityModel.Services;
    
  3. Elimine la implementación predeterminada del controlador y sustitúyala por lo siguiente:

    public void LogOn()
    {
        RedirectResult result;
        if (!Request.IsAuthenticated)
        {
            SignInRequestMessage sirm = FederatedAuthentication.WSFederationAuthenticationModule.CreateSignInRequest("", HttpContext.Request.RawUrl, false);
            result = Redirect(sirm.RequestUrl.ToString());               
        }
        else
        {
            result = Redirect("~/");
        }
        result.ExecuteResult(this.ControllerContext);
    }
    
    

En pocas palabras, el controlador ejecuta prácticamente la misma lógica que la implementada por el módulo WIF, es decir:

  • Si la solicitud no está autenticada:

    • Genera un mensaje de inicio de sesión de WS-Federation, de acuerdo con los ajustes de config (el contenido del elemento <wsFederation>).

    • Redirige el explorador del usuario en consecuencia.

  • Si la solicitud está autenticada:

    • Redirige a la página principal.

La ventaja es que ahora tendrá control total sobre cuándo sucede: como verá más adelante en este tutorial, esto le permitirá agregar un gesto de inicio de sesión explícito en la UI de la aplicación mientras mantiene la ventaja de las redirecciones automáticas activadas por las directivas de autenticación del recurso solicitado.

noteNota
Este tutorial adopta un enfoque minimalista, en el que la experiencia de autenticación lo controla totalmente Azure AD; no obstante, esto no significa necesariamente que tenga que hacer lo mismo en sus soluciones. Ahora tendrá control total sobre lo que sucede cuando se activa el flujo de autenticación: si desea mostrar una vista que solicite más información (o incluso ayude) al usuario, puede hacerlo fácilmente modificando la acción LogOn.

Para conseguir la completa integración de autenticación de formularios de autenticación federada, queda una última cosa por hacer.

Cuando se llame a la acción LogOn en respuesta a una solicitud de un recurso protegido, el módulo de autenticación de formularios incluye la dirección URL del recurso que se origina en el parámetro de consulta ReturnUrl; sin embargo, WIF lo ignora. Hasta ahora, una vez autenticado, el usuario llegaría a la página principal de la aplicación, en lugar de al recurso solicitado. Realizar la redirección interna adicional al recurso es fácil, solo es cuestión de agregar lógica para controlar el evento End_Request en Global.asax.

  1. Abra el archivo Global.asax y agregue la siguiente directiva:

    using System.Security.Claims;
    
  2. A continuación, agregue el siguiente método:

    protected void Application_EndRequest(object sender, EventArgs e)
    {
        string wsFamRedirectLocation = HttpContext.Current.Response.RedirectLocation;
        if (wsFamRedirectLocation != null && 
            wsFamRedirectLocation.Contains("ReturnUrl") && 
            ClaimsPrincipal.Current.Identity.IsAuthenticated)
        {
            HttpContext.Current.Response.RedirectLocation =
                        HttpUtility.ParseQueryString(
                          wsFamRedirectLocation.Split('?')[1])["ReturnUrl"];
        }
    }
    

El método se ejecuta al final de la canalización de procesamiento de la solicitud de HTTP. Revisa la ubicación del encabezado HTTP, que se usa en caso de redirección: si no está vacío, el usuario se autentica (por tanto, el flujo de protocolo de WS-Federation ya se ha realizado por completo) y contiene ReturnUrl (indicación de que almacena información de devolución de autenticación de formularios); después, el explorador se redirige a la ubicación ReturnUrl.

Asegurar los controladores

Ahora que ha desactivado la protección de autenticación global, cada controlador es responsable de especificar sus requisitos de autenticación. La forma más sencilla de hacerlo es decorando cada acción con el atributo [Authorize], como haría con cualquier otro escenario de autenticación de ASP.NET.

WarningAdvertencia
Aunque el tutorial cubre aplicaciones de estilo MVC, es perfectamente posible seguir el mismo enfoque en los formularios web (por ejemplo, aprovechando los elementos <location> y <authorization> en el archivo Web.config).

A continuación puede ver la modificación aplicada a la acción About() del controlador Home:

[Authorize]
public ActionResult About()
{
    ViewBag.Message = "Your app description page.";

    return View();
}

Haga lo mismo para cada acción del controlador Home, con la excepción de Index(). En este tutorial, Index se reserva para el punto de entrada autenticado para la experiencia de la aplicación.

En el primer tutorial, modificó Index para extraer información del usuario de las solicitudes: ahora que los usuarios autenticados podrán obtener acceso a la acción, ese código fallará, dado que la ausencia de un usuario autenticado implica que no haya solicitudes disponibles. Coméntelo y sustituya la asignación de ViewBag.Message por el mensaje que vea adecuado.

Public ActionResult Index()
{
    //ClaimsPrincipal cp = ClaimsPrincipal.Current;
    //string fullname =
    //       string.Format(“{0} {1}”, cp.FindFirst(ClaimTypes.GivenName).Value,
    //       cp.FindFirst(ClaimTypes.Surname).Value);
    ViewBag.Message = "Welcome to the Expense Note App";
    return View();
}
noteNota
El tutorial no proporciona instrucciones sobre cómo hacerlo; por tanto, si lo desea, puede agregar (aquí o en la vista asociada) un mensaje de bienvenida para el usuario que explique cómo usar la aplicación. Esto resulta especialmente práctico más adelante, en las partes de suscripción.

Cambiar gestos para inicio de sesión en el archivo _Layout.cshtml

Los cambios que ha hecho hasta aquí activarán el flujo de autenticación en cuanto el usuario haga clic en un elemento de UI que solicite una acción protegida por [Authorize]. Sin embargo, es muy común para aplicaciones no cubiertas por la protección global ofrecer un gesto explícito de la UI para iniciar sesión.

Para ello, revisitaremos el texto de bienvenida del usuario en el área superior de la pantalla, que se define en _Layout.cshtml, donde trabajamos al explicar cómo agregar el cierre de sesión en el tutorial Adición de inicio de sesión. A su vez lo integramos todo en _Layout.cshtml, pero en este tutorial deberemos agregar más funcionalidad, lo que requiere cierta refactorización.

  1. Abra _Layout.cshtml, localice la sección de inicio de sesión <section id=”login”> y modifíquela de la siguiente forma:

    <section id=”login”>
       @Html.Partial("_LoginPartial")
       @* @if (Request.IsAuthenticated) 
        {                       
           <text> Hello, <span class=”username”>@User.Identity.Name</span>! @Html.ActionLink(“Signout”,”SignOut”, “SignOut”)</text>
        } 
        else {          
            <text>  You are not authenticated </text> 
         } *@
    </section>
    
    
  2. Una vez hecho esto, haga clic con el botón secundario en la carpeta Vistas/Compartidas, haga clic en Agregar y en Vista, nombre la nueva vista como _LoginPartial, elija Razor como el motor de visualización y, a continuación, haga clic en Agregar.

  3. Sustituya el contenido de _LoginPartial.cshtml por el siguiente código:

    @if (Request.IsAuthenticated) 
        {                       
           <text> Hello, <span class=”username”>@User.Identity.Name</span>! @Html.ActionLink("Signout","SignOut", "SignOut")</text>
        } 
        else {          
             <ul>       
            <li>@Html.ActionLink("Sign in", "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "signLink" })</li>
        </ul> 
         }
    

Esta es la misma lógica integrada en el tutorial de LoB, con la única diferencia de que el texto “no está autenticado” se ha sustituido por un vínculo en el que se puede hacer clic, que activará la acción LogOn del controlador Account.

El controlador de cierre de sesión

No se requieren cambios para adaptar la lógica de cierre de sesión al caso de varios inquilinos. El controlador ya estaba configurado para recuperar el extremo del emisor para usar el flujo de cierre de sesión de Web.config; eso significa que ahora seleccionará automáticamente el cambio para el extremo independiente de inquilinos que aplicó al principio del tutorial.

Personalizar la lógica de acceso a gráficos

La lógica de acceso a la API de gráficos ya está diseñada para crear extremos de recursos sobre la base del tenantID recibido en las solicitudes que describen al usuario actual; como tal, seguirá funcionando incluso cuando los usuarios empiecen a llegar de varios inquilinos.

noteNota
Una de las características de Azure AD que hace esto posible es el hecho de que ClientId y el secreto del cliente no cambian entre los inquilinos: cuando un administrador de un inquilino da consentimiento a la aplicación para que obtenga acceso a su inquilino de Azure AD, la aplicación de la vista correspondiente de su inquilino tendrá los mismos valores que los demás. No obstante, tenga en cuenta que esto no significa que un administrador malicioso puede obtener el secreto de la aplicación e intentar usarlo contra otro inquilino de Azure AD que dio el consentimiento a la misma aplicación. Como ha aprendido en el tutorial de la API de gráficos, los secretos no pueden recuperarse tras la creación.

La última característica que necesitamos agregar a la aplicación para completar la transición a varios inquilinos es la capacidad de incorporar nuevas organizaciones de clientes.

Como se explica a lo largo del documento, las aplicaciones marcadas como externamente disponibles en Azure AD se asocian a una dirección URL diseñada especialmente, que puede usarse por los clientes potenciales para conceder consentimiento para que la aplicación obtenga acceso a su directorio y tenga una entrada para la aplicación aprovisionada automáticamente a sus inquilinos. En esta sección, agregará un controlador SignUp que redirige a los usuarios a la URL de consentimiento, así como un gesto de UI para activar la acción.

noteNota
Aquí agregamos la característica directamente en la aplicación; no obstante, una vez que comprenda cómo funciona el mecanismo, nada le impide implementar la lógica de consentimiento fuera de la aplicación, agruparla con vínculos de consentimiento para otras aplicaciones de su cartera, etc.

  1. Agregue un controlador SignUp vacío, siguiendo las instrucciones para creaciones de controlador proporcionadas anteriormente en los tutoriales.

  2. Agregue lo siguiente mediante directivas:

    using System.Configuration;
    
    
  3. Sustituya la implementación predeterminada del controlador con los dos métodos siguientes:

    private string CreateConsentURL(string clientId, string requestedPermissions, 
                                    string consentReturnURL, string context)
    {
        string consentUrl = string.Format("https://account.activedirectory.windowsazure.com/Consent.aspx?ClientId={0}", clientId);
        if(!String.IsNullOrEmpty(requestedPermissions))
          consentUrl+= "&RequestedPermissions="+requestedPermissions;
        if(!String.IsNullOrEmpty(consentReturnURL))
            consentUrl+= "&ConsentReturnURL="+HttpUtility.UrlEncode(
                consentReturnURL+(String.IsNullOrEmpty(context) ?
                                         String.Empty : "?"+context ));
        return consentUrl;        
    }
    public void SignUp()
    {
        string request = System.Web.HttpContext.Current.Request.Url.ToString();
        string returnurl = request.Substring(0, request.Length -6);
        string clientID = ConfigurationManager.AppSettings["ClientId"];
    
        RedirectResult result = 
           Redirect(CreateConsentURL(clientID, "DirectoryReaders", returnurl, string.Empty));
        result.ExecuteResult(this.ControllerContext);
    } 
    
    

El primer método crea la URL que permite que los clientes potenciales den a su aplicación consentimiento para obtener acceso a sus inquilinos de directorios. Aunque el portal de administración de Azure le proporciona la dirección URL de consentimiento para su aplicación, tener el código que lo genera a partir de parámetros básicos le dará una flexibilidad adicional. Examinemos los parámetros y su semántica:

  • ClientId representa el identificador de su aplicación. Lo agregó en el config durante el tutorial de API de gráficos. Es obligatorio.

  • RequestedPermissions expresa el nivel de acceso a directorios que desea que el cliente potencial conceda a la aplicación. Los valores posibles reflejan las opciones de nivel de acceso que tenía en el portal de administración de Azure en el momento del registro, aunque aquí es libre de solicitar distintos niveles a los que seleccionó en la UI para su propio inquilino. Estos valores son:

    • DirectoryReaders: use este valor para solicitar acceso de lectura al directorio.

    • DirectoryWriters: use este valor para solicitar acceso lectura/escritura.

    • <Empty>: no especifique ningún valor si solo desea tener capacidades de SSO.

  • ConsentReturnUrl indica a dónde redirigir la sesión del explorador una vez que el usuario ha concedido (o denegado) permisos a la aplicación. Quizá quiera especificar una ruta en su aplicación donde reside la lógica de procesamiento de suscripciones. Más adelante se proporcionan más detalles sobre esto.

El método CreateConsentURL expone todos los parámetros a continuación, además de uno adicional. El parámetro de contexto se ofrece como forma para incluir información adicional, que se conducirá a la página de consentimiento codificada con ConsentReturnUrl y volverá una vez que se haya respetado la redirección. Para su comodidad, se ofrece como parámetro independiente, por lo que no tiene que mezclar la dirección URL de retorno principal con la lógica de contexto.

El contexto puede ser útil si desea realizar un seguimiento de información adicional sobre la solicitud. Por ejemplo, la redirección al consentimiento se realizará muy frecuentemente como parte de su propio proceso de incorporación específico de la aplicación, y probablemente desee realizar un seguimiento de algún contexto.

El segundo método es la acción real que activa la redirección. Invoca a CreateConsentURL que pasa como parámetros ClientId desde el config, la raíz del controlador actual como URL de devolución, DirectoryReaders como el nivel de acceso solicitado y nada como contexto. A continuación, el método prosigue con la redirección a la URL creada recientemente.

Ahora que ha agregado la lógica para activar la redirección a la dirección URL de consentimiento, necesita completar el flujo proporcionando el código que procesará los resultados. Según establece la elección de ReturnURL, este tutorial colocará el código en la acción Index del controlador SignUp.

  1. Agregue la directiva de uso siguiente.

    using ExpenseReport.AADUtils;
    
  2. Agregue el método siguiente al controlador SignUp.

    public void Index()
    {
        if ((!string.IsNullOrEmpty(Request.QueryString["TenantId"]) && 
            (!string.IsNullOrEmpty(Request.QueryString["Consent"]))))
        {
            if (Request.QueryString["Consent"].Equals("Granted",
                                                StringComparison.InvariantCultureIgnoreCase))
            {
                MultiTenantIssuerNameRegistry.AddTenant(Request.QueryString["TenantId"]);
            }
        
            //redirect to SignIn
            RedirectResult result = Redirect("~/Account/LogOn");
            result.ExecuteResult(this.ControllerContext);
        }
    }
    
    noteNota
    El código de método no incluye administración de errores.

Tras conceder o denegar el acceso, Azure AD respeta la redirección a ReturnURL e incorpora un par de parámetros adicionales:

  • Consent: indica el resultado de la operación. Puede tener valores “Granted” o “Denied”.

  • TenantID: si el parámetro Consent tiene el valor “Granted”, TenantID estará presente y contendrá el identificador del inquilino que acaba de consentir las solicitudes de acceso de la aplicación.

La finalidad de este método, por tanto, consiste en capturar el identificador de los inquilinos que aprovisionaron a la aplicación y realizar un seguimiento de estos como autoridades válidas en la colección de MTINR. Según la lógica de validación creada anteriormente en el tutorial, esta permitirá a los usuarios que provengan del nuevo inquilino aceptarse en el momento del inicio de sesión.

El código anterior examina la dirección URL de la solicitud, y si encuentra que contiene un nuevo inquilino, lo guarda en MTINR (usando un método que implementaremos en breve).

noteNota
Esta implementación no agrega restricciones a las solicitudes que llegan a esta ruta, y si tienen el formato correcto, el contenido del parámetro TenantID finalizará en el almacén de MTINR. Este no sería el comportamiento deseado en una aplicación real, ya que pueden ser objeto de abuso y provocar un desbordamiento de su almacén con entradas falsas o para obtener acceso no autorizado.

Como se ha mencionado antes, la experiencia del consentimiento probablemente sería parte de su propio proceso de incorporación (por ejemplo, al recopilar información sobre el cliente potencial, obtener pagos u otros pasos de incorporación que requiera su aplicación). Como tal, debería asegurarse de que incluye ese contexto en la creación de la URL de consentimiento y de que lo valida al procesar la respuesta; eso garantizará que se rechacen las solicitudes fraudulentas.

Una vez guardado el inquilino, el método concluye activando un inicio de sesión para que el usuario pueda empezar a obtener acceso a la aplicación inmediatamente.

noteNota
Si su proceso de incorporación requiere más pasos, puede elegir retrasar el inicio de sesión y servir una vista en su lugar.

La acción Index del controlador SignUp introdujo un nuevo método MTINR, AddTenant. Agreguemos una implementación para esto. Abra MultiTenantIssuerNameRegistry.cs y agregue el siguiente método a la clase MultiTenantIssuerNameRegistry:

public static void AddTenant(string tenantId)
{
    if (!ContainsTenant(tenantId))
    {
        XElement node = new XElement("tenant", new XAttribute("id", tenantId));
        XElement tenantsRoot = 
                (XElement)(from tt in doc.Descendants("tenants") select tt).First();

        tenantsRoot.Add(node);
        doc.Save(filePath);
    }
}

El método AddTenant es muy sencillo: si tenantId en la entrada ya no existe en el almacén (la operación de consentimiento es idempotent), agrega una nueva entrada en el nodo <tenants>.

Por último, la aplicación necesita un gesto de UI para activar el flujo de suscripción. Esto puede conseguirse fácilmente agregando una entrada en _LoginPartial.cshtml: abra el archivo y cambie el bloque <li> para la suscripción como se muestra a continuación.

@if (Request.IsAuthenticated) 
    {                       
       <text> Hello, <span class="username">@User.Identity.Name</span>! @Html.ActionLink("Signout","SignOut", "SignOut")</text>
    } 
    else {          
         <ul>  
       <li>@Html.ActionLink("Sign up", "SignUp", "SignUp", routeValues: null, htmlAttributes: new { id = "signupLink" })</li>     
        <li>@Html.ActionLink("Sign in", "LogOn", "Account", routeValues: null, htmlAttributes: new { id = "signLink" })</li>
    </ul> 
     }

noteNota
La UI actual sigue un enfoque muy minimalista. En una aplicación real, puede que desee realizar la semántica de los controles de suscripción e inicio de sesión: las formas posibles de conseguir eso incluyen un texto de vínculo más detallado y una explicación en el cuerpo principal de la página principal, entre otros.

En esta sección le presentaremos algunas opciones que puede aprovechar para probar su nueva aplicación para varios inquilinos.

Para probar una aplicación para varios inquilinos en todos sus aspectos, lo mejor es tener disponible un segundo inquilino de Azure AD que pueda usar para llevar a cabo todos los flujos relacionados con el consentimiento en la aplicación de ejemplo. En este momento, esto significa que necesita tener acceso a otra suscripción de Azure. Puede obtenerlo siguiendo por segunda vez el flujo de creación de directorios y de suscripción descrito al principio del primer tutorial; de forma alternativa, puede seguir las instrucciones indicadas aquí para registrarse para una suscripción de prueba con un usuario de un inquilino existente de Azure AD.

Dado que la operación de concesión de consentimiento es idempotente, también podría usar su propio inquilino de Azure AD para experimentar con la suscripción: eso le ahorraría la tarea de crear una segunda suscripción; no obstante, no le permitiría ver lo que sucede cuando intenta iniciar sesión con un inquilino no aprovisionado, ni experimentar el flujo de revocación de consentimiento (dado que, para su inquilino, la aplicación sigue siendo LoB, aprovisionada explícitamente y, por tanto, sin necesidad expresa de pasos de concesión de consentimiento).

Otro método sería usar un inquilino de Azure AD no relacionado necesariamente con una suscripción a Azure, como el inquilino de directorio que obtiene al suscribirse a servicios como Office365 o Intune.

noteNota
Solo los administradores de inquilinos de Azure AD pueden conceder consentimiento a aplicaciones. Independientemente del método de prueba que elija, necesita tener acceso a credenciales de usuario de administrador de inquilino. Si ha creado su inquilino de Azure AD usando una suscripción a Azure basada en Live ID, debe asegurarse de que su inquilino contiene al menos un usuario de inquilino que pertenezca al rol de administrador global. Puede crear uno fácilmente siguiendo las instrucciones del primer tutorial, asegurándose de que elige “Administrador global” en la pantalla del perfil de usuario.

Ahora puede, al fin, ver la aplicación en acción para varios inquilinos. Si desea observar el trabajo interno de la aplicación, agregue un punto de interrupción en cualquiera de los fragmentos de código que agregó durante el tutorial.

Ejecutar la aplicación

noteNota
Si usa un inquilino de Azure AD distinto al suyo, puede que necesite cerrar todas las instancias del explorador antes de empezar; en otro caso, podría indicar a Visual Studio que inicie la sesión de depuración en un explorador web distinto al predeterminado. Esto puede ser necesario para garantizar que no haya interferencia entre sus sesiones web existentes y la de depuración.

En Visual Studio, presione F5.

Página principal de la aplicación

Según lo esperado, en lugar de ser redirigido inmediatamente a Azure AD para la autenticación, se le presentará la raíz de la aplicación.

En la barra superior, puede localizar la sección de inicio de sesión, que muestra correctamente los botones de suscripción e inicio de sesión dado que no está actualmente autenticado.

Probemos el flujo de incorporación. Haga clic en el botón de suscripción.

Iniciar sesión en AAD

Se le redirigirá inmediatamente a la solicitud de autenticación de Azure AD. Inicie sesión usando las credenciales de administrador del inquilino de Azure AD que decidió usar para la prueba.

Conceder acceso

noteNota
Si recibe un error aquí, compruebe de nuevo que está iniciando sesión con un administrador desde un inquilino de Azure AD. Actualmente, los usuarios de Live ID no se pueden usar para conceder acceso en el flujo descrito aquí.

Una vez autenticado correctamente, Azure AD le pide que conceda o deniegue el acceso a su inquilino de directorio para la aplicación Expense Reporting, para el nivel de acceso especificado en el controlador SignUp.

Haga clic en Conceder.

Página principal de la aplicación

La página registra el consentimiento en el directorio del usuario actual; después, activa un inicio de sesión. Dado que ya se ha autenticado con Azure AD en el momento del consentimiento, no necesita volver a especificar credenciales y verá que su sesión se inicia automáticamente. La sección de inicio de sesión refleja el nuevo estado, mostrando el nombre de usuario y el botón de cierre de sesión.

Puede hacer clic en cualquier parte de la aplicación para confirmar que está en una sesión autenticada: por ejemplo, haga clic en la pestaña Usuarios: podrá ver la lista de usuarios.

noteNota
Cuando una aplicación para varios inquilinos intenta adquirir un token de acceso a la API de gráficos para un inquilino de Windows AD que ha dado su consentimiento para la aplicación recientemente, la solicitud de token podrían producir un error ACS50012. Para resolver el problema, espere unos minutos e inténtelo de nuevo. O bien, pida al administrador del inquilino que dio su consentimiento que inicie sesión en la aplicación después de dar su consentimiento. Para obtener más información, vea Códigos de error de ACS.

Probemos el cierre de sesión. Haga clic en el botón de cierre de sesión.

Cierre de sesión

Tras un par de redirecciones, llegará a la vista SignOut.

Para confirmar que realmente ha cerrado la sesión, haga clic de nuevo en la pestaña Usuarios: esta vez, se le pedirá que inicie sesión.

Escriba sus credenciales. Observará que, después de las redirecciones de la fase de autenticación, el explorador le muestra correctamente la UI de usuarios que solicitó en primer lugar. Esto muestra que la lógica agregada en el evento End_Request ha funcionado según lo esperado.

Revocado de derechos de acceso

Solo podrá realizar las tareas mostradas en esta sección si ha aprovisionado a la aplicación en un inquilino de Azure AD distinto del suyo propio y lo ha asociado a una suscripción a Azure.

Desplácese hasta el portal de administración de Azure e inicie sesión como administrador del inquilino de Azure AD que usó para aprovisionar a la aplicación.

Vaya a la pestaña de Active Directory, seleccione su directorio, elija Aplicaciones, localice la aplicación Expense Reporting y haga clic en ella.

Detalles de las aplicaciones integradas

Mientras que en el inquilino en que se ha creado la aplicación obtendría la UI de configuración que le permitiría cambiar la configuración de la aplicación, aquí desempeña el rol de cliente que ha comprado la aplicación: obtiene una página de descripción genérica, que resume las coordenadas principales de la aplicación y los niveles de acceso concedidos.

Haga clic en Administrar acceso en la barra de comandos inferior.

Administrar acceso

Esta UI le permite revocar el acceso a la aplicación, si ya no desea que pueda obtener acceso a su directorio en los términos concedidos.

Haga clic en Revocar.

Acceso eliminado

La aplicación se ha eliminado y ya no está en la lista Aplicaciones.

Vuelva a Visual Studio y presione de nuevo F5.

Haga clic en Iniciar sesión, autentíquese como administrador del inquilino de cliente y vea qué sucede.

Error de ACS50000.

El usuario se autenticará correctamente con el directorio, pero la aplicación que sería el destinatario del token de autenticación ya no se muestra como el que tiene acceso al inquilino de directorio del usuario: como resultado, el directorio no emite el token solicitado y muestra al usuario una página de error.

Adiciones de comunidad

Mostrar:
© 2014 Microsoft