Autenticación para funciones personalizadas sin un entorno de ejecución compartido
En algunos escenarios, una función personalizada que no use un entorno de ejecución compartido tendrá que autenticar al usuario para acceder a los recursos protegidos. Funciones personalizadas que no usan una ejecución en tiempo de ejecución compartida en un entorno de ejecución solo de JavaScript. Por este motivo, si el complemento tiene un panel de tareas, deberá pasar datos entre el entorno de ejecución de solo JavaScript y el entorno de ejecución compatible con HTML que usa el panel de tareas. Para ello, use el objeto OfficeRuntime.storage y una API de diálogo especial.
Importante
Tenga en cuenta que las funciones personalizadas están disponibles en Excel en las siguientes plataformas.
- Office en la web
- Office en Windows
- Suscripción a Microsoft 365
- Retail perpetual Office 2016 y versiones posteriores
- Licencia por volumen perpetua de Office 2021 y versiones posteriores
- Office en Mac
Las funciones personalizadas de Excel no se admiten actualmente en lo siguiente:
- Office en iPad
- versiones perpetuas con licencia por volumen de Office 2019 o versiones anteriores en Windows
Nota:
Se recomienda usar funciones personalizadas con un entorno de ejecución compartido, a menos que tenga una razón específica para no usar un entorno de ejecución compartido. Tenga en cuenta que el uso de un entorno de ejecución compartido significa que el complemento usará WebView2 (basado en Microsoft Edge Chromium) si se cumplen las condiciones y, de lo contrario, el complemento usará Trident (Internet Explorer 11), independientemente de la versión de Windows o Microsoft 365. Para obtener una descripción de las condiciones de WebView2, vea Exploradores y controles de vista web que usan los complementos de Office. Para obtener más información sobre los tiempos de ejecución, vea Runtimes in Office Add-ins.
Objeto OfficeRuntime.storage
El entorno de ejecución solo JavaScript no tiene un localStorage
objeto disponible en la ventana global, donde normalmente se almacenan datos. En su lugar, el código debe compartir datos entre funciones personalizadas y paneles de tareas mediante OfficeRuntime.storage
para establecer y obtener datos.
Uso sugerido
Cuando necesite autenticarse desde un complemento de función personalizada que no use un entorno de ejecución compartido, el código debe comprobar OfficeRuntime.storage
si el token de acceso ya se ha adquirido. Si no es así, use OfficeRuntime.displayWebDialog para autenticar al usuario, recuperar el token de acceso y, a continuación, almacenar el token en OfficeRuntime.storage
para su uso futuro.
API de diálogo
Si no existe un token, debe usar la OfficeRuntime.dialog
API para pedir al usuario que inicie sesión. Una vez que un usuario escribe sus credenciales, el token de acceso resultante se puede almacenar como un elemento en OfficeRuntime.storage
.
Nota:
El tiempo de ejecución de solo JavaScript usa un objeto de diálogo ligeramente diferente del objeto dialog en el tiempo de ejecución del explorador utilizado por los paneles de tareas. Ambos se conocen como "DIALOG API", pero usan OfficeRuntime.displayWebDialog para autenticar a los usuarios en el entorno de ejecución de solo JavaScript, noOffice.ui.displayDialogAsync.
El siguiente diagrama resume este proceso básico. La línea de puntos indica que las funciones personalizadas y el panel de tareas del complemento forman parte del complemento en su conjunto, aunque usan tiempos de ejecución independientes.
- Se emite una llamada de función personalizada desde una celda de un libro de Excel.
- La función personalizada usa
OfficeRuntime.dialog
para pasar las credenciales de usuario a un sitio web. - A continuación, este sitio web devuelve un token de acceso a la página del cuadro de diálogo.
- JavaScript en el cuadro de diálogo llama a la función Office.ui.messageParent para enviar el token de acceso a la función personalizada. Para obtener más información sobre esta función, vea Enviar información desde el cuadro de diálogo a la página host.
- A continuación, la función personalizada establece este token de acceso en un elemento de
OfficeRuntime.storage
. - El panel de tareas del complemento obtiene acceso al token desde
OfficeRuntime.storage
.
Almacenar el token
Los ejemplos siguientes provienen del código de ejemplo en Using OfficeRuntime.storage in custom functions. Consulte este ejemplo de código para obtener un ejemplo completo de uso compartido de datos entre funciones personalizadas y el panel de tareas en complementos que no usan un entorno de ejecución compartido.
Si la función personalizada se autentica, entonces recibe el token de acceso y tendrá que almacenarlo en OfficeRuntime.storage
. El siguiente código de ejemplo muestra cómo llamar al método storage.setItem
para almacenar un valor. La storeValue
función es una función personalizada que almacena un valor del usuario. Puede modificar esto para almacenar cualquier valor de token que necesite.
/**
* Stores a key-value pair into OfficeRuntime.storage.
* @customfunction
* @param {string} key Key of item to put into storage.
* @param {*} value Value of item to put into storage.
*/
function storeValue(key, value) {
return OfficeRuntime.storage.setItem(key, value).then(function (result) {
return "Success: Item with key '" + key + "' saved to storage.";
}, function (error) {
return "Error: Unable to save item with key '" + key + "' to storage. " + error;
});
}
Cuando el panel de tareas necesita el token de acceso, puede recuperar el token del OfficeRuntime.storage
elemento. El siguiente código de ejemplo muestra cómo llamar al método storage.getItem
para recuperar el token.
/**
* Read a token from storage.
* @customfunction GETTOKEN
*/
function receiveTokenFromCustomFunction() {
const key = "token";
const tokenSendStatus = document.getElementById('tokenSendStatus');
OfficeRuntime.storage.getItem(key).then(function (result) {
tokenSendStatus.value = "Success: Item with key '" + key + "' read from storage.";
document.getElementById('tokenTextBox2').value = result;
}, function (error) {
tokenSendStatus.value = "Error: Unable to read item with key '" + key + "' from storage. " + error;
});
}
Instrucciones generales
Los complementos de Office se basan en la web y puede usar cualquier técnica de autenticación web. No hay ningún patrón o método concreto que deba seguir para implementar su propia autenticación con funciones personalizadas. Le recomendamos consultar la documentación sobre los distintos patrones de autenticación, comenzando con este artículo sobre la autorización a través de servicios externos.
Evite usar las siguientes ubicaciones para almacenar datos al desarrollar funciones personalizadas:
-
localStorage
: las funciones personalizadas que no usan un entorno de ejecución compartido no tienen acceso al objeto globalwindow
y, por tanto, no tienen acceso a los datos almacenados enlocalStorage
. -
Office.context.document.settings
: esta ubicación no es segura y cualquiera que use el complemento puede extraer información.
Ejemplo de API de cuadro de diálogo
En el ejemplo de código siguiente, la función getTokenViaDialog
usa la OfficeRuntime.displayWebDialog
función para mostrar un cuadro de diálogo. Este ejemplo se proporciona para mostrar las funcionalidades del método, no para demostrar cómo autenticarse.
/**
* Function retrieves a cached token or opens a dialog box if there is no saved token. Note that this isn't a sufficient example of authentication but is intended to show the capabilities of the displayWebDialog method.
* @param {string} url URL for a stored token.
*/
function getTokenViaDialog(url) {
return new Promise (function (resolve, reject) {
if (_dialogOpen) {
// Can only have one dialog box open at once. Wait for previous dialog box's token.
let timeout = 5;
let count = 0;
const intervalId = setInterval(function () {
count++;
if(_cachedToken) {
resolve(_cachedToken);
clearInterval(intervalId);
}
if(count >= timeout) {
reject("Timeout while waiting for token");
clearInterval(intervalId);
}
}, 1000);
} else {
_dialogOpen = true;
OfficeRuntime.displayWebDialog(url, {
height: '50%',
width: '50%',
onMessage: function (message, dialog) {
_cachedToken = message;
resolve(message);
dialog.close();
return;
},
onRuntimeError: function(error, dialog) {
reject(error);
},
}).catch(function (e) {
reject(e);
});
}
});
}
Siguientes pasos
Obtenga información sobre cómo depurar funciones personalizadas.