Crear un complemento de Node.js 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. Para obtener información general, vea Habilitar SSO en un complemento de Office.
Este artículo le guiará por el proceso de habilitación del inicio de sesión único (SSO) en un complemento. El complemento de ejemplo que cree tiene dos partes; un panel de tareas que se carga en Microsoft Excel y un servidor de nivel intermedio que controla las llamadas a Microsoft Graph para el panel de tareas. El servidor de nivel intermedio se compila con Node.js y Express y expone una única API REST, /getuserfilenames
, que devuelve una lista de los primeros 10 nombres de archivo en la carpeta de OneDrive del usuario. El panel de tareas usa el getAccessToken()
método para obtener un token de acceso para el usuario que ha iniciado sesión en el servidor de nivel intermedio. El servidor de nivel intermedio usa el flujo en nombre de (OBO) para intercambiar el token de acceso por uno nuevo con acceso a Microsoft Graph. Puede ampliar este patrón para acceder a cualquier dato de Microsoft Graph. El panel de tareas siempre llama a una API REST de nivel intermedio (pasando el token de acceso) cuando necesita servicios de Microsoft Graph. El nivel intermedio usa el token obtenido a través de OBO para llamar a los servicios de Microsoft Graph y devolver los resultados al panel de tareas.
Este artículo funciona con un complemento que usa Node.js y Express. Para obtener un artículo similar sobre un complemento basado en ASP.NET, vea Crear un complemento de ASP.NET Office que usa el inicio de sesión único.
Requisitos previos
Git Bash (u otro cliente de GIT)
Editor de código: se recomienda Visual Studio Code
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 NodeJS SSO.
Nota:
Existen 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 middle-tier server side (Código del servidor de nivel intermedio ).
Abra un símbolo del sistema en la carpeta Begin .
Escriba
npm install
en la consola para instalar todas las dependencias detalladas en el archivo package.json.Ejecute el comando
npm run install-dev-certs
. Seleccione Sí en la solicitud para instalar el certificado.
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-NodeJS-SSO |
<fully-qualified-domain-name> |
localhost:3000 |
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).
Inicie sesión en el Azure Portal con las credenciales de administrador en el inquilino de Microsoft 365. Por ejemplo, MyName@contoso.onmicrosoft.com.
Seleccione Registros de aplicaciones. Si no ve el icono, busque "Registro de aplicaciones" en la barra de búsqueda.
Aparece la página Registros de aplicaciones.
Seleccione Nuevo registro.
Aparece la página Registrar una aplicación.
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
.
- Establezca Nombre como
Seleccione Registrar. Se muestra un mensaje que indica que se creó el registro de la aplicación.
Copie y guarde los valores para el identificador de aplicación (cliente) y el identificador de directorio (inquilino). Deberá usar ambos en procedimientos posteriores.
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.
En el panel izquierdo, seleccione Certificados & secretos. A continuación, en la pestaña Secretos de cliente, seleccione Nuevo secreto de cliente.
Aparece el panel Agregar un secreto de cliente .
Agregue una descripción para el secreto de cliente.
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.
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
En el panel izquierdo, seleccione Exponer una API.
Aparece el panel Exponer una API .
Seleccione Establecer para generar un URI de identificador de 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>
.Actualice el URI del identificador de aplicación a
api://<fully-qualified-domain-name>/<app-id>
.- 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 entreapi://
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).
- El URI de id. de aplicación se rellena previamente con el identificador de aplicación (GUID) con el formato
Agregar un ámbito
En la página Exponer una API , seleccione Agregar un ámbito.
Se abre el panel Agregar un ámbito .
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
profile
permisos ,openid
,Files.ReadWrite
yMail.Read
. Modifique el texto para que coincida con los permisos que necesita el complemento.Campo Descripción 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.
Establezca Estadoen Habilitado y, a continuación, seleccione Agregar ámbito.
El nuevo ámbito definido se muestra en el panel.
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
.Seleccione Agregar una aplicación cliente.
Aparece el panel Agregar una aplicación cliente .
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, agregue1fec8e78-bce4-4aaf-ab1b-5451cc387264
(escritorio de Microsoft Teams y dispositivos móviles de Teams) y5e3ce6c0-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)
-
En Ámbitos autorizados, active la
api://<fully-qualified-domain-name>/<app-id>/access_as_user
casilla .Seleccione Agregar aplicación.
Adición de permisos de Microsoft Graph
En el panel izquierdo, seleccione Permisos de API.
Se abre el panel Permisos de API .
Seleccione Agregar un permiso
Se abre el panel Solicitar permisos de API .
Seleccione Microsoft Graph.
Seleccione Permisos delegados
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.ReadWrite
yMail.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.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.
Seleccione Conceder consentimiento de administrador para [nombre de inquilino]. Seleccione Sí 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.
En el panel izquierdo, seleccione Manifiesto.
Aparece el manifiesto de aplicación de Azure Active Directory.
Introduzca 2 como valor de la
accessTokenAcceptedVersion
propiedad.Haga clic en Guardar.
Aparece un mensaje en el explorador que indica que el manifiesto se actualizó correctamente.
Enhorabuena. Ha completado el registro de la aplicación para habilitar el inicio de sesión único para el complemento de Office.
Configurar el complemento
Abra la carpeta
\Begin
del proyecto clonado en el editor de código.Abra el
.ENV
archivo y use los valores que copió anteriormente del registro de la aplicación Office-Add-in-NodeJS-SSO . Establezca los valores como se indica a continuación:Nombre Valor CLIENT_ID Id. de aplicación (cliente) de la página de información general del registro de la aplicación. CLIENT_SECRET Secreto de cliente guardado en la página Certificados & secretos . Los valores no deben estar entre comillas. Cuando termine, el archivo debería ser similar al siguiente:
CLIENT_ID=8791c036-c035-45eb-8b0b-265f43cc4824 CLIENT_SECRET=X7szTuPwKNts41:-/fa3p.p@l6zsyI/p NODE_ENV=development SERVER_SOURCE=<https://localhost:3000>
Abra el archivo de manifiesto de complemento "manifest\manifest_local.xml" y, después, desplácese hasta la parte inferior del archivo. Justo encima de la
</VersionOverrides>
etiqueta final, encontrará el marcado siguiente.<WebApplicationInfo> <Id>$app-id-guid$</Id> <Resource>api://localhost:3000/$app-id-guid$</Resource> <Scopes> <Scope>Files.Read</Scope> <Scope>profile</Scope> <Scope>openid</Scope> </Scopes> </WebApplicationInfo>
Reemplace el marcador de posición "$app-id-guid$" en ambos lugares del marcado por el identificador de aplicación que copió al crear el registro de la aplicación Office-Add-in-NodeJS-SSO . Los símbolos "$" no forman parte del identificador, por lo que no los incluya. Este es el mismo identificador que usó para la CLIENT_ID en . Archivo ENV.
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.
Abra el archivo
\public\javascripts\fallback-msal\authConfig.js
. Reemplace el marcador de posición "$app-id-guid$" por el identificador de aplicación que guardó en el registro de la aplicación Office-Add-in-NodeJS-SSO que creó anteriormente.Guarde los cambios realizados en el archivo.
Codificar el lado cliente
Llamada a nuestra API REST del servidor web
Abra el archivo
public\javascripts\ssoAuthES6.js
en el editor de código. Ya tiene código que garantiza que se admiten las promesas, incluso en el control de vista web Trident (Internet Explorer 11) y unaOffice.onReady
llamada para asignar un controlador al único botón del complemento.Nota:
Como el nombre sugiere, ssoAuthES6.js usa la sintaxis ES6 de JavaScript porque el uso de
async
yawait
muestra mejor 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.En la función
getFileNameList
, reemplaceTODO 1
por el siguiente código. Sobre este código, tenga en cuenta:- Se llama a la función
getFileNameList
cuando el usuario elige el botón Obtener nombres de archivo de OneDrive en el panel de tareas. - Llama a la
callWebServerAPI
función que especifica a qué API REST llamar. Esto devuelve JSON que contiene una lista de nombres de archivo de OneDrive del usuario. - El json se pasa a la
writeFileNamesToOfficeDocument
función para enumerar los nombres de archivo del documento.
try { const jsonResponse = await callWebServerAPI('GET', '/getuserfilenames'); if (jsonResponse === null) { // Null is returned when a message was displayed to the user // regarding an authentication error that cannot be resolved. return; } await writeFileNamesToOfficeDocument(jsonResponse); showMessage('Your OneDrive filenames are added to the document.'); } catch (error) { console.log(error.message); showMessage(error.message); }
- Se llama a la función
En la función
callWebServerAPI
, reemplaceTODO 2
por el siguiente código. Sobre este código, tenga en cuenta:- La función llama a
getAccessToken
nuestra propia función que encapsula mediante el inicio de sesión único de Office o la reserva de MSAL según sea necesario para obtener el token. Si devuelve un token null, se muestra un mensaje para una condición de error de autenticación que no se puede resolver, por lo que la función también devuelve null. - La función usa la
fetch
API para llamar al servidor web y, si se ejecuta correctamente, devuelve el cuerpo JSON.
const accessToken = await getAccessToken(authSSO); if (accessToken === null) { return null; } const response = await fetch(path, { method: method, headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accessToken, }, }); // Check for success condition: HTTP status code 2xx. if (response.ok) { return response.json(); }
- La función llama a
En la función
callWebServerAPI
, reemplaceTODO 3
por el siguiente código. Sobre este código, tenga en cuenta:- Este código controla el escenario en el que expiró el token de SSO. Si es así, debemos llamar
Office.auth.getAccessToken
a para obtener un token actualizado. La manera más sencilla es realizar una llamada recursiva que da como resultado una nueva llamada aOffice.auth.getAccessToken
. ElretryRequest
parámetro garantiza que la llamada recursiva solo se intenta una vez. - Nuestro
TokenExpiredError
servidor web establece la cadena cada vez que detecta un token expirado.
// Check for fail condition: Is SSO token expired? If so, retry the call which will get a refreshed token. const jsonBody = await response.json(); if ( authSSO === true && jsonBody != null && jsonBody.type === 'TokenExpiredError' ) { if (!retryRequest) { return callWebServerAPI(method, path, true); // Try the call again. The underlying call to Office JS getAccessToken will refresh the token. } else { // Indicates a second call to retry and refresh the token failed. authSSO = false; return callWebServerAPI(method, path, true); // Try the call again, but now using MSAL fallback auth. } }
- Este código controla el escenario en el que expiró el token de SSO. Si es así, debemos llamar
En la función
callWebServerAPI
, reemplaceTODO 4
por el siguiente código. Sobre este código, tenga en cuenta:- El
Microsoft Graph
servidor web establece la cadena cada vez que se produce un error en una llamada a Microsoft Graph.
// Check for fail condition: Did we get a Microsoft Graph API error, which is returned as bad request (403)? if (response.status === 403 && jsonBody.type === 'Microsoft Graph') { throw new Error('Microsoft Graph error: ' + jsonBody.errorDetails); }
- El
En la función
callWebServerAPI
, reemplaceTODO 5
por el siguiente código.// Handle other errors. throw new Error( 'Unknown error from web server: ' + JSON.stringify(jsonBody) );
En la función
getAccessToken
, reemplaceTODO 6
por el siguiente código. Sobre este código, tenga en cuenta:-
authSSO
realiza un seguimiento de si se usa el inicio de sesión único o si se usa la reserva de MSAL. Si se usa sso, la función llama aOffice.auth.getAccessToken
y devuelve el token. - La función controla
handleSSOErrors
los errores, que devolverá un token si cambia a la autenticación MSAL de reserva. - La autenticación de reserva usa la biblioteca MSAL para iniciar sesión en el usuario. El propio complemento es un SPA y usa un registro de aplicación SPA para acceder al servidor web.
if (authSSO) { try { // Get the access token from Office host using SSO. // Note that Office.auth.getAccessToken modifies the options parameter. Create a copy of the object // to avoid modifying the original object. const options = JSON.parse(JSON.stringify(ssoOptions)); const token = await Office.auth.getAccessToken(options); return token; } catch (error) { console.log(error.message); return handleSSOErrors(error); } } else { // Get access token through MSAL fallback. try { const accessToken = await getAccessTokenMSAL(); return accessToken; } catch (error) { console.log(error); throw new Error( 'Cannot get access token. Both SSO and fallback auth failed. ' + error ); } }
-
En la función
handleSSOErrors
, reemplaceTODO 7
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. Since this sample does that, you should not see // this error. 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;
Reemplace
TODO 8
por el código siguiente. Para los errores que no se pueden controlar, el código cambia a la autenticación de reserva mediante MSAL.default: //recursive call. // For all other errors, including 13000, 13003, 13005, 13007, 13012, and 50001, fall back // to MSAL sign-in. showMessage('SSO failed. Trying fallback auth.'); authSSO = false; return getAccessToken(false); } return null; // Return null for errors that show a message to the user.
Codificación de la API REST del servidor web
El servidor web proporciona API REST para que el cliente llame. Por ejemplo, la API /getuserfilenames
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 MSAL almacena en caché el nuevo token de Microsoft Graph para las llamadas API posteriores. Nunca se envía fuera del servidor web. Para obtener más información, consulte Solicitud de token de acceso de nivel intermedio.
Creación de la ruta e implementación del flujo en nombre de
Abra el archivo
routes\getFilesRoute.js
y reemplace porTODO 9
el código siguiente. Sobre este código, tenga en cuenta:- Llama a
authHelper.validateJwt
. Esto garantiza que el token de acceso es válido y no se ha alterado. - Para obtener más información, consulte Validación de tokens.
router.get( "/getuserfilenames", authHelper.validateJwt, async function (req, res) { // TODO 10: Exchange the access token for a Microsoft Graph token // by using the OBO flow. } );
- Llama a
Reemplace
TODO 10
por el código siguiente. Sobre este código, tenga en cuenta:- Solo solicita los ámbitos mínimos que necesita, como
files.read
. - Usa MSAL
authHelper
para realizar el flujo de OBO en la llamada aacquireTokenOnBehalfOf
.
try { const authHeader = req.headers.authorization; let oboRequest = { oboAssertion: authHeader.split(' ')[1], scopes: ["files.read"], }; // The Scope claim tells you what permissions the client application has in the service. // In this case we look for a scope value of access_as_user, or full access to the service as the user. const tokenScopes = jwt.decode(oboRequest.oboAssertion).scp.split(' '); const accessAsUserScope = tokenScopes.find( (scope) => scope === 'access_as_user' ); if (!accessAsUserScope) { res.status(401).send({ type: "Missing access_as_user" }); return; } const cca = authHelper.getConfidentialClientApplication(); const response = await cca.acquireTokenOnBehalfOf(oboRequest); // TODO 11: Call Microsoft Graph to get list of filenames. } catch (err) { // TODO 12: Handle any errors. }
- Solo solicita los ámbitos mínimos que necesita, como
Reemplace
TODO 11
por el código siguiente. Sobre este código, tenga en cuenta:- Construye la dirección URL de la llamada de Microsoft Graph API y, a continuación, realiza la llamada a través de la
getGraphData
función . - Devuelve errores enviando una respuesta HTTP 500 junto con detalles.
- Si se ejecuta correctamente, devuelve el ARCHIVO JSON con la lista de nombres de archivo al cliente.
// Minimize the data that must come from MS Graph by specifying only the property we need ("name") // and only the top 10 folder or file names. const rootUrl = '/me/drive/root/children'; // Note that the last parameter, for queryParamsSegment, is hardcoded. If you reuse this code in // a production add-in and any part of queryParamsSegment comes from user input, be sure that it is // sanitized so that it cannot be used in a Response header injection attack. const params = '?$select=name&$top=10'; const graphData = await getGraphData( response.accessToken, rootUrl, params ); // If Microsoft Graph returns an error, such as invalid or expired token, // there will be a code property in the returned object set to a HTTP status (e.g. 401). // Return it to the client. On client side it will get handled in the fail callback of `makeWebServerApiCall`. if (graphData.code) { res .status(403) .send({ type: "Microsoft Graph", errorDetails: "An error occurred while calling the Microsoft Graph API.\n" + graphData, }); } else { // MS Graph data includes OData metadata and eTags that we don't need. // Send only what is actually needed to the client: the item names. const itemNames = []; const oneDriveItems = graphData["value"]; for (let item of oneDriveItems) { itemNames.push(item["name"]); } res.status(200).send(itemNames); } // TODO 12: Check for expired token.
- Construye la dirección URL de la llamada de Microsoft Graph API y, a continuación, realiza la llamada a través de la
Reemplace
TODO 12
por el código siguiente. Este código comprueba específicamente si el token expiró porque el cliente puede solicitar un nuevo token y volver a llamar a.} catch (err) { // On rare occasions the SSO access token is unexpired when Office validates it, // but expires by the time it is used in the OBO flow. Microsoft identity platform will respond // with "The provided value for the 'assertion' is not valid. The assertion has expired." // Construct an error message to return to the client so it can refresh the SSO token. if (err.errorMessage.indexOf('AADSTS500133') !== -1) { res.status(401).send({ type: "TokenExpiredError", errorDetails: err }); } else { res.status(403).send({ type: "Unknown", errorDetails: err }); } }
El ejemplo debe controlar la autenticación de reserva a través de MSAL y la autenticación sso a través de Office. El ejemplo probará primero el inicio de sesión único y el authSSO
valor booleano en la parte superior del archivo realiza un seguimiento si el ejemplo usa sso o ha cambiado a la autenticación de reserva.
Ejecutar el proyecto
Asegúrese de que tiene algunos archivos en OneDrive para que pueda comprobar los resultados.
Abra un símbolo del sistema en la raíz de la carpeta
\Begin
.Ejecute el comando
npm install
para instalar todas las dependencias del paquete.Ejecute el comando
npm start
para iniciar el servidor de nivel intermedio.Debe transferir el complemento a una aplicación de Office (Excel, Word o PowerPoint) para probarlo. Las instrucciones dependen de la plataforma. Hay vínculos a instrucciones en Transferir un complemento de Office para probarlo.
En la aplicación de Office, en la cinta de opciones Inicio, seleccione el botón Mostrar complemento en el grupo SSO Node.js para abrir el complemento del panel de tareas.
Haga clic en el botón 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 esperado, los primeros 10 nombres de archivo y carpeta de la OneDrive para la Empresa se insertan en el documento. (Puede tardar hasta 15 segundos la primera vez). 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.
Nota:
Si ha iniciado sesión previamente en Office con un identificador distinto y algunas aplicaciones de Office que estaban abiertas en el momento siguen abiertas, es posible que Office no cambie el identificador de manera confiable aunque parezca haberlo hecho. Si esto ocurre, puede que la llamada a Microsoft Graph no se realice o que se devuelvan datos del identificador anterior. Para evitarlo, asegúrese de cerrar las demás aplicaciones de Office antes de presionar Obtener los nombres de archivos de OneDrive.
Detener la ejecución del proyecto
Cuando esté listo para detener el servidor de nivel intermedio y desinstalar el complemento, siga estas instrucciones:
Ejecute el siguiente comando para detener el servidor de nivel intermedio.
npm stop
Para desinstalar o quitar el complemento, consulte el artículo de transferencia local específico que usó para obtener más información.
Notas de seguridad
La
/getuserfilenames
ruta engetFilesroute.js
usa una cadena literal para redactar la llamada a Microsoft Graph. Si cambia la llamada para que cualquier parte de la cadena provenga de la entrada del usuario, desintegre la entrada para que no se pueda usar en un ataque de inyección de encabezado de respuesta.En
app.js
la siguiente directiva de seguridad de contenido está en vigor para los scripts. Es posible que desee especificar restricciones adicionales en función de las necesidades de seguridad del complemento."Content-Security-Policy": "script-src https://appsforoffice.microsoft.com https://ajax.aspnetcdn.com https://alcdn.msauth.net " + process.env.SERVER_SOURCE,
Siga siempre los procedimientos recomendados de seguridad en la documentación de Plataforma de identidad de Microsoft.