Crear un complemento de ASP.NET Office que usa el inicio de sesión único

Los usuarios pueden iniciar sesión en Office, y el complemento de Office Web puede aprovecharse de este proceso de inicio de sesión para autorizar a los usuarios a su complemento y a Microsoft Graph sin necesitar que los usuarios inicien sesión por segunda vez. Este artículo le guiará por el proceso de habilitación del inicio de sesión único (SSO) en un complemento.

En el ejemplo se muestra cómo crear las siguientes partes:

  • Código del lado cliente que proporciona un panel de tareas que se carga en Microsoft Excel, Word o PowerPoint. El código del lado cliente llama a la API getAccessToken() de Office JS para obtener el token de acceso de SSO para llamar a las API REST del lado servidor.
  • Código del lado servidor que usa ASP.NET Core para proporcionar una única API /api/filesREST. El código del lado servidor usa la biblioteca de autenticación de Microsoft para .NET (MSAL.NET) para todo el control de tokens, la autenticación y la autorización.

En el ejemplo se usa sso y el flujo en nombre de (OBO) para obtener tokens de acceso correctos y llamar a las API de Microsoft Graph. Si no está familiarizado con el funcionamiento de este flujo, consulte Funcionamiento del inicio de sesión único en tiempo de ejecución para obtener más detalles.

Requisitos previos

  • Visual Studio 2019 o posterior.

  • Carga de trabajo de desarrollo de Office/SharePoint al configurar Visual Studio.

  • Al menos algunos archivos y carpetas almacenados en OneDrive para la Empresa en la suscripción de Microsoft 365.

  • Compilación de Microsoft 365 que admite el conjunto de requisitos de IdentityAPI 1.3. Puede calificar para una suscripción de desarrollador de Microsoft 365 E5, que incluye un espacio aislado para desarrolladores, a través del Programa para desarrolladores de Microsoft 365; para obtener más información, consulte las preguntas más frecuentes. El espacio aislado para desarrolladores incluye una suscripción de Microsoft Azure que puede usar para los registros de aplicaciones en los pasos posteriores de este artículo. Si lo prefiere, puede usar una suscripción de Microsoft Azure independiente para los registros de aplicaciones. Obtenga una suscripción de prueba en Microsoft Azure.

Configurar el proyecto de inicio

Clone o descargue el repositorio en Office Add-in ASPNET SSO.

Nota:

Hay dos versiones del ejemplo.

  • La carpeta Begin es un proyecto de inicio. La interfaz de usuario y otros aspectos del complemento que no están conectados directamente al SSO o a la autorización ya están listos. Las secciones posteriores de este artículo le guiarán a través del proceso para completarlo.
  • La carpeta Complete contiene el mismo ejemplo con todos los pasos de codificación de este artículo completados. Para usar la versión completada, siga las instrucciones de este artículo, pero reemplace "Begin" por "Complete" (Completar) y omita las secciones Code the client side (Código del lado cliente ) y Code the server side (Código del lado servidor).

Use los siguientes valores para los marcadores de posición para los pasos de registro de aplicaciones posteriores.

Marcador de posición Valor
<add-in-name> Office-Add-in-ASPNET-SSO
<fully-qualified-domain-name> localhost:44355
Permisos de Microsoft Graph profile, openid, Files.Read

Registre el complemento con Plataforma de identidad de Microsoft

Debe crear un registro de aplicación en Azure que represente el servidor web. Esto permite la compatibilidad con la autenticación para que se puedan emitir tokens de acceso adecuados al código de cliente en JavaScript. Este registro admite tanto el inicio de sesión único en el cliente como la autenticación de reserva mediante la biblioteca de autenticación de Microsoft (MSAL).

  1. Inicie sesión en el Azure Portal con las credenciales de administrador en el inquilino de Microsoft 365. Por ejemplo, MyName@contoso.onmicrosoft.com.

  2. Seleccione Registros de aplicaciones. Si no ve el icono, busque "Registro de aplicaciones" en la barra de búsqueda.

    Página principal Azure Portal.

    Aparece la página Registros de aplicaciones.

  3. Seleccione Nuevo registro.

    Nuevo registro en el panel Registros de aplicaciones.

    Aparece la página Registrar una aplicación.

  4. En la página Registrar una aplicación, establezca los valores siguientes.

    • Establezca Nombre como <add-in-name>.
    • Establezca Tipos de cuenta admitidosen Cuentas en cualquier directorio organizativo (cualquier directorio de Azure AD: multiinquilino) y cuentas personales de Microsoft (por ejemplo, Skype, Xbox).
    • Establezca el URI de redirección para usar la aplicación de página única (SPA) de la plataforma y el URI en https://<fully-qualified-domain-name>/dialog.html.

    Registre un panel de aplicación con el nombre y la cuenta admitida completadas.

  5. Seleccione Registrar. Se muestra un mensaje que indica que se creó el registro de la aplicación.

    Mensaje que indica que se creó el registro de la aplicación.

  6. Copie y guarde los valores para el identificador de aplicación (cliente) y el identificador de directorio (inquilino). Deberá usar ambos en procedimientos posteriores.

    Panel de registro de aplicaciones para Contoso que muestra el identificador de cliente y el identificador de directorio.

Adición de un secreto de cliente

A veces denominado contraseña de aplicación, un secreto de cliente es un valor de cadena que la aplicación puede usar en lugar de un certificado para la identidad propia.

  1. En el panel izquierdo, seleccione Certificados & secretos. A continuación, en la pestaña Secretos de cliente, seleccione Nuevo secreto de cliente.

    El panel Certificados & secretos.

    Aparece el panel Agregar un secreto de cliente .

  2. Agregue una descripción para el secreto de cliente.

  3. Seleccione una expiración para el secreto o especifique una duración personalizada.

    • La duración del secreto de cliente está limitada a dos años (24 meses) o menos. No se puede especificar una duración personalizada de más de 24 meses.
    • Microsoft recomienda establecer un valor de expiración de menos de 12 meses.

    Agregue un panel secreto de cliente con la descripción y expire completado.

  4. Seleccione Agregar. Se crea el nuevo secreto y se muestra temporalmente el valor.

Importante

Registre el valor del secreto para usarlo en el código de la aplicación cliente. Este valor secreto nunca se vuelve a mostrar después de salir de este panel.

Exponer una API web

  1. En el panel izquierdo, seleccione Exponer una API.

    Aparece el panel Exponer una API .

    El panel Exponer una API de un registro de aplicación.

  2. Seleccione Establecer para generar un URI de identificador de aplicación.

    Botón Establecer en el panel Exponer una API del registro de la aplicación.

    La sección para establecer el URI del identificador de aplicación aparece con un URI de identificador de aplicación generado con el formato api://<app-id>.

  3. Actualice el URI del identificador de aplicación a api://<fully-qualified-domain-name>/<app-id>.

    Edite el panel URI del identificador de aplicación con el puerto localhost establecido en 44355.

    • El URI de id. de aplicación se rellena previamente con el identificador de aplicación (GUID) con el formato api://<app-id>.
    • El formato uri del identificador de aplicación debe ser: api://<fully-qualified-domain-name>/<app-id>
    • Inserte el fully-qualified-domain-name valor entre api:// y <app-id> (que es un GUID). Por ejemplo, api://contoso.com/<app-id>.
    • Si usa localhost, el formato debe ser api://localhost:<port>/<app-id>. Por ejemplo, api://localhost:3000/c6c1f32b-5e55-4997-881a-753cc1d563b7.

    Para obtener más detalles sobre el URI del identificador de aplicación, consulte Identificador de manifiesto de aplicaciónInquilinouris.

    Nota:

    Si recibe un error que indica que el dominio ya tiene propietario, pero es usted su propietario, siga el procedimiento de Inicio rápido: agregar un nombre de dominio personalizado a Azure Active Directory para registrarlo y repita este paso. (Este error también puede producirse si no ha iniciado sesión con las credenciales de un administrador en el inquilino de Microsoft 365. Consulte el paso 2. Cierre la sesión e inicie sesión de nuevo con las credenciales de administrador y repita el proceso desde el paso 3).

Agregar un ámbito

  1. En la página Exponer una API , seleccione Agregar un ámbito.

    Seleccione el botón Agregar un ámbito.

    Se abre el panel Agregar un ámbito .

  2. En el panel Agregar un ámbito , especifique los atributos del ámbito. En la tabla siguiente se muestran los valores de ejemplo para y el complemento de Outlook que requieren los profilepermisos , openid, Files.ReadWritey Mail.Read . Modifique el texto para que coincida con los permisos que necesita el complemento.

    Campo Description Valores
    Nombre de ámbito Nombre del ámbito. Una convención de nomenclatura de ámbito común es resource.operation.constraint. Para el inicio de sesión único, debe establecerse en access_as_user.
    Quién puede dar su consentimiento Determina si se requiere el consentimiento del administrador o si los usuarios pueden dar su consentimiento sin la aprobación del administrador. Para aprender el inicio de sesión único y los ejemplos, se recomienda establecerlo en Administradores y usuarios.

    Seleccione Solo administradores para permisos con privilegios superiores.
    Administración nombre para mostrar del consentimiento Una breve descripción del propósito del ámbito visible solo para los administradores. Read/write permissions to user files. Read permissions to user mail and profiles.
    Administración descripción del consentimiento Una descripción más detallada del permiso concedido por el ámbito que solo ven los administradores. Allow Office to have read/write permissions to all user files and read permissions to all user mail. Office can call the app's web APIs as the current user.
    Nombre para mostrar del consentimiento del usuario Breve descripción del propósito del ámbito. Se muestra a los usuarios solo si establece Who can consent to Admins and users (Quién puede dar su consentimiento a administradores y usuarios). Read/write permissions to your files. Read permissions to your mail and profile.
    Descripción del consentimiento del usuario Descripción más detallada del permiso concedido por el ámbito. Se muestra a los usuarios solo si establece Who can consent to Admins and users (Quién puede dar su consentimiento a administradores y usuarios). Allow Office to have read/write permissions to your files, and read permissions to your mail and profile.
  3. Establezca Estadoen Habilitado y, a continuación, seleccione Agregar ámbito.

    Establezca el estado en habilitado y seleccione el botón Agregar ámbito.

    El nuevo ámbito definido se muestra en el panel.

    Nuevo ámbito que se muestra en el panel Exponer una API.

    Nota:

    La parte del dominio del Nombre de ámbito que aparece justo debajo del campo de texto debe coincidir automáticamente con el URI de identificador de aplicación establecido en el paso anterior, con /access_as_user anexado al final; por ejemplo, api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user.

  4. Seleccione Agregar una aplicación cliente.

    Seleccione Agregar una aplicación cliente.

    Aparece el panel Agregar una aplicación cliente .

  5. En Id . de cliente , escriba ea5a67f6-b6f3-4338-b240-c655ddc3cc8e. Este valor autoriza previamente todos los puntos de conexión de aplicación de Microsoft Office. Si también desea autorizar previamente Office cuando se usa dentro de Microsoft Teams, agregue 1fec8e78-bce4-4aaf-ab1b-5451cc387264 (escritorio de Microsoft Teams y dispositivos móviles de Teams) y 5e3ce6c0-2b1f-4285-8d4b-75ee78787346 (Teams en la web).

    Nota:

    El ea5a67f6-b6f3-4338-b240-c655ddc3cc8e identificador autoriza previamente a Office en todas las plataformas siguientes. Como alternativa, puede escribir un subconjunto adecuado de los siguientes identificadores si, por cualquier motivo, desea denegar la autorización a Office en algunas plataformas. Si lo hace, deje fuera los identificadores de las plataformas desde las que desea retener la autorización. Los usuarios del complemento en esas plataformas no podrán llamar a las API web, pero otras funciones del complemento seguirán funcionando.

    • d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)
    • 93d53678-613d-4013-afc1-62e9e444a0a5 (Office en la Web)
    • bc59ab01-8403-45c6-8796-ac3ef710b3e3 (Outlook en la Web)
  6. En Ámbitos autorizados, active la api://<fully-qualified-domain-name>/<app-id>/access_as_user casilla .

  7. Seleccione Agregar aplicación.

    Panel Agregar una aplicación cliente.

Adición de permisos de Microsoft Graph

  1. En el panel izquierdo, seleccione Permisos de API.

    Panel Permisos de API.

    Se abre el panel Permisos de API .

  2. Seleccione Agregar un permiso

    Agregar un permiso en el panel permisos de API.

    Se abre el panel Solicitar permisos de API .

  3. Seleccione Microsoft Graph.

    El panel Solicitar permisos de API con el botón Microsoft Graph.

  4. Seleccione Permisos delegados

    El panel Solicitar permisos de API con permisos delegados.

  5. En el cuadro de búsqueda Seleccionar permisos , busque los permisos que necesita el complemento. Por ejemplo, para un complemento de Outlook, puede usar profile, openid, Files.ReadWritey Mail.Read.

    Nota:

    El permiso User.Read podría aparecer ya de forma predeterminada. Se recomienda solicitar solo los permisos necesarios, por lo que se recomienda desactivar la casilla para este permiso si el complemento no lo necesita realmente.

  6. Active la casilla para cada permiso tal como aparece. Tenga en cuenta que los permisos no permanecerán visibles en la lista a medida que seleccione cada uno de ellos. Después de seleccionar los permisos que necesita el complemento, seleccione Agregar permisos.

    El panel Solicitar permisos de API con algunos permisos seleccionados.

  7. Seleccione Conceder consentimiento de administrador para [nombre de inquilino]. Seleccione para la confirmación que aparece.

Configuración de la versión del token de acceso

Debe definir la versión del token de acceso que sea aceptable para la aplicación. Esta configuración se realiza en el manifiesto de aplicación de Azure Active Directory.

Definición de la versión del token de acceso

La versión del token de acceso puede cambiar si elige un tipo de cuenta distinto de Cuentas en cualquier directorio organizativo (cualquier directorio de Azure AD: multiinquilino) y cuentas personales de Microsoft (por ejemplo, Skype, Xbox). Siga estos pasos para asegurarse de que la versión del token de acceso es correcta para el uso del inicio de sesión único de Office.

  1. En el panel izquierdo, seleccione Manifiesto.

    Seleccione Manifiesto de Azure.

    Aparece el manifiesto de aplicación de Azure Active Directory.

  2. Introduzca 2 como valor de la accessTokenAcceptedVersion propiedad.

    Valor de la versión del token de acceso aceptado.

  3. Seleccione Guardar.

    Aparece un mensaje en el explorador que indica que el manifiesto se actualizó correctamente.

    Mensaje actualizado del manifiesto.

Enhorabuena. Ha completado el registro de la aplicación para habilitar el inicio de sesión único para el complemento de Office.

Configurar la solución

  1. En la raíz de la carpeta Begin , abra el archivo de solución (.sln) en Visual Studio. Haga clic con el botón derecho en el nodo superior del Explorador de soluciones (el nodo de solución, no los nodos del proyecto) y después seleccione Establecer proyectos de inicio.

  2. En Propiedades comunes, seleccione Proyecto de inicio y después, Varios proyectos de inicio. Asegúrese de que la acción de ambos proyectos está establecida en Inicio y que el proyecto Office-Add-in-ASPNETCoreWebAPI aparece en primer lugar. Cierre el cuadro de diálogo.

  3. En Explorador de soluciones, elija el proyecto Office-Add-in-ASPNET-SSO-manifest y abra el archivo de manifiesto del complemento "Office-Add-in-ASPNET-SSO.xml" y desplácese hasta la parte inferior del archivo. Justo encima de la etiqueta final </VersionOverrides> , encontrará el marcado siguiente.

    <WebApplicationInfo>
         <Id>Enter_client_ID_here</Id>
     	<Resource>api://localhost:44355/Enter_client_ID_here</Resource>
     	<Scopes>
            <Scope>Files.Read</Scope>
     		<Scope>profile</Scope>
            <Scope>openid</Scope>
     	</Scopes>
     </WebApplicationInfo>
    
  4. Reemplace el marcador de posición "Enter_client_ID_here" en ambos lugares del marcado por el identificador de aplicación que copió al crear el registro de la aplicación Office-Add-in-ASPNET-SSO . Este es el mismo identificador que usó para el identificador de aplicación en el archivo appsettings.json.

    Nota:

    El <valor de Recurso> es el URI del identificador de aplicación que estableció al registrar el complemento. La <sección Ámbitos> solo se usa para generar un cuadro de diálogo de consentimiento si el complemento se vende a través de AppSource.

  5. Guarde y cierre el archivo de manifiesto.

  6. En Explorador de soluciones, elija el proyecto Office-Add-in-ASPNET-SSO-web y abra el archivo appsettings.json.

  7. Reemplace el marcador de posición Enter_client_id_here por el valor de id. de aplicación (cliente) que guardó anteriormente.

  8. Reemplace el marcador de posición Enter_client_secret_here por el valor de secreto de cliente que guardó anteriormente.

    Nota:

    También debe cambiar tenantId para admitir un solo inquilino si configuró el registro de la aplicación para un solo inquilino. Reemplace el valor común por el identificador de aplicación (cliente) para la compatibilidad con un solo inquilino.

  9. Guarde y cierre el archivo appsettings.json.

Programar el lado cliente

Obtener el token de acceso y llamar a la API REST del servidor de aplicaciones

  1. En el proyecto Office-Add-in-ASPNETCore-WebAPI , abra el archivo wwwroot\js\HomeES6.js . Ya tiene código que garantiza que se admiten las promesas, incluso en el control de vista web Trident (Internet Explorer 11) y una Office.onReady llamada para asignar un controlador al único botón del complemento.

    Nota:

    Como sugiere el nombre, el HomeES6.js usa la sintaxis ES6 de JavaScript porque el uso async y await la mejor muestra la simplicidad esencial de la API de SSO. Cuando se inicia el servidor localhost, este archivo se transpila a la sintaxis ES5 para que el ejemplo admita Trident.

  2. En la función getUserFileNames, reemplace TODO 1 por el siguiente código. Sobre este código, tenga en cuenta:

    • Llama Office.auth.getAccessToken a para obtener el token de acceso de Office mediante sso. Este token contendrá la identidad del usuario, así como el permiso de acceso al servidor de aplicaciones.
    • El token de acceso se pasa al callRESTApi que realiza la llamada real al servidor de aplicaciones. A continuación, el servidor de aplicaciones usa el flujo OBO para llamar a Microsoft Graph.
    • Cualquier error de llamada getAccessToken se controlará mediante handleClientSideErrors.
       let fileNameList = null;
    try {
        let accessToken = await Office.auth.getAccessToken(options);
        fileNameList = await callRESTApi("/api/files", accessToken);
    }
    catch (exception) {
        if (exception.code) {
            handleClientSideErrors(exception);
        }
        else {
            showMessage("EXCEPTION: " + exception);
        }
    }
    
    
  3. En la función getUserFileNames, reemplace TODO 2 por el siguiente código. Esto escribirá la lista de nombres de archivo en el documento.

     try {
         await writeFileNamesToOfficeDocument(fileNameList);
         showMessage("Your data has been added to the document.");
     } catch (error) {
         // The error from writeFileNamesToOfficeDocument will begin 
         // "Unable to add filenames to document."
         showMessage(error);
     }
    
  4. En la función callRESTApi, reemplace TODO 3 por el siguiente código. Sobre este código, tenga en cuenta:

    • Construye un encabezado de autorización que contiene el token de acceso. Esto confirma al servidor de aplicaciones que este código de cliente tiene permisos de acceso a las API REST.
    • Solicita tipos de valor devuelto JSON para que todos los valores devueltos se controlen en JSON.
    • Los errores se pasan a handleServerSideErrors para su procesamiento.
     try {
         let result = await $.ajax({
             url: relativeUrl,
             headers: { "Authorization": "Bearer " + accessToken },
             type: "GET",
             dataType: "json",
             contentType: "application/json; charset=utf-8"
         });
         return result;
     } catch (error) {
         handleServerSideErrors(error);
     }
    

Control de errores de SSO y errores de API REST de la aplicación

  1. En la función handleSSOErrors, reemplace TODO 4 por el siguiente código. Para obtener más información sobre estos errores, vea Solucionar problemas de SSO en los complementos de Office.

     switch (error.code) {
         case 13001:
             // No one is signed into Office. If the add-in cannot be effectively used when no one 
             // is logged into Office, then the first call of getAccessToken should pass the 
             // `allowSignInPrompt: true` option.
             showMessage("No one is signed into Office. But you can use many of the add-ins functions anyway. If you want to log in, press the Get OneDrive File Names button again.");
             break;
         case 13002:
             // The user aborted the consent prompt. If the add-in cannot be effectively used when consent
             // has not been granted, then the first call of getAccessToken should pass the `allowConsentPrompt: true` option.
             showMessage("You can use many of the add-ins functions even though you have not granted consent. If you want to grant consent, press the Get OneDrive File Names button again.");
             break;
         case 13006:
             // Only seen in Office on the web.
             showMessage("Office on the web is experiencing a problem. Please sign out of Office, close the browser, and then start again.");
             break;
         case 13008:
             // Only seen in Office on the web.
             showMessage("Office is still working on the last operation. When it completes, try this operation again.");
             break;
         case 13010:
             // Only seen in Office on the web.
             showMessage("Follow the instructions to change your browser's zone configuration.");
             break;
         default:
             // For all other errors, including 13000, 13003, 13005, 13007, 13012, and 50001, fall back
             // to non-SSO sign-in by using MSAL authentication.
             showMessage("SSO failed. In these cases you should implement a falback to MSAL authentication.");
             break;
     }
    
  2. En la función handleServerSideErrors, reemplace TODO 5 por el siguiente código.

    // Check headers to see if admin has not consented.
    const header = errorResponse.getResponseHeader('WWW-Authenticate');
    if (header !== null && header.includes('proposedAction=\"consent\"')) {
        showMessage("MSAL ERROR: " + "Admin consent required. Be sure admin consent is granted on all scopes in the Azure app registration.");
        return;
    }
    
    
  3. En la función handleServerSideErrors, reemplace TODO 6 por el siguiente código. Sobre este código, tenga en cuenta:

    • En algunos casos, se requiere consentimiento adicional, como 2FA. La identidad de Microsoft devuelve las notificaciones adicionales necesarias para completar el consentimiento. Este código agrega la authChallenge propiedad con las notificaciones adicionales y vuelve a llamar a getUserfileNames . Cuando getAccessToken se llama de nuevo con las notificaciones adicionales, el usuario obtiene un mensaje para todas las formas necesarias de autenticación.
    // Check if Microsoft Graph requires an additional form of authentication. Have the Office host 
    // get a new token using the Claims string, which tells Microsoft identity to prompt the user for all 
    // required forms of authentication.
    const errorDetails = JSON.parse(errorResponse.responseJSON.value.details);
    if (errorDetails) {
        if (errorDetails.error.message.includes("AADSTS50076")) {
            const claims = errorDetails.message.Claims;
            const claimsAsString = JSON.stringify(claims);
            getUserFileNames({ authChallenge: claimsAsString });
            return;
        }
    }
    
  4. En la función handleServerSideErrors, reemplace TODO 7 por el siguiente código. Sobre este código, tenga en cuenta:

    • En el caso poco frecuente de que el token de SSO original haya expirado, detectará esta condición de error y getUserFilenames llamará de nuevo. Esto da como resultado otra llamada a la getAccessToken que devuelve un token de acceso actualizado. La retryGetAccessToken variable cuenta los reintentos y actualmente está configurada para volver a intentarlo una sola vez.
    • Por último, si no se puede controlar un error, el valor predeterminado es mostrar el error en el panel de tareas.
    // Results from other errors (other than AADSTS50076) will have an ExceptionMessage property.
    const exceptionMessage = JSON.parse(errorResponse.responseText).ExceptionMessage;
    if (exceptionMessage) {
        // On rare occasions the access token is unexpired when Office validates it,
        // but expires by the time it is sent to Microsoft identity in the OBO flow. Microsoft identity will respond
        // with "The provided value for the 'assertion' is not valid. The assertion has expired."
        // Retry the call of getAccessToken (no more than once). This time Office will return a 
        // new unexpired access token.
        if ((exceptionMessage.includes("AADSTS500133"))
            && (retryGetAccessToken <= 0)) {
            retryGetAccessToken++;
            getUserFileNames();
            return;
        }
        else {
            showMessage("MSAL error from application server: " + JSON.stringify(exceptionMessage));
            return;
        }
    }
    // Default error handling if previous checks didn't apply.
    showMessage(errorResponse.responseJSON.value);
    
  5. Guarde el archivo.

Codificar el lado servidor

El código del lado servidor es un servidor de ASP.NET Core que proporciona API REST para que el cliente llame. Por ejemplo, la API /api/files REST obtiene una lista de nombres de archivo de la carpeta de OneDrive del usuario. Cada llamada a la API REST requiere un token de acceso por parte del cliente para asegurarse de que el cliente correcto tiene acceso a sus datos. El token de acceso se intercambia por un token de Microsoft Graph a través del flujo en nombre de (OBO). La biblioteca de MSAL.NET almacena en caché el nuevo token de Microsoft Graph para las llamadas API posteriores. Nunca se envía fuera del código del lado servidor. La documentación de identidad de Microsoft hace referencia a este servidor como servidor de nivel intermedio porque se encuentra en medio del flujo desde el código del lado cliente a los servicios de Microsoft. Para obtener más información, consulte Solicitud de token de acceso de nivel intermedio.

Configuración del flujo de Microsoft Graph y OBO

  1. Abra el Program.cs archivo y reemplace por TODO 8 el código siguiente. Sobre este código, tenga en cuenta:

    • Agrega los servicios necesarios para controlar la validación de tokens necesaria para las API rest.
    • Agrega compatibilidad con el flujo de Microsoft Graph y OBO en la llamada a EnableTokenAcquisitionToCallDownstreamApi().AddMicrosoftGraph(...). El flujo de OBO se controla automáticamente y el SDK de Microsoft Graph se proporciona a los controladores de API REST.
    • La configuración DownstreamApi se especifica en el archivo appsettings.json .
    // Add services to the container.
    builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration)
                    .EnableTokenAcquisitionToCallDownstreamApi()
                        .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
                        .AddInMemoryTokenCaches();
    
    

Creación de la API REST /api/filenames

  1. En la carpeta Controllers (Controladores ), abra el archivo FilesController.cs . reemplace por TODO 9 el código siguiente. Sobre este código, tenga en cuenta:

    • Especifica el [Authorize] atributo para asegurarse de que se valida el token de acceso para cada llamada a las API REST de la FilesController clase . Para obtener más información, consulte Validación de tokens.
    • Especifica el [RequiredScope("access_as_user")] atributo para asegurarse de que el cliente tiene el ámbito de access_as_user correcto en el token de acceso.
    • El constructor inicializa el objeto para facilitar la _graphServiceClient llamada a las API REST de Microsoft Graph.
    [Authorize]
    [Route("api/[controller]")]
    [RequiredScope("access_as_user")]
    public class FilesController : Controller
    {        
        public FilesController(ITokenAcquisition tokenAcquisition, GraphServiceClient graphServiceClient, IOptions<MicrosoftGraphOptions> graphOptions)
        {
            _tokenAcquisition = tokenAcquisition;
            _graphServiceClient = graphServiceClient;
            _graphOptions = graphOptions;
    
        }
    
        private readonly ITokenAcquisition _tokenAcquisition;
        private readonly GraphServiceClient _graphServiceClient;
        private readonly IOptions<MicrosoftGraphOptions> _graphOptions;
    
        // TODO 10: Add the REST API to get filenames.
    
    }
    
  2. Reemplace TODO 10 por el código siguiente. Sobre este código, tenga en cuenta:

    • Crea la /api/files API REST.
    • Controla las excepciones de MSAL a través de la MsalException clase .
    • Controla las excepciones de las llamadas de Microsoft Graph API a través de la ServiceException clase .
     // GET api/files
        [HttpGet]
        [Produces("application/json")]
        public async Task<IActionResult> Get()
        {
            List<DriveItem> result = new List<DriveItem>();
            try
            {
                var files = await _graphServiceClient.Me.Drive.Root.Children.Request()
                    .Top(10)
                    .Select(m => new { m.Name })
                    .GetAsync();
    
                result = files.ToList();
            }
            catch (MsalException ex)
            {
                var errorResponse = new
                {
                    message = "An authentication error occurred while acquiring a token for downstream API",
                    details = ex.Message
                };
    
                return StatusCode((int)HttpStatusCode.Unauthorized, Json(errorResponse));
            }
            catch (ServiceException ex)
            {
                if (ex.InnerException is MicrosoftIdentityWebChallengeUserException challengeException)
                {
                    _tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeader(_graphOptions.Value.Scopes.Split(' '),
                        challengeException.MsalUiRequiredException);
                }
                else
                {
                    var errorResponse = new
                    {
                        message = "An error occurred calling Microsoft Graph",
                        details = ex.RawResponseBody
                    };
                    return StatusCode((int)HttpStatusCode.BadRequest, Json(errorResponse));
                }
            }
            catch (Exception ex)
            {
                var errorResponse = new
                {
                    message = "An error occurred while calling the downstream API",
                    details = ex.Message
                };
                return StatusCode((int)HttpStatusCode.BadRequest, Json(errorResponse));
    
            }
            return Json(result);
        }
    

Ejecute la solución.

  1. En Visual Studio, en el menú Compilar , seleccione Limpiar solución. Cuando termine, abra de nuevo el menú Generar y seleccione Generar solución.

  2. En Explorador de soluciones, seleccione el nodo de proyecto Office-Add-in-ASPNET-SSO-manifest.

  3. En el panel Propiedades, abra la lista desplegable Iniciar documento y elija una de las tres opciones (Excel, Word o PowerPoint).

    Elija la aplicación cliente de Office deseada: Excel, PowerPoint o Word.

  4. Pulse F5. O bien, seleccione Depurar > Iniciar depuración.

  5. En la aplicación de Office, seleccione el grupo Mostrar complemento en el inicio de sesión único ASP.NET para abrir el complemento del panel de tareas.

  6. Seleccione Obtener nombres de archivo de OneDrive. Si ha iniciado sesión en Office con una cuenta Microsoft 365 Educación o profesional, o una cuenta de Microsoft, y el inicio de sesión único funciona según lo previsto, los primeros 10 nombres de archivo y carpeta de la OneDrive para la Empresa se muestran en el panel de tareas. Si no ha iniciado sesión o está en un escenario que no admite el inicio de sesión único o el inicio de sesión único no funciona por ningún motivo, se le pedirá que inicie sesión. Después de iniciar sesión, aparecen los nombres de archivo y carpeta.

Implementar el complemento

Cuando esté listo para realizar la implementación en un servidor de ensayo o producción, asegúrese de actualizar las siguientes áreas de la solución del proyecto.

  • En el archivo appsettings.json , cambie el dominio a su nombre de dominio de ensayo o de producción.
  • Actualice las referencias a localhost:7080 todo el proyecto para usar la dirección URL de ensayo o producción.
  • Actualice las referencias a localhost:7080 en el registro de App de Azure o cree un nuevo registro para usarlo en ensayo o producción.

Para obtener más información, consulte Hospedaje e implementación de ASP.NET Core.

Consulte también