Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial se muestra cómo preparar la aplicación cliente de servicio de Node.js mediante el flujo de concesión de credenciales de cliente Open Authorization (OAuth) 2.0 y, posteriormente, configurarla para obtener un token de acceso para llamar a una API web. Vas a construir una aplicación de Node.js usando Microsoft Authentication Library (MSAL) para Node.js para simplificar la adición de autorización a tu aplicación.
En este tutorial,
- Configuración de roles de aplicación para la API web
- Conceder permisos a la aplicación en segundo plano
- Cree una aplicación Node.js en Visual Studio Code y, a continuación, instale las dependencias.
- Habilite la aplicación Node.js para adquirir un token de acceso para llamar a una API web.
Prerrequisitos
- Registre una nueva aplicación cliente en el Centro de administración de Microsoft Entra, configurada para Cuentas en cualquier directorio organizativo y cuentas personales de Microsoft. Consulte Registro de una aplicación para obtener más detalles. Registre los valores siguientes en la página Información general de la aplicación para su uso posterior:
- Id. de aplicación (cliente)
- Id. de directorio (inquilino)
- Nombre de dominio de directorio (inquilino) (por ejemplo, contoso.onmicrosoft.com o contoso.com).
- Agregue un secreto de cliente al registro de la aplicación cliente. No use secretos de cliente en aplicaciones de producción. En su lugar, use certificados o credenciales federadas. Para más información, consulte Incorporación de credenciales a la aplicación.
- Una API web protegida que está funcionando y lista para aceptar peticiones. Asegúrese de que la API web expone los siguientes puntos de conexión a través de HTTPS:
GET /api/todolist
para conseguir todas las tareas pendientes.POST /api/todolist
para agregar una tarea pendiente.
- Node.js.
- Aunque se puede usar cualquier entorno de desarrollo integrado (IDE) que admita aplicaciones React, este tutorial usa Visual Studio Code.
Configurar roles de la aplicación
Una API debe publicar un mínimo de un rol de aplicación para las aplicaciones, también denominado Permiso de aplicación, para que las aplicaciones cliente obtengan un token de acceso como ellos mismos. Los permisos de aplicación son el tipo de permisos que las API deben publicar cuando quieran permitir que las aplicaciones cliente se autentiquen correctamente como ellas mismas y no necesiten registrar a los usuarios. Para publicar un permiso de aplicación, siga estos pasos:
En la página Registros de aplicaciones, seleccione la aplicación que creó (como ciam-ToDoList-api) para abrir la página Información general.
En Administrar, seleccione Roles de aplicación.
Seleccione Crear rol de aplicación, introduzca los siguientes valores y seleccione Aplicar para guardar los cambios:
Propiedad Importancia Nombre para mostrar ToDoList.Read.All Tipos de miembros permitido Aplicaciones Importancia ToDoList.Read.All Descripción Permitir que la aplicación lea la lista de tareas pendientes de cada usuario utilizando ''TodoListApi'' ¿Quiere habilitar este rol de aplicación? Mantenerla activada Vuelva a seleccionar Crear rol de aplicación, introduzca los siguientes valores para el segundo rol de aplicación y seleccione Aplicar para guardar los cambios:
Propiedad Importancia Nombre para mostrar ToDoList.ReadWrite.All Tipos de miembros permitido Aplicaciones Importancia ToDoList.ReadWrite.All Descripción Permitir que la aplicación lea y escriba cada lista de tareas pendientes de los usuarios mediante "ToDoListApi" ¿Quiere habilitar este rol de aplicación? Mantenerla activada
Configuración de la reclamación de token idtyp
Puede agregar la notificación opcional idtyp para ayudar a la API web a determinar si un token es un token de aplicación o un token de aplicación y un token de usuario. Aunque puede usar una combinación de declaraciones scp y roles para el mismo propósito, el uso de la declaración idtyp es la manera más fácil de distinguir un token de aplicación de un token de aplicación + usuario. Por ejemplo, el valor de esta reclamación es app cuando el token es un token exclusivo para aplicaciones.
Conceder permisos de API a la aplicación de servicio
En la página Registros de aplicaciones, seleccione la aplicación que creó (como ciam-client-app).
En Administrar, seleccione Permisos de API.
En Permisos configurados, seleccione Agregar un permiso.
Seleccione la pestaña API usadas en mi organización.
En la lista de API, seleccione la API como ciam-ToDoList-api.
Seleccione la opción Permisos de aplicación. Seleccionamos esta opción cuando la aplicación inicia sesión con su propio nombre, no en nombre de un usuario.
En la lista de permisos, seleccione TodoList.Read.All, ToDoList.ReadWrite.All (use el cuadro de búsqueda si es necesario).
Seleccione el botón Agregar permisos.
En este momento, ha asignado los permisos correctamente. Sin embargo, dado que la aplicación de demonio no permite que los usuarios interactúen con ella, los propios usuarios no pueden dar su consentimiento a estos permisos. Para solucionar este problema, como administrador debe consentir estos permisos en nombre de todos los usuarios del inquilino:
- Seleccione Conceder consentimiento del administrador para <nombre del inquilino> y, luego, elija Sí.
- Seleccione Actualizar, luego compruebe que Concedido para <su nombre de inquilino> aparece en Estado en ambos permisos.
Creación del proyecto demonio de Node.js
Cree una carpeta para alojar la aplicación de proceso de Node.js, como ciam-call-api-node-daemon
:
En el terminal, cambie el directorio a la carpeta de la aplicación demonio de Node, como
cd ciam-call-api-node-daemon
, y ejecutenpm init -y
. Este comando crea un archivo package.json predeterminado para el proyecto de Node.js. Este comando crea un archivopackage.json
predeterminado para el proyecto de Node.js.Cree carpetas y archivos adicionales para conseguir la siguiente estructura de proyecto:
ciam-call-api-node-daemon/ ├── auth.js └── authConfig.js └── fetch.js └── index.js └── package.json
Instalación de dependencias de aplicaciones
En el terminal, ejecute este comando para instalar los paquetes axios
, yargs
y @azure/msal-node
:
npm install axios yargs @azure/msal-node
Creación de un objeto de configuración de MSAL
En el editor de código, abra el archivo authConfig.js y agregue el siguiente código:
require('dotenv').config();
/**
* Configuration object to be passed to MSAL instance on creation.
* For a full list of MSAL Node configuration parameters, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
*/
const msalConfig = {
auth: {
clientId: process.env.CLIENT_ID || 'Enter_the_Application_Id_Here', // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
authority: process.env.AUTHORITY || 'https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com/', // Replace "Enter_the_Tenant_Subdomain_Here" with your tenant subdomain
clientSecret: process.env.CLIENT_SECRET || 'Enter_the_Client_Secret_Here', // Client secret generated from the app
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: 'Info',
},
},
};
const protectedResources = {
apiToDoList: {
endpoint: process.env.API_ENDPOINT || 'https://localhost:44351/api/todolist',
scopes: [process.env.SCOPES || 'api://Enter_the_Web_Api_Application_Id_Here'],
},
};
module.exports = {
msalConfig,
protectedResources,
};
El objeto msalConfig
contiene un conjunto de opciones de configuración que se usan para personalizar el comportamiento de los flujos de autorización.
En el archivo authConfig.js, reemplace:
Enter_the_Application_Id_Here
con el id. de aplicación (cliente) de la aplicación de demonio de cliente que registró anteriormente.Enter_the_Tenant_Subdomain_Here
y reemplácelo por el subdominio Directorio (inquilino). Por ejemplo, si el dominio principal del cliente escontoso.onmicrosoft.com
, utilicecontoso
. Si no tiene el nombre del inquilino, aprenda a leer los detalles del inquilino.Enter_the_Client_Secret_Here
con el valor del secreto de la aplicación de demonio de cliente que copió anteriormente.Enter_the_Web_Api_Application_Id_Here
con el id. de aplicación (cliente) de la aplicación de API web que copió anteriormente.
Observe que la scopes
propiedad de la protectedResources
variable es el identificador de recurso (URI de identificador de aplicación) de la API web que registró como parte de los requisitos previos. El URI de ámbito completo es similar a api://Enter_the_Web_Api_Application_Id_Here/.default
.
Adquisición de un token de acceso
En el editor de código, abra el archivo auth.js y agregue el siguiente código:
const msal = require('@azure/msal-node');
const { msalConfig, protectedResources } = require('./authConfig');
/**
* With client credentials flows permissions need to be granted in the portal by a tenant administrator.
* The scope is always in the format '<resource-appId-uri>/.default'. For more, visit:
* https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
*/
const tokenRequest = {
scopes: [`${protectedResources.apiToDoList.scopes}/.default`],
};
const apiConfig = {
uri: protectedResources.apiToDoList.endpoint,
};
/**
* Initialize a confidential client application. For more info, visit:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/initialize-confidential-client-application.md
*/
const cca = new msal.ConfidentialClientApplication(msalConfig);
/**
* Acquires token with client credentials.
* @param {object} tokenRequest
*/
async function getToken(tokenRequest) {
return await cca.acquireTokenByClientCredential(tokenRequest);
}
module.exports = {
apiConfig: apiConfig,
tokenRequest: tokenRequest,
getToken: getToken,
};
En el código:
Prepare el objeto
tokenRequest
yapiConfig
.tokenRequest
contiene el ámbito para el que se solicita un token de acceso. El ámbito tiene un aspecto similar aapi://Enter_the_Web_Api_Application_Id_Here/.default
. El objetoapiConfig
contiene el punto de conexión a la API web. Obtenga más información sobre el flujo de credenciales de cliente de OAuth 2.0.Para crear una instancia de cliente confidencial, pase el objeto
msalConfig
al constructor de la clase ConfidentialClientApplication.const cca = new msal.ConfidentialClientApplication(msalConfig);
A continuación, use la función acquireTokenByClientCredential para adquirir un token de acceso. Esta lógica se implementa en la función
getToken
:cca.acquireTokenByClientCredential(tokenRequest);
Una vez que adquiera un token de acceso, puede continuar con la llamada a una API.
Llamada a una API
En el editor de código, abra el archivo fetch.js y agregue el siguiente código:
const axios = require('axios');
/**
* Calls the endpoint with authorization bearer token.
* @param {string} endpoint
* @param {string} accessToken
*/
async function callApi(endpoint, accessToken) {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`
}
};
console.log('request made to web API at: ' + new Date().toString());
try {
const response = await axios.get(endpoint, options);
return response.data;
} catch (error) {
console.log(error)
return error;
}
};
module.exports = {
callApi: callApi
};
En este código, realizas una llamada a la API web pasando el token de acceso como bearer token en el encabezado de solicitud Authorization
.
Authorization: `Bearer ${accessToken}`
Use el token de acceso que adquirió anteriormente en Adquisición de un token de acceso.
Una vez que la API web recibe la solicitud, la evalúa y, a continuación, determina que es una solicitud de aplicación. Si el token de acceso es válido, la API web devuelve los datos solicitados. De lo contrario, la API devuelve un error HTTP 401 Unauthorized
.
Finalización de la aplicación de demonio
En el editor de código, abra el archivo index.js y agregue el siguiente código:
#!/usr/bin/env node
// read in env settings
require('dotenv').config();
const yargs = require('yargs');
const fetch = require('./fetch');
const auth = require('./auth');
const options = yargs
.usage('Usage: --op <operation_name>')
.option('op', { alias: 'operation', describe: 'operation name', type: 'string', demandOption: true })
.argv;
async function main() {
console.log(`You have selected: ${options.op}`);
switch (yargs.argv['op']) {
case 'getToDos':
try {
const authResponse = await auth.getToken(auth.tokenRequest);
const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);
} catch (error) {
console.log(error);
}
break;
default:
console.log('Select an operation first');
break;
}
};
main();
Este código es el punto de entrada a la aplicación. Use la biblioteca de análisis de argumentos de línea de comandos yargs de JavaScript para aplicaciones Node.js para obtener un token de acceso de manera interactiva y, a continuación, realizar llamadas a la API. Use las funciones getToken
y callApi
que definió anteriormente:
const authResponse = await auth.getToken(auth.tokenRequest);
const todos = await fetch.callApi(auth.apiConfig.uri, authResponse.accessToken);
Ejecución y prueba de la aplicación y la API de demonio
En este momento, está listo para probar la aplicación de demonio cliente y la API web:
Siga los pasos que ha aprendido en el tutorial Protección de una API web de ASP.NET para iniciar la API web. La API web ya está lista para atender solicitudes de cliente. Si no ejecuta su API web en el puerto
44351
especificado en el archivo authConfig.js, asegúrese de actualizar el archivo authConfig.js para utilizar el número de puerto correcto de la API web.En su terminal, asegúrese de que está en la carpeta del proyecto que contiene su aplicación daemon Node.js como
ciam-call-api-node-daemon
, luego ejecuta el siguiente comando:node . --op getToDos
Si su aplicación daemon y la API web se ejecutan correctamente, debería encontrar los datos devueltos por la variable todos
del punto de conexión de la API web, similares a la siguiente matriz JSON, en su ventana de consola:
{
id: 1,
owner: '3e8....-db63-43a2-a767-5d7db...',
description: 'Pick up grocery'
},
{
id: 2,
owner: 'c3cc....-c4ec-4531-a197-cb919ed.....',
description: 'Finish invoice report'
},
{
id: 3,
owner: 'a35e....-3b8a-4632-8c4f-ffb840d.....',
description: 'Water plants'
}