Overview
El proveedor de autenticación de funciones personalizadas permite definir un flujo de autenticación personalizado mediante una función sin servidor. Puede usar este proveedor para implementar su propia lógica de autenticación de usuarios o integrar un sistema de autenticación externo.
Cuándo utilizar la autenticación de funciones personalizadas
La autenticación con funciones personalizadas es la forma más flexible de autenticación. Sin embargo, también requiere que usted mismo defina y configure manualmente el flujo de autenticación.
Antes de definir un proveedor de funciones personalizado, considere si puede utilizar uno de los proveedores de autenticación integrados.
Considere utilizar el proveedor de funciones personalizadas en su aplicación si:
Desea utilizar un servicio de autenticación externo sin un proveedor integrado. Si el servicio utiliza tokens web JSON, considere crear un proveedor JWT personalizado.
Desea personalizar el proceso de autenticación más allá de lo que ofrece un proveedor integrado. Por ejemplo, podría usar un servicio para enviar correos electrónicos de confirmación personalizados en lugar de los correos predeterminados del proveedor de correo electrónico/contraseña.
Importante
Atlas App Services no realiza ninguna validación de datos ni comprobaciones de autenticación para el proveedor de función personalizada.
Asegúrese de validar los datos entrantes y de que su sistema de autenticación realice las comprobaciones de autenticación adecuadas, como solicitar una contraseña, autenticación de dos factores, o un token de inicio de sesión único.
El siguiente diagrama muestra el proceso de inicio de sesión de una función personalizada:

La función de autenticación
La función de autenticación es una función de JavaScript que contiene el código de autenticación de usuario personalizado. Se ejecuta cada vez que un usuario inicia sesión a través del proveedor de funciones personalizadas.
La función asigna los datos proporcionados al iniciar sesión, como el nombre de usuario y la contraseña o un token de acceso, a una cadena que identifica de forma única al usuario en su sistema de autenticación externo. Por ejemplo, podría usar los datos proporcionados para iniciar sesión en un servicio externo mediante HTTP o con un paquete de npm.
exports = async function (payload) { // 1. Parse the `payload` object, which holds data from the // FunctionCredential sent by the SDK. const { username, password } = payload; // 2. Create a new user or log in an existing user in the external // authentication service. // You can use a client library from npm const auth = require("fake-auth-service"); const user = await auth.login({ username, password }); // Or you can communicate directly over HTTP const userFromHttp = await context.http.post({ url: "https://example.com/auth/login", headers: { Authorization: ["Basic bmlja0BleGFtcGxlLmNvbTpQYTU1dzByZA=="], }, body: JSON.stringify({ username, password }), }); // 3. Return a unique identifier for the user. Typically this is the // user's ID in the external authentication system or the _id of a // stored MongoDB document that describes them. // // !!! This is NOT the user's internal account ID for your app !!! return user.id; };
Recibir una carga útil de credenciales personalizada
El payload El objeto pasado a la función contiene datos incluidos con la credencial del proveedor de la función personalizada en la aplicación cliente. La función acepta cualquier valor proporcionado por la aplicación cliente, por lo que los nombres y valores de los campos dependen de la implementación.
Para obtener ejemplos de cómo crear un objeto de credencial personalizado payload utilizando los SDK de Realm, consulte la documentación de cada SDK:
Devolver un ID de usuario autenticado
Si la autenticación es correcta, la función debe devolver un identificador de cadena único para el usuario. Por ejemplo, podría devolver el valor del ID de usuario utilizado por su sistema de autenticación externo. Este es el ID externo del usuario, que el proveedor utiliza para asignar desde su sistema personalizado a las cuentas de usuario internas de su aplicación.
Importante
El ID externo del usuario no es el mismo que el ID interno de la cuenta, que se expone como el id campo de un objeto de usuario. Se accede al ID interno del usuario con %%user.id en expresiones, context.user.id en funciones y la User.id propiedad en los SDK.
Si un usuario existente ya está asociado con la ID externa, el proveedor inicia sesión con ese usuario.
Si el proveedor no tiene registro de una identificación externa determinada, crea una nueva cuenta de usuario, agrega una identidad de proveedor de función personalizada y luego inicia sesión con el nuevo usuario.
El objeto de identidad del proveedor de funciones personalizadas se almacena en el objeto de usuario y se parece al siguiente:
{ "id": "<Internal User Account ID>", "identities": [ { "providerType": "custom-function", "id": "<External User ID>", } ] }
Ejemplo
La función de autenticación debe devolver una identificación externa única como una cadena:
return "5f650356a8631da45dd4784c"
También puede devolver un objeto que contenga el ID externo como su valor id:
return { "id": "5f650356a8631da45dd4784c" }
Si desea definir un nombre para mostrar para el usuario, defínalo en el campo name del objeto devuelto:
return { "id": "5f650356a8631da45dd4784c", "name": "James Bond" }
Lanzar un error por autenticación fallida
Si el usuario proporciona credenciales no válidas o la función no logra autenticar al usuario por otro motivo, lanzar un error con un mensaje descriptivo. Esto devuelve un error 401 - Unauthorized con el mensaje adjunto al SDK.
const auth = require("some-external-auth-system"); try { const user = await auth.login(payload); return user.id; } catch (err) { throw new Error(`Authentication failed with reason: ${err.message}`); }
Configurar el proveedor de funciones personalizadas
Puede configurar la autenticación de funciones personalizadas utilizando cualquier método de implementación compatible.
Habilitar el proveedor de funciones personalizadas
Para habilitar el proveedor:
Haga clic App Users en el menú de navegación de la izquierda.
Seleccione la pestaña Providers.
Haga clic en Custom Function Authentication.
En la pantalla de configuración del proveedor, cambie el interruptor Provider Enabled a On.

Definir la función de autenticación
El proveedor utiliza una función normal para gestionar la autenticación. Esta función debe devolver una cadena de identificación externa única para identificar al usuario.
Para definir una nueva función de autenticación:
Haz clic en el desplegable Function y selecciona New Function.
Introduzca un nombre para la función. Este nombre debe ser único entre todas las funciones de la aplicación.
Define el código fuente en el editor de funciones.
Haga clic Save

Implementar la aplicación actualizada
Para que la autenticación de funciones personalizadas esté disponible para las aplicaciones cliente, implemente su aplicación.
Haga clic en Deploy en el menú de navegación de la izquierda
Busque el borrador en la tabla del historial de implementación y luego haga clic en Review & Deploy Changes.
Revise la diferencia de cambios y luego haga clic en Deploy.
Obtenga la última versión de su aplicación
Para extraer una copia local de la última versión de su aplicación, ejecute lo siguiente:
appservices pull --remote="<Your App ID>"
Tip
También puedes descargar una copia de los archivos de configuración de tu aplicación desde la pantalla Deploy > Export App en la Interfaz de usuario Realm.
Definir la función de autenticación
El proveedor utiliza una función normal para gestionar la autenticación. Esta función debe devolver una cadena de identificación externa única para identificar al usuario.
Guarde el código de la función de autenticación en el functions directorio.
touch functions/handleCustomFunctionAuthentication.js
Agregar un archivo de configuración del proveedor
Para habilitar y configurar el proveedor de autenticación de función personalizada, defina un objeto de configuración para él /auth/providers.json en.
Las configuraciones del proveedor de funciones personalizadas tienen el siguiente formato:
{ "custom-function": { "name": "custom-function", "type": "custom-function", "config": { "authFunctionName": "<Authentication Function Name>" }, "disabled": false } }
Configurar datos de usuario personalizados
Puedes asociar datos personalizados de una colección de MongoDB Atlas con cuentas de usuario en tu aplicación. Esto puede ser útil si necesitas acceder a los datos de un usuario con frecuencia, pero no es necesario usar el proveedor de funciones personalizadas.
El documento de datos personalizado de un usuario puede contener cualquier dato. Para las aplicaciones que utilizan el proveedor de funciones personalizadas, recomendamos almacenar tanto el ID de la cuenta interna del usuario como su ID externo.
Por ejemplo, podrías usar el siguiente formato:
{ "_id": "<Generated ObjectId>", "user_id": "<Internal User ID>", "external_id": "<External User ID>" }
Puede utilizar el siguiente enfoque para crear documentos de usuario personalizados para usuarios de proveedores de funciones personalizadas:
Configure datos de usuario personalizados para una colección en su clúster vinculado. El campo ID de usuario almacena el ID de cuenta interno del usuario.
/auth/datos_de_usuario_personalizados.json{ "mongo_service_name": "mongodb-atlas", "database_name": "myApp", "collection_name": "users", "user_id_field": "user_id", "enabled": true } Configure el proveedor de autenticación de la función personalizada y devuelva un ID de usuario externo único desde la función de autenticación. App Services almacena este ID en el campo
idde la identidadcustom-functiondel usuario.exports = async function handleCustomFunctionAuth(payload) { const auth = require("some-external-auth-system"); const user = await auth.login(payload); return user.id; }; Configure un disparador de autenticación que detecte eventos
CREATEdel proveedorcustom-function. En la función de disparo, añada un nuevo documento a la colección de datos de usuario personalizada que incluya tanto el ID interno como el externo del usuario.exports = async function onNewCustomFunctionUser({ user }) { // This is the user's internal account ID that was generated by your app const internalId = user.id; // This is the external ID returned from the authentication function const customFunctionIdentity = user.identities.find((id) => { return id.provider_type === "custom-function"; }); const externalId = customFunctionIdentity.id; // Create a custom user data document for the user const mdb = context.services.get("mongodb-atlas"); const users = mdb.db("myApp").collection("users"); return await users.insertOne({ // Include both the internal ID and external ID user_id: internalId, external_id: externalId, // Add any other data you want to include created_at: new Date(), }); };
Iniciar sesión desde un SDK de Realm
Para iniciar sesión desde una aplicación cliente, utilice una credencial de función personalizada que contenga sus datos de carga útil de inicio de sesión.
Para obtener ejemplos, consulte la documentación de un SDK específico: